Compare commits
218 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
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
|
|||
|
a76543d7a7
|
|||
|
e6d4cb7e4f
|
|||
|
d567ea4517
|
|||
|
424a4efb7a
|
|||
|
03d863f5e7
|
|||
|
820f770619
|
|||
|
b6d5505c2d
|
|||
|
6af347f5d2
|
|||
|
eb0f7a5a72
|
|||
|
01415e13d5
|
|||
|
9329a3a032
|
|||
|
e857bfee03
|
|||
|
7e71ff5e37
|
|||
|
bc629d6384
|
|||
|
21d1c8bacf
|
|||
|
f086e806df
|
|||
|
fdd9093f49
|
|||
|
7fad9689c6
|
|||
|
2b2795b7dd
|
|||
|
fab2bc636a
|
|||
|
f0237eb488
|
|||
|
1160f43820
|
|||
|
d7b2e338d9
|
|||
|
2d61f8516d
|
|||
|
7c1483184a
|
|||
|
5f03e374d4
|
|||
|
d391676a8e
|
|||
|
25ed3c38e7
|
|||
|
37195341c5
|
|||
|
6f0602f49b
|
|||
|
b163dff842
|
|||
|
|
439b706060 | ||
|
44f7f8c6c2
|
|||
|
075303e9b6
|
|||
|
62da08860d
|
|||
|
a6abfcde90
|
|||
|
9f394e84cb
|
|||
|
e0062d181d
|
|||
|
bc0ed61e1a
|
|||
|
6965d2eaa4
|
|||
|
016751ddbd
|
|||
|
06bf294f8a
|
|||
|
23f2726ff8
|
|||
|
9e54446f44
|
|||
|
811380215a
|
|||
|
b4675dac70
|
|||
|
d4df854820
|
|||
|
94a55d5922
|
|||
|
02f5d5e7d9
|
|||
|
f8ce387f4f
|
|||
|
8e01deba82
|
|||
|
5dbf387bf0
|
|||
|
8a13954718
|
|||
|
a05c4d3684
|
|||
|
a6543fdc28
|
|||
|
23d4d523d6
|
|||
|
b6a8bb2e66
|
|||
|
dea4a21f92
|
|||
|
074fbe67d8
|
|||
|
eee25769c8
|
|||
|
cbef38f970
|
|||
|
03ab50f557
|
|||
|
6b88664db0
|
|||
|
ceafd71461
|
|||
|
614a0a2daf
|
|||
|
e6bde3e0de
|
|||
|
50c724869e
|
|||
|
b595aa09a5
|
|||
|
7e68e55ae6
|
|||
| 1a423d0def | |||
|
|
e107475252 | ||
| 667b260aff | |||
| 4036117d6c | |||
|
|
83ee35b9ae | ||
|
9cca602585
|
|||
|
05944d284e
|
|||
|
b8d6e4f538
|
|||
|
a45541f0b9
|
|||
|
d836665df3
|
|||
|
21cb2a90c8
|
|||
|
|
259f0a1fe1 | ||
|
731ca00390
|
|||
|
c938f7a212
|
|||
|
b11f85caf5
|
|||
|
0e0eefba2b
|
|||
|
06cbd4663c
|
|||
|
a578677137
|
|||
|
e5cecbac54
|
|||
|
42597e0652
|
|||
|
8ccd339d05
|
|||
|
54afd779b3
|
|||
|
f83ef42653
|
|||
|
dc36741c72
|
|||
|
2ec3b6ed19
|
|||
|
77ae969d28
|
|||
|
f8bf7afbe2
|
|||
|
aa61eeec34
|
|||
|
7cdb4b9109
|
|||
|
99c0491cb5
|
|||
|
e889bb37b6
|
|||
|
2db3ea8c62
|
|||
| d54303d0d7 | |||
|
|
f6fa7054bd | ||
|
|
6249d3ad42 | ||
| da241a8c9e | |||
| 525dae72e1 | |||
|
|
6182a1c3d4 | ||
|
|
a00aaa77cf | ||
| 57aa72b355 | |||
| 5ad42e6388 | |||
|
|
d0b2f0a4f4 | ||
|
af90927a84
|
|||
| 5a5c0606a7 | |||
|
|
946469a4db | ||
|
|
5aa8e1ad7e | ||
| b29144be8f | |||
|
c13bb89584
|
|||
|
|
aaed36e18b | ||
|
57f84e4bba
|
|||
|
8983cabd48
|
|||
|
8d856a30bd
|
|||
|
2518424ad1
|
|||
|
f587291d72
|
|||
|
b8dbba7a7e
|
|||
|
7d29ab31ce
|
|||
|
61345f3bcd
|
|||
|
7c21adb843
|
|||
|
dd88789f14
|
|||
|
4d8794d3d0
|
|||
|
aa0028901a
|
|||
|
901a11382d
|
|||
|
9e19d9798f
|
|||
|
97f01942af
|
|||
|
d622de1341
|
|||
|
6e1ed71674
|
|||
|
4ee2e79446
|
|||
|
c70553093d
|
|||
|
57b0d44c7d
|
|||
|
71fad013cf
|
|||
|
d2aee89c21
|
|||
|
544302de6e
|
|||
|
dfdc44b1e3
|
|||
|
05ab495a46
|
|||
|
f5829034a2
|
|||
|
f186dd8030
|
|||
|
ec885559af
|
|||
|
57c4547a66
|
|||
|
f8a90a3e33
|
|||
|
6700d94abb
|
|||
|
577b28cd6d
|
|||
|
f5c767426f
|
|||
|
9a9b18bfbc
|
|||
|
a2aaddb9b2
|
|||
|
eac58e39aa
|
|||
|
6ec3894175
|
|||
|
f8b333af70
|
|||
|
d021aaaea5
|
|||
|
0a892a80ad
|
|||
|
17ecda57fe
|
|||
|
4c0af665d5
|
|||
|
3ef13657cd
|
@@ -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
|
||||||
# #
|
# #
|
||||||
|
|
||||||
|
|||||||
65
.github/workflows/deploy-clean.yml
vendored
@@ -1,15 +1,35 @@
|
|||||||
# #
|
# #
|
||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @desc cleans up the list of deployments in the environment history
|
|
||||||
# edit the 'environment:' to determine which deployment to keep clean
|
|
||||||
# - can be ran manually
|
|
||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage cleans up the list of deployments in the environment history
|
||||||
|
# edit the 'environment:' to determine which deployment to keep clean
|
||||||
|
# - can be ran manually
|
||||||
#
|
#
|
||||||
# @secrets secrets.SELF_TOKEN_CL Github Access Token (Classic)
|
# @secrets secrets.SELF_TOKEN self github personal access token (fine-grained)
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKfLOWS Discord Webbhook URL; right-click on channel, click "Integrations"
|
# 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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/deploy-clean.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/deploy-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "⚙️ Deploy › Clean"
|
name: "⚙️ Deploy › Clean"
|
||||||
@@ -30,10 +50,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
DEPLOYMENT_ENV:
|
DEPLOYMENT_ENV:
|
||||||
description: '📦 Deployment Environment'
|
description: '📦 Deployment Environment'
|
||||||
required: true
|
required: true
|
||||||
default: 'orion'
|
default: 'orion'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Delay
|
# Delay
|
||||||
@@ -42,20 +62,22 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
DEPLOYMENT_DELAY:
|
DEPLOYMENT_DELAY:
|
||||||
description: '🕛 Delete Delay'
|
description: '🕛 Delete Delay'
|
||||||
required: true
|
required: true
|
||||||
default: '1000'
|
default: '1000'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# environment variables
|
# environment variables
|
||||||
# #
|
# #
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEPLOYMENT_ENV: ${{ github.event.inputs.DEPLOYMENT_ENV || 'orion' }}
|
DEPLOYMENT_ENV: ${{ github.event.inputs.DEPLOYMENT_ENV || 'orion' }}
|
||||||
DEPLOYMENT_DELAY: ${{ github.event.inputs.DEPLOYMENT_DELAY || '1000' }}
|
DEPLOYMENT_DELAY: ${{ github.event.inputs.DEPLOYMENT_DELAY || '1000' }}
|
||||||
BOT_NAME_1: EuropaServ
|
BOT_NAME_1: EuropaServ
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[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" },
|
||||||
@@ -128,7 +150,6 @@ jobs:
|
|||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 20
|
timeout-minutes: 20
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -188,7 +209,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Success)
|
🔔 Send Discord Webhook Message (Success)
|
||||||
id: task_cleanup_notify_discord_success
|
id: task_cleanup_notify_discord_success
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -224,7 +245,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Failure)
|
🔔 Send Discord Webhook Message (Failure)
|
||||||
id: task_cleanup_notify_discord_failure
|
id: task_cleanup_notify_discord_failure
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
|
|||||||
1884
.github/workflows/deploy-docker-all.yml
vendored
592
.github/workflows/deploy-docker-dockerhub.yml
vendored
@@ -4,10 +4,31 @@
|
|||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
# @usage deploys docker container to Dockerhub and send message to discord
|
# @usage deploys docker container to Dockerhub and send message to discord
|
||||||
# upload this workflow to both the `main` branch of the tvapp2 repository
|
# upload this workflow to both the `main` branch of the tvapp2 repository
|
||||||
# @secrets secrets.ADMINSERV_GPG_KEY_ASC gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
#
|
||||||
# secrets.ADMINSERV_GPG_PASSPHRASE gpg private key passphrase
|
# @secrets secrets.SELF_TOKEN self github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN github personal access token (classic) with package:write permission
|
# secrets.SELF_TOKEN_CL self github personal access token (classic)
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES Discord webhook to report releases from github to discord
|
# 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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/deploy-docker-dockerhub.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/deploy-docker-dockerhub.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "📦 Deploy › Docker › Dockerhub"
|
name: "📦 Deploy › Docker › Dockerhub"
|
||||||
@@ -36,10 +57,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
IMAGE_NAME:
|
IMAGE_NAME:
|
||||||
description: '📦 Image Name'
|
description: '📦 Image Name'
|
||||||
required: true
|
required: true
|
||||||
default: 'tvapp2'
|
default: 'tvapp2'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Image Version
|
# Image Version
|
||||||
@@ -118,8 +139,11 @@ env:
|
|||||||
IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }}
|
IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }}
|
||||||
IMAGE_DOCKERHUB_AUTHOR: ${{ github.event.inputs.IMAGE_DOCKERHUB_AUTHOR || 'thebinaryninja' }}
|
IMAGE_DOCKERHUB_AUTHOR: ${{ github.event.inputs.IMAGE_DOCKERHUB_AUTHOR || 'thebinaryninja' }}
|
||||||
IMAGE_DOCKERHUB_USERNAME: ${{ github.event.inputs.IMAGE_DOCKERHUB_USERNAME || 'thebinaryninja' }}
|
IMAGE_DOCKERHUB_USERNAME: ${{ github.event.inputs.IMAGE_DOCKERHUB_USERNAME || 'thebinaryninja' }}
|
||||||
|
|
||||||
BOT_NAME_1: EuropaServ
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Jobs
|
# Jobs
|
||||||
@@ -203,282 +227,21 @@ jobs:
|
|||||||
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Docker Release › Dockerhub › Arm64
|
# Job › Docker Release › Dockerhub
|
||||||
# #
|
# #
|
||||||
|
|
||||||
job-docker-release-dockerhub-arm64:
|
job-docker-release-dockerhub:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Dockerhub › Arm64
|
📦 Release › Dockerhub
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
needs: [ job-docker-release-tags-create ]
|
needs: [ job-docker-release-tags-create ]
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Start › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🏳️ Start'
|
|
||||||
id: task_release_dh_start
|
|
||||||
run: |
|
|
||||||
echo "Starting Dockerhub arm64"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Checkout › Amd64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '✅ Checkout'
|
|
||||||
id: task_release_gh_checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Get Timestamp
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🕛 Get Timestamp'
|
|
||||||
id: task_release_set_timestamp
|
|
||||||
run: |
|
|
||||||
echo "DOCKER_IMAGE=`echo ${{github.repository}} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV}
|
|
||||||
echo "DOCKER_SHA=${GITHUB_SHA}" >> $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 › Dockerhub › Install Dependencies
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Install Dependencies'
|
|
||||||
id: task_release_dh_dependencies
|
|
||||||
run:
|
|
||||||
sudo apt-get install -qq dos2unix
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Execute dos2unix
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔐 Apply dos2unix'
|
|
||||||
id: task_release_dh_dos2unix
|
|
||||||
run: |
|
|
||||||
echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️"
|
|
||||||
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
|
||||||
echo "✅✅✅ Completed DOS2UNIX ✅✅✅"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Fix Permissions
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '#️⃣ Manage Permissions'
|
|
||||||
id: task_release_dh_permissions
|
|
||||||
run: |
|
|
||||||
find ./ -name 'run' -exec chmod 755 {} \;
|
|
||||||
WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print)
|
|
||||||
if [ -n "${WRONG_PERM}" ]; then
|
|
||||||
echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️"
|
|
||||||
for i in ${WRONG_PERM}; do
|
|
||||||
echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!"
|
|
||||||
done
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "✅✅✅ Executable permissions are OK ✅✅✅"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › QEMU › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Set up QEMU'
|
|
||||||
id: task_release_dh_qemu
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Setup BuildX › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Setup Buildx'
|
|
||||||
id: task_release_dh_buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
driver-opts: 'image=moby/buildkit:latest'
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Registry Login › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Login to Dockerhub'
|
|
||||||
id: task_release_dh_registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: ${{ env.IMAGE_DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN }}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Meta › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔨 Dockerhub: Meta - Arm64'
|
|
||||||
id: task_release_dh_meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
${{ env.IMAGE_DOCKERHUB_AUTHOR }}/${{ env.IMAGE_NAME }}
|
|
||||||
tags: |
|
|
||||||
# latest no
|
|
||||||
type=raw,value=latest,enable=false
|
|
||||||
|
|
||||||
# tag add arm64
|
|
||||||
# type=raw,enable=true,priority=1000,value=arm64
|
|
||||||
|
|
||||||
# dispatch add x1.x.x-arm64
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-arm64,value=${{ env.IMAGE_VERSION }}
|
|
||||||
|
|
||||||
# dispatch add arm64-development
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-arm64,value=development
|
|
||||||
|
|
||||||
# tag add tag-arm64
|
|
||||||
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-arm64,event=tag
|
|
||||||
|
|
||||||
flavor: |
|
|
||||||
latest=false
|
|
||||||
labels: |
|
|
||||||
org.opencontainers.image.VERSION=${{ env.IMAGE_VERSION }}
|
|
||||||
org.opencontainers.image.BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
|
||||||
org.opencontainers.image.licenses=MIT
|
|
||||||
org.opencontainers.image.revision=${{ github.sha }}
|
|
||||||
org.opencontainers.image.vendor=${{ env.IMAGE_DOCKERHUB_AUTHOR }}
|
|
||||||
org.opencontainers.image.ref.name=${{ env.ref_name }}
|
|
||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Build and Push › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Build & Push (linux/arm64)'
|
|
||||||
id: task_release_dh_push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Dockerfile.aarch64
|
|
||||||
platforms: linux/arm64
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.task_release_dh_meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.task_release_dh_meta.outputs.labels }}
|
|
||||||
provenance: false
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Checkpoint › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚠️ Checkpoint'
|
|
||||||
id: task_release_dh_checkpoint
|
|
||||||
run: |
|
|
||||||
echo "registry ............. Dockerhub"
|
|
||||||
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 "inputs.DRY_RUN ....... ${{ inputs.DRY_RUN }}"
|
|
||||||
echo "env.AUTHOR ........... ${{ env.IMAGE_DOCKERHUB_AUTHOR }}"
|
|
||||||
echo "tags ................. ${{ steps.task_release_dh_meta.outputs.tags }}"
|
|
||||||
echo "labels ............... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
|
||||||
echo "docker image ......... ${{ env.DOCKER_IMAGE }}"
|
|
||||||
echo "docker sha ........... ${{ env.DOCKER_SHA }}"
|
|
||||||
echo "docker image id ...... ${{ steps.task_release_dh_push.outputs.imageid }}"
|
|
||||||
echo "docker digest ........ ${{ steps.task_release_dh_push.outputs.digest }}"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Get Weekly Commits
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🕛 Get Weekly Commit List'
|
|
||||||
id: task_release_set_weekly_commit_list
|
|
||||||
run: |
|
|
||||||
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
|
||||||
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
|
||||||
echo 'EOF' >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Dockerhub › Notify Github
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔔 Send Discord Webhook Message'
|
|
||||||
id: task_release_notifications_discord_send
|
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
|
||||||
if: success()
|
|
||||||
with:
|
|
||||||
username: 'Io'
|
|
||||||
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES }}
|
|
||||||
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: |
|
|
||||||
## 📦 Docker › Deploy (Dockerhub) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
|
||||||
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
|
||||||
|
|
||||||
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Dockerhub. The image is available at:
|
|
||||||
- https://github.com/${{ github.repository }}/pkgs/container/${{ env.IMAGE_NAME }}
|
|
||||||
|
|
||||||
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
|
||||||
- Pull: `docker pull ${{ env.DOCKER_IMAGE }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-amd64`
|
|
||||||
- Pull: `docker pull ${{ env.DOCKER_IMAGE }}@${{ steps.task_release_dh_push.outputs.digest }}`
|
|
||||||
- Dry Run: `${{ inputs.DRY_RUN }}`
|
|
||||||
- Source: `Dockerhub` https://hub.docker.com/r/${{ env.IMAGE_DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}
|
|
||||||
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
|
||||||
- Version: `${{ env.IMAGE_VERSION }}`
|
|
||||||
- Branch: `${{ github.ref_name }}`
|
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
|
||||||
- Runner: `${{ runner.name }}`
|
|
||||||
- Triggered By: `${{ github.actor }}`
|
|
||||||
- Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}`
|
|
||||||
|
|
||||||
### Tags
|
|
||||||
-# This docker image will use the following tags:
|
|
||||||
|
|
||||||
```
|
|
||||||
${{ steps.task_release_dh_meta.outputs.tags }}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Labels
|
|
||||||
-# This docker image embeds the following labels:
|
|
||||||
|
|
||||||
```
|
|
||||||
${{ steps.task_release_dh_meta.outputs.labels }}
|
|
||||||
```
|
|
||||||
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"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Job › Docker Release › Dockerhub › Amd64
|
|
||||||
# #
|
|
||||||
|
|
||||||
job-docker-release-dockerhub-amd64:
|
|
||||||
name: >-
|
|
||||||
📦 Release › Dockerhub › Amd64
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 10
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
needs: [ job-docker-release-tags-create, job-docker-release-dockerhub-arm64 ]
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -507,12 +270,16 @@ jobs:
|
|||||||
- name: '🕛 Get Timestamp'
|
- name: '🕛 Get Timestamp'
|
||||||
id: task_release_set_timestamp
|
id: task_release_set_timestamp
|
||||||
run: |
|
run: |
|
||||||
echo "DOCKER_IMAGE=`echo ${{github.repository}} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV}
|
echo "IMAGE_VERSION_1DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1`" >> ${GITHUB_ENV} # 1
|
||||||
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV
|
echo "IMAGE_VERSION_2DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-2`" >> ${GITHUB_ENV} # 1.0
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "REGISTRY_REPO_ORG_AUTHOR_LC=`echo ${{ env.IMAGE_DOCKERHUB_AUTHOR }}/${{ env.IMAGE_NAME }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja/tvapp2
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo "REGISTRY_REPO_AUTHOR_LC=`echo ${{ env.IMAGE_DOCKERHUB_AUTHOR }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV # 71fad013cfce9116ec62779e4a7e627fe4c33627
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV # 02-25-2025 12:49:48
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV # 02-25-2025
|
||||||
|
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_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Install Dependencies
|
# Release › Dockerhub › Install Dependencies
|
||||||
@@ -530,7 +297,9 @@ jobs:
|
|||||||
- name: '🔐 Apply dos2unix'
|
- name: '🔐 Apply dos2unix'
|
||||||
id: task_release_dh_dos2unix
|
id: task_release_dh_dos2unix
|
||||||
run: |
|
run: |
|
||||||
|
echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️"
|
||||||
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
||||||
|
echo "✅✅✅ Completed DOS2UNIX ✅✅✅"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Fix Permissions
|
# Release › Dockerhub › Fix Permissions
|
||||||
@@ -582,50 +351,93 @@ jobs:
|
|||||||
password: ${{ secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN }}
|
password: ${{ secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Meta › Amd64
|
# Release › Dockerhub › Read Readme
|
||||||
|
#
|
||||||
|
# @usage org.opencontainers.image.description=${{ steps.task_release_dh_readme_cache.outputs.content }}
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔨 Dockerhub: Meta - Amd64'
|
- name: '📄 Cache README.md'
|
||||||
|
id: task_release_dh_readme_cache
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }}
|
||||||
|
script: |
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { promises: fs } = require('fs')
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const path = "README.md"
|
||||||
|
let content = await fs.readFile(path, 'utf8')
|
||||||
|
|
||||||
|
core.setOutput('content', content)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(err => core.setFailed(err.message))
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Dockerhub › Meta
|
||||||
|
#
|
||||||
|
# this version of meta does not need one for amd64 and one for arm64 because both
|
||||||
|
# platforms are combined into one release, all sharing the same tags
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Dockerhub: Meta'
|
||||||
id: task_release_dh_meta
|
id: task_release_dh_meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
${{ env.IMAGE_DOCKERHUB_AUTHOR }}/${{ env.IMAGE_NAME }}
|
${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }}
|
||||||
tags: |
|
tags: |
|
||||||
# latest yes
|
# tag latest = yes ( no dev )
|
||||||
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
||||||
|
|
||||||
# tag add amd64
|
# tag add pr tag ( PR or push only )
|
||||||
# type=raw,enable=true,priority=1000,value=amd64
|
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=,event=tag
|
||||||
|
|
||||||
# dispatch add x1.x.x-amd64
|
# tag add 1.0.0 ( dispatch only + no dev )
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-amd64,value=${{ env.IMAGE_VERSION }}
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=450,prefix=,suffix=,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
# dispatch add amd64-development
|
# tag add 1.0 ( dispatch only + no dev )
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-amd64,value=development
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=425,prefix=,suffix=,value=${{ env.IMAGE_VERSION_2DIGIT }}
|
||||||
|
|
||||||
# tag add tag-arm64
|
# tag add 1 ( dispatch only + no dev )
|
||||||
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-amd64,event=tag
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=400,prefix=,suffix=,value=${{ env.IMAGE_VERSION_1DIGIT }}
|
||||||
|
|
||||||
# add development tag to default architecture (amd64)
|
# tag add development ( dispatch only + only dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=,value=development
|
||||||
|
|
||||||
|
# tag add development ( amd64 + only dev )
|
||||||
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=${{ !inputs.DEV_RELEASE }}
|
latest=false
|
||||||
labels: |
|
labels: |
|
||||||
org.opencontainers.image.VERSION=${{ env.IMAGE_VERSION }}
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
org.opencontainers.image.BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
org.opencontainers.image.licenses=MIT
|
org.opencontainers.image.licenses=MIT
|
||||||
org.opencontainers.image.revision=${{ github.sha }}
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
org.opencontainers.image.vendor=${{ env.IMAGE_DOCKERHUB_AUTHOR }}
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
org.opencontainers.image.ref.name=${{ env.ref_name }}
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
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.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.opencontainers.image.registry=dockerhub
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Build and Push › Amd64
|
# Release › Dockerhub › Build and Push › Amd64
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '📦 Build & Push (linux/amd64)'
|
- name: '📦 Build & Push (linux/amd64)'
|
||||||
id: task_release_dh_push
|
id: task_release_dh_push_amd64
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
with:
|
with:
|
||||||
@@ -633,9 +445,110 @@ jobs:
|
|||||||
file: Dockerfile
|
file: Dockerfile
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.task_release_dh_meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.task_release_dh_meta.outputs.labels }}
|
labels: ${{ steps.task_release_dh_meta.outputs.labels }}
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_dh_meta.outputs.tags }}
|
||||||
provenance: false
|
provenance: false
|
||||||
|
sbom: false
|
||||||
|
build-args: |-
|
||||||
|
ARCH=amd64
|
||||||
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Dockerhub › Export Digest › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📄 Export Digest (linux/amd64)'
|
||||||
|
id: task_release_dh_digest_export_amd64
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/build-digest-amd64
|
||||||
|
digest="${{ steps.task_release_dh_push_amd64.outputs.digest }}"
|
||||||
|
digest="${digest#sha256:}"
|
||||||
|
touch "/tmp/build-digest-amd64/$digest"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Dockerhub › Upload Digest › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔼 Upload Digest (linux/amd64)'
|
||||||
|
id: task_release_dh_digest_upload_amd64
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
name: digest-amd64
|
||||||
|
path: /tmp/build-digest-amd64/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 10
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Dockerhub › Build and Push › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Build & Push (linux/arm64)'
|
||||||
|
id: task_release_dh_push_arm64
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: Dockerfile
|
||||||
|
platforms: linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
labels: ${{ steps.task_release_dh_meta.outputs.labels }}
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_dh_meta.outputs.tags }}
|
||||||
|
provenance: false
|
||||||
|
sbom: false
|
||||||
|
build-args: |-
|
||||||
|
ARCH=arm64
|
||||||
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Dockerhub › Export Digest › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📄 Export Digest (linux/arm64)'
|
||||||
|
id: task_release_dh_digest_export_arm64
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/build-digest-arm64
|
||||||
|
digest="${{ steps.task_release_dh_push_arm64.outputs.digest }}"
|
||||||
|
digest="${digest#sha256:}"
|
||||||
|
touch "/tmp/build-digest-arm64/$digest"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Dockerhub › Upload Digest › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔼 Upload Digest (linux/arm64)'
|
||||||
|
id: task_release_dh_digest_upload_arm64
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
name: digest-arm64
|
||||||
|
path: /tmp/build-digest-arm64/*
|
||||||
|
if-no-files-found: error
|
||||||
|
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
|
||||||
@@ -644,19 +557,53 @@ jobs:
|
|||||||
- name: '⚠️ Checkpoint'
|
- name: '⚠️ Checkpoint'
|
||||||
id: task_release_dh_checkpoint
|
id: task_release_dh_checkpoint
|
||||||
run: |
|
run: |
|
||||||
echo "registry ............. Dockerhub"
|
echo ""
|
||||||
echo "github.actor.......... ${{ github.actor }}"
|
echo "[ GITHUB ] ---------------------------------------------------------------------------------------------"
|
||||||
echo "github.ref ........... ${{ github.ref }}"
|
echo "github.actor.............................. ${{ github.actor }}"
|
||||||
echo "github.ref_name ...... ${{ github.ref_name }}"
|
echo "github.ref ............................... ${{ github.ref }}"
|
||||||
echo "github.event_name .... ${{ github.event_name }}"
|
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
||||||
echo "inputs.DRY_RUN ....... ${{ inputs.DRY_RUN }}"
|
echo "github.event_name ........................ ${{ github.event_name }}"
|
||||||
echo "env.AUTHOR ........... ${{ env.IMAGE_DOCKERHUB_AUTHOR }}"
|
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
||||||
echo "tags ................. ${{ steps.task_release_dh_meta.outputs.tags }}"
|
echo "github.repository ........................ ${{ github.repository }}"
|
||||||
echo "labels ............... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
echo ""
|
||||||
echo "docker image ......... ${{ env.DOCKER_IMAGE }}"
|
echo "[ INPUTS ] ---------------------------------------------------------------------------------------------"
|
||||||
echo "docker sha ........... ${{ env.DOCKER_SHA }}"
|
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
||||||
echo "docker image id ...... ${{ steps.task_release_dh_push.outputs.imageid }}"
|
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
||||||
echo "docker digest ........ ${{ steps.task_release_dh_push.outputs.digest }}"
|
echo "inputs.IMAGE_DOCKERHUB_AUTHOR ............ ${{ inputs.IMAGE_DOCKERHUB_AUTHOR }}"
|
||||||
|
echo "inputs.IMAGE_DOCKERHUB_USERNAME .......... ${{ inputs.IMAGE_DOCKERHUB_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_DOCKERHUB_AUTHOR ............... ${{ env.IMAGE_DOCKERHUB_AUTHOR }}"
|
||||||
|
echo "env.IMAGE_DOCKERHUB_USERNAME ............. ${{ env.IMAGE_DOCKERHUB_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 ""
|
||||||
|
echo "[ DOCKER IMAGES ] --------------------------------------------------------------------------------------"
|
||||||
|
echo "registry ................................. Dockerhub"
|
||||||
|
echo "tags ..................................... ${{ steps.task_release_dh_meta.outputs.tags }}"
|
||||||
|
echo "labels ................................... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
||||||
|
echo "digest ................................... ${{ steps.task_release_dh_push_amd64.outputs.digest }}"
|
||||||
|
echo ""
|
||||||
|
echo "(release) tags ........................... ${{ steps.task_release_dh_meta.outputs.tags }}"
|
||||||
|
echo "(release) labels ......................... ${{ steps.task_release_dh_meta.outputs.labels }}"
|
||||||
|
echo ""
|
||||||
|
echo "[ DOCKER DIGESTS ] -------------------------------------------------------------------------------------"
|
||||||
|
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 image id (arm64) .................. ${{ steps.task_release_dh_push_arm64.outputs.imageid }}"
|
||||||
|
echo "docker digest (arm64) .................... ${{ steps.task_release_dh_push_arm64.outputs.digest }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Dockerhub › Get Weekly Commits
|
# Release › Dockerhub › Get Weekly Commits
|
||||||
@@ -674,7 +621,7 @@ jobs:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔔 Send Discord Webhook Message'
|
- name: '🔔 Send Discord Webhook Message'
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -684,19 +631,20 @@ jobs:
|
|||||||
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'
|
||||||
embed-description: |
|
embed-description: |
|
||||||
## 📦 Docker › Deploy (Dockerhub) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
### 📦 Deploy (Dockerhub) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
||||||
|
|
||||||
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Dockerhub. The image is available at:
|
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Dockerhub. The image is available at:
|
||||||
- https://github.com/${{ github.repository }}/pkgs/container/${{ env.IMAGE_NAME }}
|
- https://hub.docker.com/r/${{ env.IMAGE_DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}
|
||||||
|
|
||||||
|
- Version: `${{ env.IMAGE_VERSION }}`
|
||||||
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
||||||
- Pull: `docker pull ${{ env.DOCKER_IMAGE }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-amd64`
|
- Pull: `docker pull ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}`
|
||||||
- Pull: `docker pull ${{ env.DOCKER_IMAGE }}@${{ steps.task_release_dh_push.outputs.digest }}`
|
- Pull (amd64): `docker pull ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_dh_push_amd64.outputs.digest }}`
|
||||||
|
- Pull (arm64): `docker pull ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_dh_push_arm64.outputs.digest }}`
|
||||||
- Dry Run: `${{ inputs.DRY_RUN }}`
|
- Dry Run: `${{ inputs.DRY_RUN }}`
|
||||||
- Source: `Dockerhub` https://hub.docker.com/r/${{ env.IMAGE_DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}
|
- Source: `Dockerhub` https://hub.docker.com/r/${{ env.IMAGE_DOCKERHUB_USERNAME }}/${{ env.IMAGE_NAME }}
|
||||||
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
- Version: `${{ env.IMAGE_VERSION }}`
|
|
||||||
- Branch: `${{ github.ref_name }}`
|
- Branch: `${{ github.ref_name }}`
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
||||||
- Runner: `${{ runner.name }}`
|
- Runner: `${{ runner.name }}`
|
||||||
|
|||||||
772
.github/workflows/deploy-docker-gitea.yml
vendored
@@ -4,10 +4,31 @@
|
|||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
# @usage deploys docker container to Gitea and send message to discord
|
# @usage deploys docker container to Gitea and send message to discord
|
||||||
# upload this workflow to both the `main` branch of the tvapp2 repository
|
# upload this workflow to both the `main` branch of the tvapp2 repository
|
||||||
# @secrets secrets.ADMINSERV_GPG_KEY_ASC gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
#
|
||||||
# secrets.ADMINSERV_GPG_PASSPHRASE gpg private key passphrase
|
# @secrets secrets.SELF_TOKEN self github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_GITEA_TOKEN gitea personal access token (classic) with package:write permission
|
# secrets.SELF_TOKEN_CL self github personal access token (classic)
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES Discord webhook to report releases from gitea to discord
|
# 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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/deploy-docker-gitea.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/deploy-docker-gitea.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "📦 Deploy › Docker › Gitea"
|
name: "📦 Deploy › Docker › Gitea"
|
||||||
@@ -36,10 +57,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
IMAGE_NAME:
|
IMAGE_NAME:
|
||||||
description: '📦 Image Name'
|
description: '📦 Image Name'
|
||||||
required: true
|
required: true
|
||||||
default: 'tvapp2'
|
default: 'tvapp2'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Image Version
|
# Image Version
|
||||||
@@ -48,10 +69,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
IMAGE_VERSION:
|
IMAGE_VERSION:
|
||||||
description: '🏷️ Image Version'
|
description: '🏷️ Image Version'
|
||||||
required: true
|
required: true
|
||||||
default: '1.0.0'
|
default: '1.0.0'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Gitea › Author
|
# Gitea › Author
|
||||||
@@ -61,10 +82,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
IMAGE_GITEA_AUTHOR:
|
IMAGE_GITEA_AUTHOR:
|
||||||
description: '🪪 Image Author'
|
description: '🪪 Image Author'
|
||||||
required: true
|
required: true
|
||||||
default: 'BinaryNinja'
|
default: 'BinaryNinja'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Gitea › Username
|
# Gitea › Username
|
||||||
@@ -78,6 +99,18 @@ on:
|
|||||||
default: 'aetherinox'
|
default: 'aetherinox'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Gitea › Website
|
||||||
|
#
|
||||||
|
# this is the gitea website / url to push to
|
||||||
|
# #
|
||||||
|
|
||||||
|
IMAGE_GITEA_WEBSITE:
|
||||||
|
description: '🌎 Gitea Website'
|
||||||
|
required: true
|
||||||
|
default: 'git.binaryninja.net'
|
||||||
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# true no changes to the repo will be made
|
# true no changes to the repo will be made
|
||||||
# false workflow will behave normally, and push any changes detected to the files
|
# false workflow will behave normally, and push any changes detected to the files
|
||||||
@@ -113,12 +146,16 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE_NAME: ${{ github.event.inputs.IMAGE_NAME || 'tvapp2' }}
|
IMAGE_NAME: ${{ github.event.inputs.IMAGE_NAME || 'tvapp2' }}
|
||||||
IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }}
|
IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }}
|
||||||
IMAGE_GITEA_AUTHOR: ${{ github.event.inputs.IMAGE_GITEA_AUTHOR || 'BinaryNinja' }}
|
IMAGE_GITEA_AUTHOR: ${{ github.event.inputs.IMAGE_GITEA_AUTHOR || 'BinaryNinja' }}
|
||||||
IMAGE_GITEA_USERNAME: ${{ github.event.inputs.IMAGE_GITEA_USERNAME || 'BinaryNinja' }}
|
IMAGE_GITEA_USERNAME: ${{ github.event.inputs.IMAGE_GITEA_USERNAME || 'BinaryNinja' }}
|
||||||
BOT_NAME_1: EuropaServ
|
IMAGE_GITEA_WEBSITE: ${{ github.event.inputs.IMAGE_GITEA_WEBSITE || 'git.binaryninja.net' }}
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
|
||||||
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Jobs
|
# Jobs
|
||||||
@@ -202,282 +239,21 @@ jobs:
|
|||||||
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Docker Release › Gitea › Arm64
|
# Job › Docker Release › Gitea
|
||||||
# #
|
# #
|
||||||
|
|
||||||
job-docker-release-gitea-arm64:
|
job-docker-release-gitea:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Gitea › Arm64
|
📦 Release › Gitea
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
needs: [ job-docker-release-tags-create ]
|
needs: [ job-docker-release-tags-create ]
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Start › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🏳️ Start'
|
|
||||||
id: task_release_gi_start
|
|
||||||
run: |
|
|
||||||
echo "Starting Gitea Docker arm64"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Checkout › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '✅ Checkout'
|
|
||||||
id: task_release_gh_checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Get Timestamp
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🕛 Get Timestamp'
|
|
||||||
id: task_release_set_timestamp
|
|
||||||
run: |
|
|
||||||
echo "DOCKER_IMAGE=`echo ${{github.repository}} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV}
|
|
||||||
echo "DOCKER_SHA=${GITHUB_SHA}" >> $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 › Gitea › Install Dependencies
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Install Dependencies'
|
|
||||||
id: task_release_gi_dependencies
|
|
||||||
run:
|
|
||||||
sudo apt-get install -qq dos2unix
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Execute dos2unix
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔐 Apply dos2unix'
|
|
||||||
id: task_release_gi_dos2unix
|
|
||||||
run: |
|
|
||||||
echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️"
|
|
||||||
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
|
||||||
echo "✅✅✅ Completed DOS2UNIX ✅✅✅"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Fix Permissions
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '#️⃣ Manage Permissions'
|
|
||||||
id: task_release_gi_permissions
|
|
||||||
run: |
|
|
||||||
find ./ -name 'run' -exec chmod 755 {} \;
|
|
||||||
WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print)
|
|
||||||
if [ -n "${WRONG_PERM}" ]; then
|
|
||||||
echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️"
|
|
||||||
for i in ${WRONG_PERM}; do
|
|
||||||
echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!"
|
|
||||||
done
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "✅✅✅ Executable permissions are OK ✅✅✅"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › QEMU › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Set up QEMU'
|
|
||||||
id: task_release_gi_qemu
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Setup BuildX › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Setup Buildx'
|
|
||||||
id: task_release_gi_buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
driver-opts: 'image=moby/buildkit:latest'
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Registry Login › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Login to Gitea'
|
|
||||||
id: task_release_gi_registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: git.binaryninja.net
|
|
||||||
username: ${{ env.IMAGE_GITEA_USERNAME }}
|
|
||||||
password: ${{ secrets.ORG_BINARYNINJA_GITEA_TOKEN }}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Meta › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔨 Gitea: Meta - Arm64'
|
|
||||||
id: task_release_gi_meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
git.binaryninja.net/${{ env.IMAGE_GITEA_AUTHOR }}/${{ env.IMAGE_NAME }}
|
|
||||||
tags: |
|
|
||||||
# latest no
|
|
||||||
type=raw,value=latest,enable=false
|
|
||||||
|
|
||||||
# tag add arm64
|
|
||||||
# type=raw,enable=true,priority=1000,value=arm64
|
|
||||||
|
|
||||||
# dispatch add x1.x.x-arm64
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-arm64,value=${{ env.IMAGE_VERSION }}
|
|
||||||
|
|
||||||
# dispatch add arm64-development
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-arm64,value=development
|
|
||||||
|
|
||||||
# tag add tag-arm64
|
|
||||||
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-arm64,event=tag
|
|
||||||
flavor: |
|
|
||||||
latest=false
|
|
||||||
labels: |
|
|
||||||
org.opencontainers.image.VERSION=${{ env.IMAGE_VERSION }}
|
|
||||||
org.opencontainers.image.BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
|
||||||
org.opencontainers.image.licenses=MIT
|
|
||||||
org.opencontainers.image.revision=${{ github.sha }}
|
|
||||||
org.opencontainers.image.vendor=${{ env.IMAGE_GITEA_AUTHOR }}
|
|
||||||
org.opencontainers.image.ref.name=${{ env.ref_name }}
|
|
||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Build and Push › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Build & Push (linux/arm64)'
|
|
||||||
id: task_release_gi_push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Dockerfile.aarch64
|
|
||||||
platforms: linux/arm64
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.task_release_gi_meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.task_release_gi_meta.outputs.labels }}
|
|
||||||
provenance: false
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Checkpoint › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚠️ Checkpoint'
|
|
||||||
id: task_release_gi_checkpoint
|
|
||||||
run: |
|
|
||||||
echo "registry ............. Gitea"
|
|
||||||
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 "inputs.DRY_RUN ....... ${{ inputs.DRY_RUN }}"
|
|
||||||
echo "env.AUTHOR ........... ${{ env.IMAGE_GITEA_AUTHOR }}"
|
|
||||||
echo "tags ................. ${{ steps.task_release_gi_meta.outputs.tags }}"
|
|
||||||
echo "labels ............... ${{ steps.task_release_gi_meta.outputs.labels }}"
|
|
||||||
echo "docker image ......... ${{ env.DOCKER_IMAGE }}"
|
|
||||||
echo "docker sha ........... ${{ env.DOCKER_SHA }}"
|
|
||||||
echo "docker image id ...... ${{ steps.task_release_gi_push.outputs.imageid }}"
|
|
||||||
echo "docker digest ........ ${{ steps.task_release_gi_push.outputs.digest }}"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Get Weekly Commits
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🕛 Get Weekly Commit List'
|
|
||||||
id: task_release_set_weekly_commit_list
|
|
||||||
run: |
|
|
||||||
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
|
||||||
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
|
||||||
echo 'EOF' >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Gitea › Notify Gitea
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔔 Send Discord Webhook Message'
|
|
||||||
id: task_release_notifications_discord_send
|
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
|
||||||
if: success()
|
|
||||||
with:
|
|
||||||
username: 'Io'
|
|
||||||
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES }}
|
|
||||||
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: |
|
|
||||||
## 📦 Docker › Deploy (Gitea) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
|
||||||
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
|
||||||
|
|
||||||
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Gitea. The image is available at:
|
|
||||||
- https://git.binaryninja.net/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
|
||||||
|
|
||||||
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
|
||||||
- Pull: `docker pull git.binaryninja.net/${{ env.DOCKER_IMAGE }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-arm64`
|
|
||||||
- Pull: `docker pull git.binaryninja.net/${{ env.DOCKER_IMAGE }}@${{ steps.task_release_gi_push.outputs.digest }}`
|
|
||||||
- Dry Run: `${{ inputs.DRY_RUN }}`
|
|
||||||
- Source: `Gitea` https://git.binaryninja.net/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
|
||||||
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
|
||||||
- Version: `${{ env.IMAGE_VERSION }}`
|
|
||||||
- Branch: `${{ github.ref_name }}`
|
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
|
||||||
- Runner: `${{ runner.name }}`
|
|
||||||
- Triggered By: `${{ github.actor }}`
|
|
||||||
- Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}`
|
|
||||||
|
|
||||||
### Tags
|
|
||||||
-# This docker image will use the following tags:
|
|
||||||
|
|
||||||
```
|
|
||||||
${{ steps.task_release_gi_meta.outputs.tags }}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Labels
|
|
||||||
-# This docker image embeds the following labels:
|
|
||||||
|
|
||||||
```
|
|
||||||
${{ steps.task_release_gi_meta.outputs.labels }}
|
|
||||||
```
|
|
||||||
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"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Job › Docker Release › Gitea › Amd64
|
|
||||||
# #
|
|
||||||
|
|
||||||
job-docker-release-gitea-amd64:
|
|
||||||
name: >-
|
|
||||||
📦 Release › Gitea › Amd64
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 10
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
needs: [ job-docker-release-tags-create, job-docker-release-gitea-arm64 ]
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -506,12 +282,16 @@ jobs:
|
|||||||
- name: '🕛 Get Timestamp'
|
- name: '🕛 Get Timestamp'
|
||||||
id: task_release_set_timestamp
|
id: task_release_set_timestamp
|
||||||
run: |
|
run: |
|
||||||
echo "DOCKER_IMAGE=`echo ${{github.repository}} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV}
|
echo "IMAGE_VERSION_1DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1`" >> ${GITHUB_ENV} # 1
|
||||||
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV
|
echo "IMAGE_VERSION_2DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-2`" >> ${GITHUB_ENV} # 1.0
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "REGISTRY_REPO_ORG_AUTHOR_LC=`echo ${{ env.IMAGE_GITEA_AUTHOR }}/${{ env.IMAGE_NAME }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja/tvapp2
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo "REGISTRY_REPO_AUTHOR_LC=`echo ${{ env.IMAGE_GITEA_AUTHOR }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV # 71fad013cfce9116ec62779e4a7e627fe4c33627
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV # 02-25-2025 12:49:48
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV # 02-25-2025
|
||||||
|
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_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Install Dependencies
|
# Release › Gitea › Install Dependencies
|
||||||
@@ -529,7 +309,9 @@ jobs:
|
|||||||
- name: '🔐 Apply dos2unix'
|
- name: '🔐 Apply dos2unix'
|
||||||
id: task_release_gi_dos2unix
|
id: task_release_gi_dos2unix
|
||||||
run: |
|
run: |
|
||||||
|
echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️"
|
||||||
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
||||||
|
echo "✅✅✅ Completed DOS2UNIX ✅✅✅"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Fix Permissions
|
# Release › Gitea › Fix Permissions
|
||||||
@@ -577,55 +359,209 @@ jobs:
|
|||||||
id: task_release_gi_registry
|
id: task_release_gi_registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: git.binaryninja.net
|
registry: ${{ env.IMAGE_GITEA_WEBSITE }}
|
||||||
username: ${{ env.IMAGE_GITEA_USERNAME }}
|
username: ${{ env.IMAGE_GITEA_USERNAME }}
|
||||||
password: ${{ secrets.ORG_BINARYNINJA_GITEA_TOKEN }}
|
password: ${{ secrets.ORG_BINARYNINJA_GITEA_TOKEN }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Meta › Amd64
|
# Release › Gitea › Read Readme
|
||||||
|
#
|
||||||
|
# @usage org.opencontainers.image.description=${{ steps.task_release_gi_readme_cache.outputs.content }}
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔨 Gitea: Meta - Amd64'
|
- name: '📄 Cache README.md'
|
||||||
id: task_release_gi_meta
|
id: task_release_gi_readme_cache
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }}
|
||||||
|
script: |
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { promises: fs } = require('fs')
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const path = "README.md"
|
||||||
|
let content = await fs.readFile(path, 'utf8')
|
||||||
|
|
||||||
|
core.setOutput('content', content)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(err => core.setFailed(err.message))
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Meta › amd64
|
||||||
|
#
|
||||||
|
# this version of meta needs one entry for amd64 and one for arm64 because each
|
||||||
|
# image needs to be uploaded manually, and then merged into a single platform.
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Gitea: Meta › amd64'
|
||||||
|
id: task_release_gi_meta_amd64
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
git.binaryninja.net/${{ env.IMAGE_GITEA_AUTHOR }}/${{ env.IMAGE_NAME }}
|
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }}
|
||||||
tags: |
|
tags: |
|
||||||
# latest yes
|
# tag latest = yes ( no dev )
|
||||||
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
||||||
|
|
||||||
# tag add amd64
|
# tag add tag-amd64 ( PR or push only )
|
||||||
# type=raw,enable=true,priority=1000,value=amd64
|
|
||||||
|
|
||||||
# dispatch add x1.x.x-amd64
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-amd64,value=${{ env.IMAGE_VERSION }}
|
|
||||||
|
|
||||||
# dispatch add amd64-development
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-amd64,value=development
|
|
||||||
|
|
||||||
# tag add tag-amd64
|
|
||||||
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-amd64,event=tag
|
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-amd64,event=tag
|
||||||
|
|
||||||
# add development tag to default architecture (amd64)
|
# tag add 1.0.0-amd64 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=500,prefix=,suffix=-amd64,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
|
# tag add 1.0.0 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=450,prefix=,suffix=,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
|
# tag add 1.0 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=425,prefix=,suffix=,value=${{ env.IMAGE_VERSION_2DIGIT }}
|
||||||
|
|
||||||
|
# tag add 1 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=400,prefix=,suffix=,value=${{ env.IMAGE_VERSION_1DIGIT }}
|
||||||
|
|
||||||
|
# dispatch add development-amd64 ( dispatch only + only dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=development-,suffix=,value=amd64
|
||||||
|
|
||||||
|
# tag add development ( amd64 + only dev )
|
||||||
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=${{ !inputs.DEV_RELEASE }}
|
latest=false
|
||||||
labels: |
|
labels: |
|
||||||
org.opencontainers.image.VERSION=${{ env.IMAGE_VERSION }}
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
org.opencontainers.image.BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
org.opencontainers.image.licenses=MIT
|
org.opencontainers.image.licenses=MIT
|
||||||
org.opencontainers.image.revision=${{ github.sha }}
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
org.opencontainers.image.vendor=${{ env.IMAGE_GITEA_AUTHOR }}
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
org.opencontainers.image.ref.name=${{ env.ref_name }}
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
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.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.opencontainers.image.registry=gitea
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Meta › arm64
|
||||||
|
#
|
||||||
|
# this version of meta needs one entry for amd64 and one for arm64 because each
|
||||||
|
# image needs to be uploaded manually, and then merged into a single platform.
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Gitea: Meta › arm64'
|
||||||
|
id: task_release_gi_meta_arm64
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
# tag latest = no
|
||||||
|
type=raw,value=latest,enable=false
|
||||||
|
|
||||||
|
# tag add tag-arm64
|
||||||
|
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-arm64,event=tag
|
||||||
|
|
||||||
|
# tag add 1.0.0-arm64 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=500,prefix=,suffix=-arm64,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
|
# dispatch add development-arm64 ( dispatch only + only dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-arm64,value=development
|
||||||
|
flavor: |
|
||||||
|
latest=false
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.opencontainers.image.registry=gitea
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.opencontainers.image.registry=gitea
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Meta › Release
|
||||||
|
#
|
||||||
|
# this version of meta needs one entry for amd64 and one for arm64 because each
|
||||||
|
# image needs to be uploaded manually, and then merged into a single platform.
|
||||||
|
#
|
||||||
|
# this meta action is for the final image; which has both platforms merged and
|
||||||
|
# will be the final release.
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Gitea: Meta › Release'
|
||||||
|
id: task_release_gi_meta_release
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
# tag latest = yes ( no dev )
|
||||||
|
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
||||||
|
|
||||||
|
# tag add pr tag ( PR or push only )
|
||||||
|
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=,event=tag
|
||||||
|
|
||||||
|
# tag add 1.0.0 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=450,prefix=,suffix=,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
|
# tag add 1.0 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=425,prefix=,suffix=,value=${{ env.IMAGE_VERSION_2DIGIT }}
|
||||||
|
|
||||||
|
# tag add 1 ( dispatch only + no dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=400,prefix=,suffix=,value=${{ env.IMAGE_VERSION_1DIGIT }}
|
||||||
|
|
||||||
|
# tag add development ( dispatch only + only dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=,value=development
|
||||||
|
|
||||||
|
# tag add development ( amd64 + only dev )
|
||||||
|
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
||||||
|
flavor: |
|
||||||
|
latest=false
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.opencontainers.image.registry=gitea
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.opencontainers.image.registry=gitea
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Build and Push › Amd64
|
# Release › Gitea › Build and Push › Amd64
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '📦 Build & Push (linux/amd64)'
|
- name: '📦 Build & Push (linux/amd64)'
|
||||||
id: task_release_gi_push
|
id: task_release_gi_push_amd64
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
with:
|
with:
|
||||||
@@ -633,30 +569,171 @@ jobs:
|
|||||||
file: Dockerfile
|
file: Dockerfile
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.task_release_gi_meta.outputs.tags }}
|
labels: ${{ steps.task_release_gi_meta_amd64.outputs.labels }}
|
||||||
labels: ${{ steps.task_release_gi_meta.outputs.labels }}
|
tags: |
|
||||||
|
${{ steps.task_release_gi_meta_amd64.outputs.tags }}
|
||||||
provenance: false
|
provenance: false
|
||||||
|
sbom: false
|
||||||
|
build-args: |-
|
||||||
|
ARCH=amd64
|
||||||
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Checkpoint › Amd64
|
# Release › Gitea › Export Digest › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📄 Export Digest (linux/amd64)'
|
||||||
|
id: task_release_gi_digest_export_amd64
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/build-digest-amd64
|
||||||
|
digest="${{ steps.task_release_gi_push_amd64.outputs.digest }}"
|
||||||
|
digest="${digest#sha256:}"
|
||||||
|
touch "/tmp/build-digest-amd64/$digest"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Upload Digest › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔼 Upload Digest (linux/amd64)'
|
||||||
|
id: task_release_gi_digest_upload_amd64
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
name: digest-amd64
|
||||||
|
path: /tmp/build-digest-amd64/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 10
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Build and Push › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Build & Push (linux/arm64)'
|
||||||
|
id: task_release_gi_push_arm64
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: Dockerfile
|
||||||
|
platforms: linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
labels: ${{ steps.task_release_gi_meta_arm64.outputs.labels }}
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_gi_meta_arm64.outputs.tags }}
|
||||||
|
provenance: false
|
||||||
|
sbom: false
|
||||||
|
build-args: |-
|
||||||
|
ARCH=arm64
|
||||||
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Export Digest › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📄 Export Digest (linux/arm64)'
|
||||||
|
id: task_release_gi_digest_export_arm64
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/build-digest-arm64
|
||||||
|
digest="${{ steps.task_release_gi_push_arm64.outputs.digest }}"
|
||||||
|
digest="${digest#sha256:}"
|
||||||
|
touch "/tmp/build-digest-arm64/$digest"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Upload Digest › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔼 Upload Digest (linux/arm64)'
|
||||||
|
id: task_release_gi_digest_upload_arm64
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
name: digest-arm64
|
||||||
|
path: /tmp/build-digest-arm64/*
|
||||||
|
if-no-files-found: error
|
||||||
|
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
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '⚠️ Checkpoint'
|
- name: '⚠️ Checkpoint'
|
||||||
id: task_release_gi_checkpoint
|
id: task_release_gi_checkpoint
|
||||||
run: |
|
run: |
|
||||||
echo "registry ............. Gitea"
|
echo ""
|
||||||
echo "github.actor.......... ${{ github.actor }}"
|
echo "[ GITHUB ] ---------------------------------------------------------------------------------------------"
|
||||||
echo "github.ref ........... ${{ github.ref }}"
|
echo "github.actor.............................. ${{ github.actor }}"
|
||||||
echo "github.ref_name ...... ${{ github.ref_name }}"
|
echo "github.ref ............................... ${{ github.ref }}"
|
||||||
echo "github.event_name .... ${{ github.event_name }}"
|
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
||||||
echo "inputs.DRY_RUN ....... ${{ inputs.DRY_RUN }}"
|
echo "github.event_name ........................ ${{ github.event_name }}"
|
||||||
echo "env.AUTHOR ........... ${{ env.IMAGE_GITEA_AUTHOR }}"
|
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
||||||
echo "tags ................. ${{ steps.task_release_gi_meta.outputs.tags }}"
|
echo "github.repository ........................ ${{ github.repository }}"
|
||||||
echo "labels ............... ${{ steps.task_release_gi_meta.outputs.labels }}"
|
echo ""
|
||||||
echo "docker image ......... ${{ env.DOCKER_IMAGE }}"
|
echo "[ INPUTS ] ---------------------------------------------------------------------------------------------"
|
||||||
echo "docker sha ........... ${{ env.DOCKER_SHA }}"
|
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
||||||
echo "docker image id ...... ${{ steps.task_release_gi_push.outputs.imageid }}"
|
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
||||||
echo "docker digest ........ ${{ steps.task_release_gi_push.outputs.digest }}"
|
echo "inputs.IMAGE_GITEA_USERNAME .............. ${{ inputs.IMAGE_GITEA_AUTHOR }}"
|
||||||
|
echo "inputs.IMAGE_GITEA_USERNAME .............. ${{ inputs.IMAGE_GITEA_USERNAME }}"
|
||||||
|
echo "inputs.IMAGE_GITEA_WEBSITE ............... ${{ inputs.IMAGE_GITEA_WEBSITE }}"
|
||||||
|
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_GITEA_AUTHOR ................... ${{ env.IMAGE_GITEA_AUTHOR }}"
|
||||||
|
echo "env.IMAGE_GITEA_USERNAME ................. ${{ env.IMAGE_GITEA_USERNAME }}"
|
||||||
|
echo "env.IMAGE_GITEA_WEBSITE .................. ${{ env.IMAGE_GITEA_WEBSITE }}"
|
||||||
|
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 ""
|
||||||
|
echo "[ DOCKER IMAGES ] --------------------------------------------------------------------------------------"
|
||||||
|
echo "registry ................................. Gitea"
|
||||||
|
echo "(amd64) tags ............................. ${{ steps.task_release_gi_meta_amd64.outputs.tags }}"
|
||||||
|
echo "(amd64) labels ........................... ${{ steps.task_release_gi_meta_amd64.outputs.labels }}"
|
||||||
|
echo "(amd64) digest ........................... ${{ steps.task_release_gi_push_amd64.outputs.digest }}"
|
||||||
|
echo ""
|
||||||
|
echo "(arm64) tags ............................. ${{ steps.task_release_gi_meta_arm64.outputs.tags }}"
|
||||||
|
echo "(arm64) labels ........................... ${{ steps.task_release_gi_meta_arm64.outputs.labels }}"
|
||||||
|
echo "(arm64) digest ........................... ${{ steps.task_release_gi_push_arm64.outputs.digest }}"
|
||||||
|
echo ""
|
||||||
|
echo "(release) tags ........................... ${{ steps.task_release_gi_meta_release.outputs.tags }}"
|
||||||
|
echo "(release) labels ......................... ${{ steps.task_release_gi_meta_release.outputs.labels }}"
|
||||||
|
echo ""
|
||||||
|
echo "[ DOCKER DIGESTS ] -------------------------------------------------------------------------------------"
|
||||||
|
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 image id (arm64) .................. ${{ steps.task_release_gi_push_arm64.outputs.imageid }}"
|
||||||
|
echo "docker digest (arm64) .................... ${{ steps.task_release_gi_push_arm64.outputs.digest }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Gitea › Get Weekly Commits
|
# Release › Gitea › Get Weekly Commits
|
||||||
@@ -674,7 +751,7 @@ jobs:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔔 Send Discord Webhook Message'
|
- name: '🔔 Send Discord Webhook Message'
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -684,19 +761,20 @@ jobs:
|
|||||||
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'
|
||||||
embed-description: |
|
embed-description: |
|
||||||
## 📦 Docker › Deploy (Gitea) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
### 📦 Deploy (Gitea) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
||||||
|
|
||||||
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Gitea. The image is available at:
|
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Gitea. The image is available at:
|
||||||
- https://git.binaryninja.net/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
- https://${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
||||||
|
|
||||||
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
|
||||||
- Pull: `docker pull git.binaryninja.net/${{ env.DOCKER_IMAGE }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-amd64`
|
|
||||||
- Pull: `docker pull git.binaryninja.net/${{ env.DOCKER_IMAGE }}@${{ steps.task_release_gi_push.outputs.digest }}`
|
|
||||||
- Dry Run: `${{ inputs.DRY_RUN }}`
|
|
||||||
- Source: `Gitea` https://git.binaryninja.net/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
|
||||||
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
|
||||||
- Version: `${{ env.IMAGE_VERSION }}`
|
- Version: `${{ env.IMAGE_VERSION }}`
|
||||||
|
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
||||||
|
- Pull: `docker pull ${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}`
|
||||||
|
- Pull (amd64): `docker pull ${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push_amd64.outputs.digest }}`
|
||||||
|
- Pull (arm64): `docker pull ${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push_arm64.outputs.digest }}`
|
||||||
|
- Dry Run: `${{ inputs.DRY_RUN }}`
|
||||||
|
- Source: `Gitea` https://${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
||||||
|
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
- Branch: `${{ github.ref_name }}`
|
- Branch: `${{ github.ref_name }}`
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
||||||
- Runner: `${{ runner.name }}`
|
- Runner: `${{ runner.name }}`
|
||||||
@@ -707,14 +785,14 @@ jobs:
|
|||||||
-# This docker image will use the following tags:
|
-# This docker image will use the following tags:
|
||||||
|
|
||||||
```
|
```
|
||||||
${{ steps.task_release_gi_meta.outputs.tags }}
|
${{ steps.task_release_gi_meta_amd64.outputs.tags }}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Labels
|
### Labels
|
||||||
-# This docker image embeds the following labels:
|
-# This docker image embeds the following labels:
|
||||||
|
|
||||||
```
|
```
|
||||||
${{ steps.task_release_gi_meta.outputs.labels }}
|
${{ steps.task_release_gi_meta_amd64.outputs.labels }}
|
||||||
```
|
```
|
||||||
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"
|
||||||
|
|||||||
783
.github/workflows/deploy-docker-giteacom.yml
vendored
Normal file
@@ -0,0 +1,783 @@
|
|||||||
|
# #
|
||||||
|
# @type github workflow
|
||||||
|
# @author Aetherinox
|
||||||
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage deploys docker container to Gitea.com and send message to discord
|
||||||
|
# upload this workflow to both the `main` branch of the tvapp2 repository
|
||||||
|
#
|
||||||
|
# @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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/deploy-docker-giteacom.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/deploy-docker-giteacom.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
|
# #
|
||||||
|
|
||||||
|
name: "📦 Deploy › Docker › Gitea.com"
|
||||||
|
run-name: "📦 Deploy › Docker › Gitea.com"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Triggers
|
||||||
|
# #
|
||||||
|
|
||||||
|
on:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger › Workflow Dispatch
|
||||||
|
#
|
||||||
|
# If any values are not provided, will use fallback env variable
|
||||||
|
# #
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Image Name
|
||||||
|
#
|
||||||
|
# used in github image path
|
||||||
|
# gitea.com/${{ env.IMAGE_GITEA_AUTHOR }}/${{ env.IMAGE_NAME }}
|
||||||
|
# #
|
||||||
|
|
||||||
|
IMAGE_NAME:
|
||||||
|
description: '📦 Image Name'
|
||||||
|
required: true
|
||||||
|
default: 'tvapp2'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Image Version
|
||||||
|
#
|
||||||
|
# used to create new release tag, and add version to docker image name
|
||||||
|
# #
|
||||||
|
|
||||||
|
IMAGE_VERSION:
|
||||||
|
description: '🏷️ Image Version'
|
||||||
|
required: true
|
||||||
|
default: '1.0.0'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Gitea › Author
|
||||||
|
#
|
||||||
|
# used in github image path
|
||||||
|
# gitea.com/${{ env.IMAGE_GITEA_AUTHOR }}/${{ env.IMAGE_NAME }}
|
||||||
|
# #
|
||||||
|
|
||||||
|
IMAGE_GITEA_AUTHOR:
|
||||||
|
description: '🪪 Image Author'
|
||||||
|
required: true
|
||||||
|
default: 'BinaryNinja'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Gitea › Username
|
||||||
|
#
|
||||||
|
# this is the user to sign into gitea as.
|
||||||
|
# #
|
||||||
|
|
||||||
|
IMAGE_GITEA_USERNAME:
|
||||||
|
description: '🪪 Gitea Username'
|
||||||
|
required: true
|
||||||
|
default: 'aetherinox'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Gitea › Website
|
||||||
|
#
|
||||||
|
# this is the gitea website / url to push to
|
||||||
|
# #
|
||||||
|
|
||||||
|
IMAGE_GITEA_WEBSITE:
|
||||||
|
description: '🌎 Gitea Website'
|
||||||
|
required: true
|
||||||
|
default: 'gitea.com'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
# #
|
||||||
|
# true no changes to the repo will be made
|
||||||
|
# false workflow will behave normally, and push any changes detected to the files
|
||||||
|
# #
|
||||||
|
|
||||||
|
DRY_RUN:
|
||||||
|
description: '🐛 Dry Run (Debug)'
|
||||||
|
required: true
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
# #
|
||||||
|
# true released version will be marked as a development build and will have the v1.x.x-development tag instead of -latest
|
||||||
|
# false release version will be marked with -latest docker tag
|
||||||
|
# #
|
||||||
|
|
||||||
|
DEV_RELEASE:
|
||||||
|
description: '🧪 Development Release'
|
||||||
|
required: true
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Trigger › Push
|
||||||
|
# #
|
||||||
|
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Environment Vars
|
||||||
|
# #
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: ${{ github.event.inputs.IMAGE_NAME || 'tvapp2' }}
|
||||||
|
IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }}
|
||||||
|
IMAGE_GITEA_AUTHOR: ${{ github.event.inputs.IMAGE_GITEA_AUTHOR || 'BinaryNinja' }}
|
||||||
|
IMAGE_GITEA_USERNAME: ${{ github.event.inputs.IMAGE_GITEA_USERNAME || 'BinaryNinja' }}
|
||||||
|
IMAGE_GITEA_WEBSITE: ${{ github.event.inputs.IMAGE_GITEA_WEBSITE || 'gitea.com' }}
|
||||||
|
|
||||||
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Jobs
|
||||||
|
#
|
||||||
|
# The way pushed docker containers on Gitea work, the most recent image built goes at the top.
|
||||||
|
# We will use the order below which builds the :latest image last so that it appears at the very
|
||||||
|
# top of the packages page.
|
||||||
|
# #
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Job › Create Tag
|
||||||
|
# #
|
||||||
|
|
||||||
|
job-docker-release-tags-create:
|
||||||
|
name: >-
|
||||||
|
📦 Release › Create Tag
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 4
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Tags › Start
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🏳️ Start'
|
||||||
|
id: task_release_tags_start
|
||||||
|
run: |
|
||||||
|
echo "Generating Docker Image on ${{ env.IMAGE_GITEA_WEBSITE }}"
|
||||||
|
echo "Using original Gitea workflow without manifest"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Tags › Checkout
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '✅ Checkout'
|
||||||
|
id: task_release_tags_checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Tags › Fix Permissions
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '#️⃣ Manage Permissions'
|
||||||
|
id: task_release_tags_permissions
|
||||||
|
run: |
|
||||||
|
find ./ -name 'run' -exec chmod 755 {} \;
|
||||||
|
WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print)
|
||||||
|
if [ -n "${WRONG_PERM}" ]; then
|
||||||
|
echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️"
|
||||||
|
for i in ${WRONG_PERM}; do
|
||||||
|
echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!"
|
||||||
|
done
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "✅✅✅ Executable permissions are OK ✅✅✅"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Tags › Create Tag
|
||||||
|
#
|
||||||
|
# only called in dispatch mode
|
||||||
|
# #
|
||||||
|
|
||||||
|
- uses: rickstaa/action-create-tag@v1
|
||||||
|
id: task_release_tags_create
|
||||||
|
if: ( github.event_name != 'workflow_dispatch' && inputs.DRY_RUN == false )
|
||||||
|
with:
|
||||||
|
tag: "${{ env.IMAGE_VERSION }}"
|
||||||
|
tag_exists_error: false
|
||||||
|
message: '${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}'
|
||||||
|
gpg_private_key: ${{ secrets.ADMINSERV_GPG_KEY_ASC }}
|
||||||
|
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Job › Docker Release › Gitea › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
job-docker-release-gitea-arm64:
|
||||||
|
name: >-
|
||||||
|
📦 Release › Gitea › Arm64
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 10
|
||||||
|
needs: [ job-docker-release-tags-create ]
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Start › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🏳️ Start'
|
||||||
|
id: task_release_gi_start
|
||||||
|
run: |
|
||||||
|
echo "Generating Docker Image on ${{ env.IMAGE_GITEA_WEBSITE }} › arm64"
|
||||||
|
echo "Using original Gitea workflow without manifest"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Checkout › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '✅ Checkout'
|
||||||
|
id: task_release_gh_checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Get Timestamp
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🕛 Get Timestamp'
|
||||||
|
id: task_release_set_timestamp
|
||||||
|
run: |
|
||||||
|
echo "IMAGE_VERSION_1DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1`" >> ${GITHUB_ENV} # 1
|
||||||
|
echo "IMAGE_VERSION_2DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-2`" >> ${GITHUB_ENV} # 1.0
|
||||||
|
echo "REGISTRY_REPO_ORG_AUTHOR_LC=`echo ${{ env.IMAGE_GITEA_AUTHOR }}/${{ env.IMAGE_NAME }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # binaryninja/tvapp2
|
||||||
|
echo "REGISTRY_REPO_AUTHOR_LC=`echo ${{ env.IMAGE_GITEA_AUTHOR }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # binaryninja
|
||||||
|
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV # 71fad013cfce9116ec62779e4a7e627fe4c33627
|
||||||
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV # 02-25-2025 12:49:48
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV # 02-25-2025
|
||||||
|
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_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Install Dependencies
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Install Dependencies'
|
||||||
|
id: task_release_gi_dependencies
|
||||||
|
run:
|
||||||
|
sudo apt-get install -qq dos2unix
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Execute dos2unix
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔐 Apply dos2unix'
|
||||||
|
id: task_release_gi_dos2unix
|
||||||
|
run: |
|
||||||
|
echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️"
|
||||||
|
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
||||||
|
echo "✅✅✅ Completed DOS2UNIX ✅✅✅"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Fix Permissions
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '#️⃣ Manage Permissions'
|
||||||
|
id: task_release_gi_permissions
|
||||||
|
run: |
|
||||||
|
find ./ -name 'run' -exec chmod 755 {} \;
|
||||||
|
WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print)
|
||||||
|
if [ -n "${WRONG_PERM}" ]; then
|
||||||
|
echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️"
|
||||||
|
for i in ${WRONG_PERM}; do
|
||||||
|
echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!"
|
||||||
|
done
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "✅✅✅ Executable permissions are OK ✅✅✅"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › QEMU › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Set up QEMU'
|
||||||
|
id: task_release_gi_qemu
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Setup BuildX › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Setup Buildx'
|
||||||
|
id: task_release_gi_buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
driver-opts: 'image=moby/buildkit:latest'
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Registry Login › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Login to Gitea'
|
||||||
|
id: task_release_gi_registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.IMAGE_GITEA_WEBSITE }}
|
||||||
|
username: ${{ env.IMAGE_GITEA_USERNAME }}
|
||||||
|
password: ${{ secrets.ORG_BINARYNINJA_GITEACOM_TOKEN }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Meta › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Gitea: Meta - Arm64'
|
||||||
|
id: task_release_gi_meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
# latest no
|
||||||
|
type=raw,value=latest,enable=false
|
||||||
|
|
||||||
|
# tag add arm64
|
||||||
|
# type=raw,enable=true,priority=1000,value=arm64
|
||||||
|
|
||||||
|
# dispatch add x1.x.x-arm64
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-arm64,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
|
# dispatch add arm64-development
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-arm64,value=development
|
||||||
|
|
||||||
|
# tag add tag-arm64
|
||||||
|
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-arm64,event=tag
|
||||||
|
flavor: |
|
||||||
|
latest=false
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Build and Push › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Build & Push (linux/arm64)'
|
||||||
|
id: task_release_gi_push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: Dockerfile.aarch64
|
||||||
|
platforms: linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.task_release_gi_meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.task_release_gi_meta.outputs.labels }}
|
||||||
|
provenance: false
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Checkpoint › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚠️ Checkpoint'
|
||||||
|
id: task_release_gi_checkpoint
|
||||||
|
run: |
|
||||||
|
echo "registry ................................. Gitea"
|
||||||
|
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 "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
||||||
|
echo "env.AUTHOR ............................... ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
||||||
|
echo "tags ..................................... ${{ steps.task_release_gi_meta.outputs.tags }}"
|
||||||
|
echo "labels ................................... ${{ steps.task_release_gi_meta.outputs.labels }}"
|
||||||
|
echo "docker image ............................. ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
||||||
|
echo "docker sha ............................... ${{ env.DOCKER_SHA }}"
|
||||||
|
echo "docker image id .......................... ${{ steps.task_release_gi_push.outputs.imageid }}"
|
||||||
|
echo "docker digest ............................ ${{ steps.task_release_gi_push.outputs.digest }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Get Weekly Commits
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🕛 Get Weekly Commit List'
|
||||||
|
id: task_release_set_weekly_commit_list
|
||||||
|
run: |
|
||||||
|
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
||||||
|
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
||||||
|
echo 'EOF' >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Notify Gitea
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔔 Send Discord Webhook Message'
|
||||||
|
id: task_release_notifications_discord_send
|
||||||
|
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_GITHUB_TVAPP2_RELEASES }}
|
||||||
|
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: |
|
||||||
|
## 📦 Docker › Deploy (Gitea) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
|
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
||||||
|
|
||||||
|
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Gitea. The image is available at:
|
||||||
|
- https://${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
||||||
|
|
||||||
|
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
||||||
|
- Pull: `docker pull ${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-arm64`
|
||||||
|
- Pull: `docker pull ${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push.outputs.digest }}`
|
||||||
|
- Dry Run: `${{ inputs.DRY_RUN }}`
|
||||||
|
- Source: `Gitea` https://${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
||||||
|
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
|
- Version: `${{ env.IMAGE_VERSION }}`
|
||||||
|
- Branch: `${{ github.ref_name }}`
|
||||||
|
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
||||||
|
- Runner: `${{ runner.name }}`
|
||||||
|
- Triggered By: `${{ github.actor }}`
|
||||||
|
- Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}`
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
-# This docker image will use the following tags:
|
||||||
|
|
||||||
|
```
|
||||||
|
${{ steps.task_release_gi_meta.outputs.tags }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Labels
|
||||||
|
-# This docker image embeds the following labels:
|
||||||
|
|
||||||
|
```
|
||||||
|
${{ steps.task_release_gi_meta.outputs.labels }}
|
||||||
|
```
|
||||||
|
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"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Job › Docker Release › Gitea › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
job-docker-release-gitea-amd64:
|
||||||
|
name: >-
|
||||||
|
📦 Release › Gitea › Amd64
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 10
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
needs: [ job-docker-release-tags-create, job-docker-release-gitea-arm64 ]
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Start › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🏳️ Start'
|
||||||
|
id: task_release_gi_start
|
||||||
|
run: |
|
||||||
|
echo "Generating Docker Image on ${{ env.IMAGE_GITEA_WEBSITE }} › amd64"
|
||||||
|
echo "Using original Gitea workflow without manifest"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Checkout
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '✅ Checkout'
|
||||||
|
id: task_release_gh_checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Get Timestamp
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🕛 Get Timestamp'
|
||||||
|
id: task_release_set_timestamp
|
||||||
|
run: |
|
||||||
|
echo "IMAGE_VERSION_1DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1`" >> ${GITHUB_ENV} # 1
|
||||||
|
echo "IMAGE_VERSION_2DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-2`" >> ${GITHUB_ENV} # 1.0
|
||||||
|
echo "REGISTRY_REPO_ORG_AUTHOR_LC=`echo ${{ env.IMAGE_GITEA_AUTHOR }}/${{ env.IMAGE_NAME }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # binaryninja/tvapp2
|
||||||
|
echo "REGISTRY_REPO_AUTHOR_LC=`echo ${{ env.IMAGE_GITEA_AUTHOR }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # binaryninja
|
||||||
|
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV # 71fad013cfce9116ec62779e4a7e627fe4c33627
|
||||||
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV # 02-25-2025 12:49:48
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV # 02-25-2025
|
||||||
|
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_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Install Dependencies
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Install Dependencies'
|
||||||
|
id: task_release_gi_dependencies
|
||||||
|
run:
|
||||||
|
sudo apt-get install -qq dos2unix
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Execute dos2unix
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔐 Apply dos2unix'
|
||||||
|
id: task_release_gi_dos2unix
|
||||||
|
run: |
|
||||||
|
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Fix Permissions
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '#️⃣ Manage Permissions'
|
||||||
|
id: task_release_gi_permissions
|
||||||
|
run: |
|
||||||
|
find ./ -name 'run' -exec chmod 755 {} \;
|
||||||
|
WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print)
|
||||||
|
if [ -n "${WRONG_PERM}" ]; then
|
||||||
|
echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️"
|
||||||
|
for i in ${WRONG_PERM}; do
|
||||||
|
echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!"
|
||||||
|
done
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "✅✅✅ Executable permissions are OK ✅✅✅"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › QEMU › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Set up QEMU'
|
||||||
|
id: task_release_gi_qemu
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Setup BuildX › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Setup Buildx'
|
||||||
|
id: task_release_gi_buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
driver-opts: 'image=moby/buildkit:latest'
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Registry Login › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Login to Gitea'
|
||||||
|
id: task_release_gi_registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.IMAGE_GITEA_WEBSITE }}
|
||||||
|
username: ${{ env.IMAGE_GITEA_USERNAME }}
|
||||||
|
password: ${{ secrets.ORG_BINARYNINJA_GITEACOM_TOKEN }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Meta › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Gitea: Meta - Amd64'
|
||||||
|
id: task_release_gi_meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }}
|
||||||
|
tags: |
|
||||||
|
# latest yes
|
||||||
|
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
||||||
|
|
||||||
|
# tag add amd64
|
||||||
|
# type=raw,enable=true,priority=1000,value=amd64
|
||||||
|
|
||||||
|
# dispatch add x1.x.x-amd64
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-amd64,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
|
# dispatch add amd64-development
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-amd64,value=development
|
||||||
|
|
||||||
|
# tag add tag-amd64
|
||||||
|
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-amd64,event=tag
|
||||||
|
|
||||||
|
# add development tag to default architecture (amd64)
|
||||||
|
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
||||||
|
flavor: |
|
||||||
|
latest=false
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Build and Push › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Build & Push (linux/amd64)'
|
||||||
|
id: task_release_gi_push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.task_release_gi_meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.task_release_gi_meta.outputs.labels }}
|
||||||
|
provenance: false
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Checkpoint › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚠️ Checkpoint'
|
||||||
|
id: task_release_gi_checkpoint
|
||||||
|
run: |
|
||||||
|
echo "registry ................................. Gitea"
|
||||||
|
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 "inputs.DRY_RUN ........................... ${{ inputs.DRY_RUN }}"
|
||||||
|
echo "env.AUTHOR ............................... ${{ env.REGISTRY_REPO_AUTHOR_LC }}"
|
||||||
|
echo "tags ..................................... ${{ steps.task_release_gi_meta.outputs.tags }}"
|
||||||
|
echo "labels ................................... ${{ steps.task_release_gi_meta.outputs.labels }}"
|
||||||
|
echo "docker image ............................. ${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}"
|
||||||
|
echo "docker sha ............................... ${{ env.DOCKER_SHA }}"
|
||||||
|
echo "docker image id .......................... ${{ steps.task_release_gi_push.outputs.imageid }}"
|
||||||
|
echo "docker digest ............................ ${{ steps.task_release_gi_push.outputs.digest }}"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Get Weekly Commits
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🕛 Get Weekly Commit List'
|
||||||
|
id: task_release_set_weekly_commit_list
|
||||||
|
run: |
|
||||||
|
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
||||||
|
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
||||||
|
echo 'EOF' >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Gitea › Notify Gitea
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔔 Send Discord Webhook Message'
|
||||||
|
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_GITHUB_TVAPP2_RELEASES }}
|
||||||
|
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: |
|
||||||
|
## 📦 Docker › Deploy (Gitea) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
|
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
||||||
|
|
||||||
|
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Gitea. The image is available at:
|
||||||
|
- https://${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
||||||
|
|
||||||
|
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
||||||
|
- Pull: `docker pull ${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-amd64`
|
||||||
|
- Pull: `docker pull ${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gi_push.outputs.digest }}`
|
||||||
|
- Dry Run: `${{ inputs.DRY_RUN }}`
|
||||||
|
- Source: `Gitea` https://${{ env.IMAGE_GITEA_WEBSITE }}/${{ env.IMAGE_GITEA_USERNAME }}/${{ env.IMAGE_NAME }}/packages
|
||||||
|
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
|
- Version: `${{ env.IMAGE_VERSION }}`
|
||||||
|
- Branch: `${{ github.ref_name }}`
|
||||||
|
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
||||||
|
- Runner: `${{ runner.name }}`
|
||||||
|
- Triggered By: `${{ github.actor }}`
|
||||||
|
- Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}`
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
-# This docker image will use the following tags:
|
||||||
|
|
||||||
|
```
|
||||||
|
${{ steps.task_release_gi_meta.outputs.tags }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Labels
|
||||||
|
-# This docker image embeds the following labels:
|
||||||
|
|
||||||
|
```
|
||||||
|
${{ steps.task_release_gi_meta.outputs.labels }}
|
||||||
|
```
|
||||||
|
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"
|
||||||
682
.github/workflows/deploy-docker-github.yml
vendored
@@ -4,10 +4,31 @@
|
|||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
# @usage deploys docker container to github and send message to discord
|
# @usage deploys docker container to github and send message to discord
|
||||||
# upload this workflow to both the `main` branch of the tvapp2 repository
|
# upload this workflow to both the `main` branch of the tvapp2 repository
|
||||||
# @secrets secrets.ADMINSERV_GPG_KEY_ASC gpg private key (armored) | BEGIN PGP PRIVATE KEY BLOCK
|
#
|
||||||
# secrets.ADMINSERV_GPG_PASSPHRASE gpg private key passphrase
|
# @secrets secrets.SELF_TOKEN self github personal access token (fine-grained)
|
||||||
# secrets.ORG_BINARYNINJA_TOKEN_CL github personal access token (classic) with package:write permission
|
# secrets.SELF_TOKEN_CL self github personal access token (classic)
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES Discord webhook to report releases from github to discord
|
# 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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/deploy-docker-github.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/deploy-docker-github.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "📦 Deploy › Docker › Github"
|
name: "📦 Deploy › Docker › Github"
|
||||||
@@ -36,10 +57,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
IMAGE_NAME:
|
IMAGE_NAME:
|
||||||
description: '📦 Image Name'
|
description: '📦 Image Name'
|
||||||
required: true
|
required: true
|
||||||
default: 'tvapp2'
|
default: 'tvapp2'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Image Version
|
# Image Version
|
||||||
@@ -48,10 +69,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
IMAGE_VERSION:
|
IMAGE_VERSION:
|
||||||
description: '🏷️ Image Version'
|
description: '🏷️ Image Version'
|
||||||
required: true
|
required: true
|
||||||
default: '1.0.0'
|
default: '1.0.0'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Image Author
|
# Image Author
|
||||||
@@ -61,10 +82,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
IMAGE_GHCR_AUTHOR:
|
IMAGE_GHCR_AUTHOR:
|
||||||
description: '🪪 Image Author'
|
description: '🪪 Image Author'
|
||||||
required: true
|
required: true
|
||||||
default: 'TheBinaryNinja'
|
default: 'TheBinaryNinja'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Image ghcr username
|
# Image ghcr username
|
||||||
@@ -113,12 +134,15 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE_NAME: ${{ github.event.inputs.IMAGE_NAME || 'tvapp2' }}
|
IMAGE_NAME: ${{ github.event.inputs.IMAGE_NAME || 'tvapp2' }}
|
||||||
IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }}
|
IMAGE_VERSION: ${{ github.event.inputs.IMAGE_VERSION || '1.0.0' }}
|
||||||
IMAGE_GHCR_AUTHOR: ${{ github.event.inputs.IMAGE_GHCR_AUTHOR || 'BinaryNinja' }}
|
IMAGE_GHCR_AUTHOR: ${{ github.event.inputs.IMAGE_GHCR_AUTHOR || 'BinaryNinja' }}
|
||||||
IMAGE_GHCR_USERNAME: ${{ github.event.inputs.IMAGE_GHCR_USERNAME || 'BinaryNinja' }}
|
IMAGE_GHCR_USERNAME: ${{ github.event.inputs.IMAGE_GHCR_USERNAME || 'BinaryNinja' }}
|
||||||
BOT_NAME_1: EuropaServ
|
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Jobs
|
# Jobs
|
||||||
@@ -202,280 +226,21 @@ jobs:
|
|||||||
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Docker Release › Github › Arm64
|
# Job › Docker Release › Github
|
||||||
# #
|
# #
|
||||||
|
|
||||||
job-docker-release-github-arm64:
|
job-docker-release-github:
|
||||||
name: >-
|
name: >-
|
||||||
📦 Release › Github › Arm64
|
📦 Release › Github
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
needs: [ job-docker-release-tags-create ]
|
needs: [ job-docker-release-tags-create ]
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Start › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🏳️ Start'
|
|
||||||
id: task_release_gh_start
|
|
||||||
run: |
|
|
||||||
echo "Starting Github Docker arm64"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Checkout › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '✅ Checkout'
|
|
||||||
id: task_release_gh_checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Get Timestamp
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🕛 Get Timestamp'
|
|
||||||
id: task_release_set_timestamp
|
|
||||||
run: |
|
|
||||||
echo "DOCKER_IMAGE=`echo ${{github.repository}} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV}
|
|
||||||
echo "DOCKER_SHA=${GITHUB_SHA}" >> $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 › Github › Install Dependencies
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Install Dependencies'
|
|
||||||
id: task_release_gh_dependencies
|
|
||||||
run:
|
|
||||||
sudo apt-get install -qq dos2unix
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Execute dos2unix
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔐 Apply dos2unix'
|
|
||||||
id: task_release_gh_dos2unix
|
|
||||||
run: |
|
|
||||||
echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️"
|
|
||||||
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
|
||||||
echo "✅✅✅ Completed DOS2UNIX ✅✅✅"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Fix Permissions
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '#️⃣ Manage Permissions'
|
|
||||||
id: task_release_gh_permissions
|
|
||||||
run: |
|
|
||||||
find ./ -name 'run' -exec chmod 755 {} \;
|
|
||||||
WRONG_PERM=$(find ./ -path "./.git" -prune -o \( -name "run" -o -name "finish" -o -name "check" \) -not -perm -u=x,g=x,o=x -print)
|
|
||||||
if [ -n "${WRONG_PERM}" ]; then
|
|
||||||
echo "⚠️⚠️⚠️ Permissions are invalid ⚠️⚠️⚠️"
|
|
||||||
for i in ${WRONG_PERM}; do
|
|
||||||
echo "::error file=${i},line=1,title=Missing Executable Bit::This file needs to be set as executable!"
|
|
||||||
done
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "✅✅✅ Executable permissions are OK ✅✅✅"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › QEMU › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Set up QEMU'
|
|
||||||
id: task_release_gh_qemu
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Setup BuildX › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Setup Buildx'
|
|
||||||
id: task_release_gh_buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
driver-opts: 'image=moby/buildkit:latest'
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Registry Login › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚙️ Login to Github'
|
|
||||||
id: task_release_gh_registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ env.IMAGE_GHCR_USERNAME }}
|
|
||||||
password: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Meta › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔨 Github: Meta - Arm64'
|
|
||||||
id: task_release_gh_meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
ghcr.io/${{ env.IMAGE_GHCR_AUTHOR }}/${{ env.IMAGE_NAME }}
|
|
||||||
tags: |
|
|
||||||
# latest no
|
|
||||||
type=raw,value=latest,enable=false
|
|
||||||
|
|
||||||
# tag add arm64
|
|
||||||
# type=raw,enable=true,priority=1000,value=arm64
|
|
||||||
|
|
||||||
# dispatch add x1.x.x-arm64
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-arm64,value=${{ env.IMAGE_VERSION }}
|
|
||||||
|
|
||||||
# dispatch add arm64-development
|
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-arm64,value=development
|
|
||||||
|
|
||||||
# tag add tag-arm64
|
|
||||||
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-arm64,event=tag
|
|
||||||
flavor: |
|
|
||||||
latest=false
|
|
||||||
labels: |
|
|
||||||
org.opencontainers.image.VERSION=${{ env.IMAGE_VERSION }}
|
|
||||||
org.opencontainers.image.BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
|
||||||
org.opencontainers.image.licenses=MIT
|
|
||||||
org.opencontainers.image.revision=${{ github.sha }}
|
|
||||||
org.opencontainers.image.vendor=${{ env.IMAGE_GHCR_AUTHOR }}
|
|
||||||
org.opencontainers.image.ref.name=${{ env.ref_name }}
|
|
||||||
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Build and Push › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '📦 Build & Push (linux/arm64)'
|
|
||||||
id: task_release_gh_push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: Dockerfile.aarch64
|
|
||||||
platforms: linux/arm64
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.task_release_gh_meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.task_release_gh_meta.outputs.labels }}
|
|
||||||
provenance: false
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Checkpoint › Arm64
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '⚠️ Checkpoint'
|
|
||||||
id: task_release_gh_checkpoint
|
|
||||||
run: |
|
|
||||||
echo "registry ............. 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 "inputs.DRY_RUN ....... ${{ inputs.DRY_RUN }}"
|
|
||||||
echo "env.AUTHOR ........... ${{ env.IMAGE_GHCR_AUTHOR }}"
|
|
||||||
echo "tags ................. ${{ steps.task_release_gh_meta.outputs.tags }}"
|
|
||||||
echo "labels ............... ${{ steps.task_release_gh_meta.outputs.labels }}"
|
|
||||||
echo "docker image ......... ${{ env.DOCKER_IMAGE }}"
|
|
||||||
echo "docker sha ........... ${{ env.DOCKER_SHA }}"
|
|
||||||
echo "docker image id ...... ${{ steps.task_release_gh_push.outputs.imageid }}"
|
|
||||||
echo "docker digest ........ ${{ steps.task_release_gh_push.outputs.digest }}"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Get Weekly Commits
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🕛 Get Weekly Commit List'
|
|
||||||
id: task_release_set_weekly_commit_list
|
|
||||||
run: |
|
|
||||||
echo 'WEEKLY_COMMITS<<EOF' >> $GITHUB_ENV
|
|
||||||
git log --format="[\`%h\`](${{ github.server_url }}/${{ github.repository }}/commit/%H) %s - %an" --since=7.days >> $GITHUB_ENV
|
|
||||||
echo 'EOF' >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Release › Github › Notify Github
|
|
||||||
# #
|
|
||||||
|
|
||||||
- name: '🔔 Send Discord Webhook Message'
|
|
||||||
id: task_release_notifications_discord_send
|
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
|
||||||
if: success()
|
|
||||||
with:
|
|
||||||
username: 'Io'
|
|
||||||
avatar-url: 'https://i.imgur.com/8BVDkla.jpg'
|
|
||||||
webhook-url: ${{ secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_RELEASES }}
|
|
||||||
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: |
|
|
||||||
## 📦 Docker › Deploy (Github) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
|
||||||
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
|
||||||
|
|
||||||
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Github GHCR. The image is available at:
|
|
||||||
- https://github.com/${{ github.repository }}/pkgs/container/${{ env.IMAGE_NAME }}
|
|
||||||
|
|
||||||
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
|
||||||
- Pull: `docker pull ghcr.io/${{ env.DOCKER_IMAGE }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-arm64`
|
|
||||||
- Pull: `docker pull ghcr.io/${{ env.DOCKER_IMAGE }}@${{ steps.task_release_gh_push.outputs.digest }}`
|
|
||||||
- Dry Run: `${{ inputs.DRY_RUN }}`
|
|
||||||
- Source: `Github` https://github.com/${{ github.repository }}
|
|
||||||
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
|
||||||
- Version: `${{ env.IMAGE_VERSION }}`
|
|
||||||
- Branch: `${{ github.ref_name }}`
|
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
|
||||||
- Runner: `${{ runner.name }}`
|
|
||||||
- Triggered By: `${{ github.actor }}`
|
|
||||||
- Status: `${{ job.status == 'success' && '✅ Successful' || '❌ Failed' }}`
|
|
||||||
|
|
||||||
### Tags
|
|
||||||
-# This docker image will use the following tags:
|
|
||||||
|
|
||||||
```
|
|
||||||
${{ steps.task_release_gh_meta.outputs.tags }}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Labels
|
|
||||||
-# This docker image embeds the following labels:
|
|
||||||
|
|
||||||
```
|
|
||||||
${{ steps.task_release_gh_meta.outputs.labels }}
|
|
||||||
```
|
|
||||||
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"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Job › Docker Release › Github › Amd64
|
|
||||||
# #
|
|
||||||
|
|
||||||
job-docker-release-github-amd64:
|
|
||||||
name: >-
|
|
||||||
📦 Release › Github › Amd64
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 10
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
attestations: write
|
|
||||||
id-token: write
|
|
||||||
needs: [ job-docker-release-tags-create, job-docker-release-github-arm64 ]
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -502,12 +267,16 @@ jobs:
|
|||||||
- name: '🕛 Get Timestamp'
|
- name: '🕛 Get Timestamp'
|
||||||
id: task_release_set_timestamp
|
id: task_release_set_timestamp
|
||||||
run: |
|
run: |
|
||||||
echo "DOCKER_IMAGE=`echo ${{github.repository}} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV}
|
echo "IMAGE_VERSION_1DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-1`" >> ${GITHUB_ENV} # 1
|
||||||
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV
|
echo "IMAGE_VERSION_2DIGIT=`echo ${{ env.IMAGE_VERSION }} | cut -d '.' -f1-2`" >> ${GITHUB_ENV} # 1.0
|
||||||
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV
|
echo "REGISTRY_REPO_ORG_AUTHOR_LC=`echo ${{ env.IMAGE_GHCR_AUTHOR }}/${{ env.IMAGE_NAME }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja/tvapp2
|
||||||
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV
|
echo "REGISTRY_REPO_AUTHOR_LC=`echo ${{ env.IMAGE_GHCR_AUTHOR }} | tr '[:upper:]' '[:lower:]'`" >> ${GITHUB_ENV} # thebinaryninja
|
||||||
echo "NOW_LONG=$(date +'%m-%d-%Y %H:%M')" >> $GITHUB_ENV
|
echo "DOCKER_SHA=${GITHUB_SHA}" >> $GITHUB_ENV # 71fad013cfce9116ec62779e4a7e627fe4c33627
|
||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
echo "NOW=$(date +'%m-%d-%Y %H:%M:%S')" >> $GITHUB_ENV # 02-25-2025 12:49:48
|
||||||
|
echo "NOW_SHORT=$(date +'%m-%d-%Y')" >> $GITHUB_ENV # 02-25-2025
|
||||||
|
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_TS=$(date -u +'%FT%T.%3NZ')" >> $GITHUB_ENV # 2025-02-25T12:50:11.569Z
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Install Dependencies
|
# Release › Github › Install Dependencies
|
||||||
@@ -525,7 +294,9 @@ jobs:
|
|||||||
- name: '🔐 Apply dos2unix'
|
- name: '🔐 Apply dos2unix'
|
||||||
id: task_release_gh_dos2unix
|
id: task_release_gh_dos2unix
|
||||||
run: |
|
run: |
|
||||||
|
echo "⚠️⚠️⚠️ Running DOS2UNIX ⚠️⚠️⚠️"
|
||||||
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
find ./ \( -path "./.git" -o -path "./docs" -o -path "./.github" -o -path "*.png" -o -path "*.jpg" \) -prune -o -name '*' -print | xargs dos2unix --
|
||||||
|
echo "✅✅✅ Completed DOS2UNIX ✅✅✅"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Fix Permissions
|
# Release › Github › Fix Permissions
|
||||||
@@ -578,81 +349,271 @@ jobs:
|
|||||||
password: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }}
|
password: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Meta › Amd64
|
# Release › Github › Read Readme
|
||||||
|
#
|
||||||
|
# @usage org.opencontainers.image.description=${{ steps.task_release_gh_readme_cache.outputs.content }}
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔨 Github: Meta - Amd64'
|
- name: '📄 Cache README.md'
|
||||||
|
id: task_release_gh_readme_cache
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }}
|
||||||
|
script: |
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { promises: fs } = require('fs')
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const path = "README.md"
|
||||||
|
let content = await fs.readFile(path, 'utf8')
|
||||||
|
|
||||||
|
core.setOutput('content', content)
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(err => core.setFailed(err.message))
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Meta
|
||||||
|
#
|
||||||
|
# this version of meta does not need one for amd64 and one for arm64 because both
|
||||||
|
# platforms are combined into one release, all sharing the same tags
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Github: Meta'
|
||||||
id: task_release_gh_meta
|
id: task_release_gh_meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
ghcr.io/${{ env.IMAGE_GHCR_AUTHOR }}/${{ env.IMAGE_NAME }}
|
ghcr.io/${{ env.REGISTRY_REPO_AUTHOR_LC }}/${{ env.IMAGE_NAME }}
|
||||||
tags: |
|
tags: |
|
||||||
# latest yes
|
# tag latest = yes ( no dev )
|
||||||
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
type=raw,value=latest,enable=${{ !inputs.DEV_RELEASE }}
|
||||||
|
|
||||||
# tag add amd64
|
# tag add pr tag ( PR or push only )
|
||||||
# type=raw,enable=true,priority=1000,value=amd64
|
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=,event=tag
|
||||||
|
|
||||||
# dispatch add x1.x.x-amd64
|
# tag add 1.0.0 ( dispatch only + no dev )
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=300,prefix=,suffix=-amd64,value=${{ env.IMAGE_VERSION }}
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=450,prefix=,suffix=,value=${{ env.IMAGE_VERSION }}
|
||||||
|
|
||||||
# dispatch add amd64-development
|
# tag add 1.0 ( dispatch only + no dev )
|
||||||
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=-amd64,value=development
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=425,prefix=,suffix=,value=${{ env.IMAGE_VERSION_2DIGIT }}
|
||||||
|
|
||||||
# tag add tag-amd64
|
# tag add 1 ( dispatch only + no dev )
|
||||||
type=ref,enable=${{ github.event_name == 'pull_request' || github.event_name == 'push' }},priority=600,prefix=,suffix=-amd64,event=tag
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == false }},priority=400,prefix=,suffix=,value=${{ env.IMAGE_VERSION_1DIGIT }}
|
||||||
|
|
||||||
# add development tag to default architecture (amd64)
|
# tag add development ( dispatch only + only dev )
|
||||||
|
type=raw,enable=${{ github.event_name == 'workflow_dispatch' && inputs.DEV_RELEASE == true }},priority=300,prefix=,suffix=,value=development
|
||||||
|
|
||||||
|
# tag add development ( amd64 + only dev )
|
||||||
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
type=raw,enable=${{ inputs.DEV_RELEASE }},priority=400,prefix=,suffix=,value=development
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=${{ !inputs.DEV_RELEASE }}
|
latest=false
|
||||||
labels: |
|
labels: |
|
||||||
org.opencontainers.image.VERSION=${{ env.IMAGE_VERSION }}
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
org.opencontainers.image.BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
org.opencontainers.image.licenses=MIT
|
org.opencontainers.image.licenses=MIT
|
||||||
org.opencontainers.image.revision=${{ github.sha }}
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
org.opencontainers.image.vendor=${{ env.IMAGE_GHCR_AUTHOR }}
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
org.opencontainers.image.ref.name=${{ env.ref_name }}
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
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.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
annotations: |
|
||||||
|
org.opencontainers.image.created=${{ env.NOW_DOCKER_TS }}
|
||||||
|
org.opencontainers.image.version=${{ env.IMAGE_VERSION }}
|
||||||
|
org.opencontainers.image.licenses=MIT
|
||||||
|
org.opencontainers.image.revision=${{ github.sha }}
|
||||||
|
org.opencontainers.image.vendor=${{ env.REGISTRY_REPO_AUTHOR_LC }}
|
||||||
|
org.opencontainers.image.ref.name=${{ github.ref_name }}
|
||||||
|
org.opencontainers.image.development=${{ inputs.DEV_RELEASE == true && 'true' || 'false' }}
|
||||||
|
org.opencontainers.image.registry=github
|
||||||
|
org.tvapp2.image.build-version="Version:- ${{ env.IMAGE_VERSION }} Date:- ${{ env.NOW_DOCKER_LABEL }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Build and Push › Amd64
|
# Release › Github › Build and Push › Amd64
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '📦 Build & Push (linux/amd64)'
|
- name: '📦 Build & Push (linux/amd64)'
|
||||||
id: task_release_gh_push
|
id: task_release_gh_push_amd64
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
with:
|
with:
|
||||||
|
allow: |
|
||||||
|
network.host
|
||||||
|
network: host
|
||||||
context: .
|
context: .
|
||||||
file: Dockerfile
|
file: Dockerfile
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.task_release_gh_meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.task_release_gh_meta.outputs.labels }}
|
labels: ${{ steps.task_release_gh_meta.outputs.labels }}
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_gh_meta.outputs.tags }}
|
||||||
|
annotations: |
|
||||||
|
${{ steps.task_release_gh_meta.outputs.annotations }}
|
||||||
provenance: false
|
provenance: false
|
||||||
|
sbom: false
|
||||||
|
build-args: |-
|
||||||
|
ARCH=amd64
|
||||||
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Github › Checkpoint › Amd64
|
# Release › Github › Export Digest › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📄 Export Digest (linux/amd64)'
|
||||||
|
id: task_release_gh_digest_export_amd64
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/build-digest-amd64
|
||||||
|
digest="${{ steps.task_release_gh_push_amd64.outputs.digest }}"
|
||||||
|
digest="${digest#sha256:}"
|
||||||
|
touch "/tmp/build-digest-amd64/$digest"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Upload Digest › Amd64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔼 Upload Digest (linux/amd64)'
|
||||||
|
id: task_release_gh_digest_upload_amd64
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
name: digest-amd64
|
||||||
|
path: /tmp/build-digest-amd64/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 10
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Build and Push › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Build & Push (linux/arm64)'
|
||||||
|
id: task_release_gh_push_arm64
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
allow: |
|
||||||
|
network.host
|
||||||
|
network: host
|
||||||
|
context: .
|
||||||
|
file: Dockerfile
|
||||||
|
platforms: linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
labels: ${{ steps.task_release_gh_meta.outputs.labels }}
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_gh_meta.outputs.tags }}
|
||||||
|
annotations: |
|
||||||
|
${{ steps.task_release_gh_meta.outputs.annotations }}
|
||||||
|
provenance: false
|
||||||
|
sbom: false
|
||||||
|
build-args: |-
|
||||||
|
ARCH=arm64
|
||||||
|
VERSION=${{ env.IMAGE_VERSION }}
|
||||||
|
BUILDDATE=${{ env.NOW_DOCKER_LABEL }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Export Digest › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📄 Export Digest (linux/arm64)'
|
||||||
|
id: task_release_gh_digest_export_arm64
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/build-digest-arm64
|
||||||
|
digest="${{ steps.task_release_gh_push_arm64.outputs.digest }}"
|
||||||
|
digest="${digest#sha256:}"
|
||||||
|
touch "/tmp/build-digest-arm64/$digest"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Upload Digest › Arm64
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔼 Upload Digest (linux/arm64)'
|
||||||
|
id: task_release_gh_digest_upload_arm64
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: ( github.event_name == 'workflow_dispatch' && inputs.DRY_RUN == false ) || ( github.event_name == 'push' )
|
||||||
|
with:
|
||||||
|
name: digest-arm64
|
||||||
|
path: /tmp/build-digest-arm64/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 10
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Push Manifest
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Push Manifest'
|
||||||
|
id: task_release_gh_manifest
|
||||||
|
uses: int128/docker-manifest-create-action@v2
|
||||||
|
with:
|
||||||
|
push: ${{ !inputs.DRY_RUN }}
|
||||||
|
tags: |
|
||||||
|
${{ steps.task_release_gh_meta.outputs.tags }}
|
||||||
|
sources: |
|
||||||
|
ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_amd64.outputs.digest }}
|
||||||
|
ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_arm64.outputs.digest }}
|
||||||
|
index-annotations: |
|
||||||
|
${{ steps.task_release_gh_meta.outputs.labels }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Github › Checkpoint
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '⚠️ Checkpoint'
|
- name: '⚠️ Checkpoint'
|
||||||
id: task_release_gh_checkpoint
|
id: task_release_gh_checkpoint
|
||||||
run: |
|
run: |
|
||||||
echo "registry ............. Github"
|
echo ""
|
||||||
echo "github.actor.......... ${{ github.actor }}"
|
echo "[ GITHUB ] ---------------------------------------------------------------------------------------------"
|
||||||
echo "github.ref ........... ${{ github.ref }}"
|
echo "github.actor.............................. ${{ github.actor }}"
|
||||||
echo "github.ref_name ...... ${{ github.ref_name }}"
|
echo "github.ref ............................... ${{ github.ref }}"
|
||||||
echo "github.event_name .... ${{ github.event_name }}"
|
echo "github.ref_name .......................... ${{ github.ref_name }}"
|
||||||
echo "inputs.DRY_RUN ....... ${{ inputs.DRY_RUN }}"
|
echo "github.event_name ........................ ${{ github.event_name }}"
|
||||||
echo "env.AUTHOR ........... ${{ env.IMAGE_GHCR_AUTHOR }}"
|
echo "github.repository_owner .................. ${{ github.repository_owner }}"
|
||||||
echo "tags ................. ${{ steps.task_release_gh_meta.outputs.tags }}"
|
echo "github.repository ........................ ${{ github.repository }}"
|
||||||
echo "labels ............... ${{ steps.task_release_gh_meta.outputs.labels }}"
|
echo ""
|
||||||
echo "docker image ......... ${{ env.DOCKER_IMAGE }}"
|
echo "[ INPUTS ] ---------------------------------------------------------------------------------------------"
|
||||||
echo "docker sha ........... ${{ env.DOCKER_SHA }}"
|
echo "inputs.IMAGE_NAME ........................ ${{ inputs.IMAGE_NAME }}"
|
||||||
echo "docker image id ...... ${{ steps.task_release_gh_push.outputs.imageid }}"
|
echo "inputs.IMAGE_VERSION ..................... ${{ inputs.IMAGE_VERSION }}"
|
||||||
echo "docker digest ........ ${{ steps.task_release_gh_push.outputs.digest }}"
|
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
|
||||||
@@ -670,7 +631,7 @@ jobs:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
- name: '🔔 Send Discord Webhook Message'
|
- name: '🔔 Send Discord Webhook Message'
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -680,19 +641,20 @@ jobs:
|
|||||||
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'
|
||||||
embed-description: |
|
embed-description: |
|
||||||
## 📦 Docker › Deploy (Github) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
### 📦 Deploy (Github) ${{ job.status == 'success' && '✅' || '❌' }} › `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
${{ inputs.DEV_RELEASE == true && '### ⚠️⚠️ Development / Pre-release ⚠️⚠️' || '' }}
|
||||||
|
|
||||||
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Github GHCR. The image is available at:
|
A new version of the docker container `${{ env.IMAGE_NAME }}` has been released from Github to Github GHCR. The image is available at:
|
||||||
- https://github.com/${{ github.repository }}/pkgs/container/${{ env.IMAGE_NAME }}
|
- https://github.com/${{ github.repository }}/pkgs/container/${{ env.IMAGE_NAME }}
|
||||||
|
|
||||||
|
- Version: `${{ env.IMAGE_VERSION }}`
|
||||||
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
- Release Type: `${{ inputs.DEV_RELEASE == true && '⚠️⚠️ Development / Pre-release ⚠️⚠️' || 'Stable' }}`
|
||||||
- Pull: `docker pull ghcr.io/${{ env.DOCKER_IMAGE }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}-amd64`
|
- Pull: `docker pull ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}:${{ inputs.DEV_RELEASE == true && 'development' || env.IMAGE_VERSION }}`
|
||||||
- Pull: `docker pull ghcr.io/${{ env.DOCKER_IMAGE }}@${{ steps.task_release_gh_push.outputs.digest }}`
|
- Pull (amd64): `docker pull ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_amd64.outputs.digest }}`
|
||||||
|
- Pull (arm64): `docker pull ghcr.io/${{ env.REGISTRY_REPO_ORG_AUTHOR_LC }}@${{ steps.task_release_gh_push_arm64.outputs.digest }}`
|
||||||
- Dry Run: `${{ inputs.DRY_RUN }}`
|
- Dry Run: `${{ inputs.DRY_RUN }}`
|
||||||
- Source: `Github` https://github.com/${{ github.repository }}
|
- Source: `Github` https://github.com/${{ github.repository }}
|
||||||
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
- Docker Image: `${{ env.IMAGE_NAME }}-${{ env.IMAGE_VERSION }}${{ inputs.DEV_RELEASE == true && '-development' || '' }}`
|
||||||
- Version: `${{ env.IMAGE_VERSION }}`
|
|
||||||
- Branch: `${{ github.ref_name }}`
|
- Branch: `${{ github.ref_name }}`
|
||||||
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
- Workflow: `${{ github.workflow }} (#${{github.run_number}})`
|
||||||
- Runner: `${{ runner.name }}`
|
- Runner: `${{ runner.name }}`
|
||||||
@@ -718,3 +680,55 @@ jobs:
|
|||||||
embed-author-name: "${{ github.repository_owner }}"
|
embed-author-name: "${{ github.repository_owner }}"
|
||||||
embed-author-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
embed-author-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||||
embed-author-icon-url: "https://avatars.githubusercontent.com/u/200161462"
|
embed-author-icon-url: "https://avatars.githubusercontent.com/u/200161462"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Job › Docker Release › Cleanup
|
||||||
|
# #
|
||||||
|
|
||||||
|
job-docker-release-cleanup:
|
||||||
|
name: >-
|
||||||
|
🧹 Release › Cleanup
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
runs-on: apollo-x64
|
||||||
|
timeout-minutes: 5
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
needs: [ job-docker-release-tags-create, job-docker-release-github ]
|
||||||
|
steps:
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Cleanup
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🏳️ Start'
|
||||||
|
id: task_cleanup_gh_start
|
||||||
|
run: |
|
||||||
|
echo "Cleaning up untagged docker images"
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Cleanup › Checkout
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '✅ Checkout'
|
||||||
|
id: task_cleanup_gh_checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Cleanup › Clean Untagged Images
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🧹 Clean Untagged Images'
|
||||||
|
id: task_cleanup_clean
|
||||||
|
uses: quartx-analytics/ghcr-cleaner@v1
|
||||||
|
with:
|
||||||
|
owner-type: org
|
||||||
|
token: ${{ secrets.ORG_BINARYNINJA_TOKEN_CL }}
|
||||||
|
repository-owner: ${{ github.repository_owner }}
|
||||||
|
repository-name: ${{ github.repository }}
|
||||||
|
delete-untagged: true
|
||||||
|
# keep-at-most: 0
|
||||||
|
|||||||
102
.github/workflows/documentation.yml
vendored
@@ -1,16 +1,38 @@
|
|||||||
# #
|
# #
|
||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @desc builds mkdocs from the main branch /docs/ folder and puts the compiled version
|
|
||||||
# in the `gh-pages` branch. Is hosted using Github Pages.
|
|
||||||
#
|
|
||||||
# @update pip install --upgrade mkdocs
|
|
||||||
# pip install --upgrade --force-reinstall mkdocs-material
|
|
||||||
#
|
|
||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage builds mkdocs from the main branch /docs/ folder and puts the compiled version
|
||||||
|
# in the `gh-pages` branch. Is hosted using Github Pages.
|
||||||
#
|
#
|
||||||
# @secrets secrets.SELF_TOKEN_CL Github Access Token (Classic)
|
# @update use the following commands to update mkdocs and the mkdocs-material theme:
|
||||||
# secrets.DISCORD_WEBHOOK_CHAN_GITHUB_TVAPP2_WORKfLOWS Discord Webbhook URL; right-click on channel, click "Integrations"
|
# pip install --upgrade mkdocs
|
||||||
|
# pip install --upgrade --force-reinstall mkdocs-material
|
||||||
|
#
|
||||||
|
# @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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/documentation.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/documentation.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "📒 Docs › Build"
|
name: "📒 Docs › Build"
|
||||||
@@ -21,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 * * *"
|
||||||
|
|
||||||
@@ -36,9 +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_DEPENDABOT: dependabot[bot]
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# jobs
|
# jobs
|
||||||
@@ -82,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:
|
||||||
@@ -104,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
|
||||||
@@ -117,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 }}"
|
||||||
|
|
||||||
|
|
||||||
# #
|
# #
|
||||||
@@ -144,7 +214,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Success)
|
🔔 Send Discord Webhook Message (Success)
|
||||||
id: task_docs_notify_discord_success
|
id: task_docs_notify_discord_success
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -178,7 +248,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Failure)
|
🔔 Send Discord Webhook Message (Failure)
|
||||||
id: task_docs_notify_discord_failure
|
id: task_docs_notify_discord_failure
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
|
|||||||
198
.github/workflows/issues-new.yml
vendored
@@ -1,15 +1,40 @@
|
|||||||
# #
|
# #
|
||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @desc searches a new issues title and body for certain keywords and assigns a label
|
|
||||||
# sets the assignee for the issue to the repository owner
|
|
||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage searches a new issues title and body for certain keywords and assigns a label
|
||||||
|
# sets the assignee for the issue to the repository owner
|
||||||
#
|
#
|
||||||
# requires the following labels to be created in your repo:
|
# @notes requires the following labels to be created in your repo:
|
||||||
# - bug
|
# - bug
|
||||||
# - feature
|
# - feature
|
||||||
# - urgent
|
# - urgent
|
||||||
# - roadmap
|
# - roadmap
|
||||||
|
#
|
||||||
|
# @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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/issues-new.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/issues-new.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Issue › New"
|
name: "🎫 Issue › New"
|
||||||
@@ -30,28 +55,31 @@ 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 ◦ Git Action"
|
LABEL_INTERNAL: "Type ◦ Internal"
|
||||||
LABEL_URGENT: "⚠ Urgent"
|
LABEL_URGENT: "⚠ Urgent"
|
||||||
|
|
||||||
BOT_NAME_1: EuropaServ
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
LABELS_JSON: |
|
LABELS_JSON: |
|
||||||
[
|
[
|
||||||
@@ -131,8 +159,7 @@ jobs:
|
|||||||
job-labels-create:
|
job-labels-create:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Verify Existing
|
🎫 Labels › Verify Existing
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
@@ -204,8 +231,7 @@ jobs:
|
|||||||
🏷️ Labels › Assign
|
🏷️ Labels › Assign
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
@@ -291,7 +317,7 @@ jobs:
|
|||||||
https://regex101.com/r/Z99Gnq/2
|
https://regex101.com/r/Z99Gnq/2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const 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 findWordList = /^\b(?:I?\s*have\s*(?:a|an)\s*(?:issue|problem|bug))|(?:problem\swith)|(?: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 bFoundMatchTitle = Boolean( findWordList.test( iss_title ) );
|
const bFoundMatchTitle = Boolean( findWordList.test( iss_title ) );
|
||||||
const bFoundMatchBody = Boolean( findWordList.test( iss_body ) );
|
const bFoundMatchBody = Boolean( findWordList.test( iss_body ) );
|
||||||
|
|
||||||
@@ -306,7 +332,7 @@ jobs:
|
|||||||
const bug_bFoundPRTitle = Boolean( bug_findPRTitle.test( iss_title ) );
|
const bug_bFoundPRTitle = Boolean( bug_findPRTitle.test( iss_title ) );
|
||||||
|
|
||||||
console.log( "Title Lowercase ............... " + iss_title_lc )
|
console.log( "Title Lowercase ............... " + iss_title_lc )
|
||||||
console.log( "Startswith " + bug_tag.toLowerCase( ) + "................ " + iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) )
|
console.log( "Startswith " + bug_tag.toLowerCase( ) + "................ " + iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) )
|
||||||
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
||||||
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
||||||
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
||||||
@@ -317,45 +343,45 @@ jobs:
|
|||||||
- Check if title contains word in words
|
- Check if title contains word in words
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
if ( iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
||||||
{
|
{
|
||||||
|
|
||||||
console.log( "⚠️ " + bug_tag + " ---------------------------------------" )
|
console.log( "⚠️ " + bug_tag + " ---------------------------------------" )
|
||||||
console.log( "Already starts with " + bug_tag + " ......... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + bug_tag + " ......... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + feat_tag + " ..... " + iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + feat_tag + " ..... " + iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + urgn_tag + " ...... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + urgn_tag + " ...... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + road_tag + " ..... " + iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + road_tag + " ..... " + iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
|
|
||||||
add_labels.push( `${ bug_lbl }` );
|
add_labels.push( `${ bug_lbl }` );
|
||||||
|
|
||||||
console.log( `Adding Tag ....................... ${ bug_lbl }` )
|
console.log( `Adding Tag ....................... ${ bug_lbl }` )
|
||||||
console.log( "\n" )
|
console.log( "\n" )
|
||||||
|
|
||||||
if ( iss_author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
if ( iss_author === `${{ env.BOT_NAME_DEPENDABOT }}` )
|
||||||
core.info( `Skipping: Detected ${ iss_author }` )
|
core.info( `Skipping: Detected ${ iss_author }` )
|
||||||
|
|
||||||
// Rename title to contain Bug:
|
// Rename title to contain Bug:
|
||||||
// Make sure issue / pr title doesnt already contain a beginning title tag
|
// Make sure issue / pr title doesnt already contain a beginning title tag
|
||||||
|
|
||||||
if ( iss_author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !bug_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
if ( iss_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( ) ) )
|
||||||
{
|
{
|
||||||
console.log( "Renaming Title" )
|
console.log( "Renaming Title" )
|
||||||
console.log( `Old Title: .................. ${ iss_title }` )
|
console.log( `Old Title: .................. ${ iss_title }` )
|
||||||
|
|
||||||
const title = context.payload.issue.title
|
const title = context.payload.issue.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 }` )
|
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: context.issue.number,
|
owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number,
|
||||||
title: `${ iss_title }`, labels: add_labels
|
title: `${ iss_title }`, labels: add_labels
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
core.setOutput( 'issue_title', iss_title )
|
core.setOutput( 'issue_title', iss_title )
|
||||||
@@ -435,7 +461,7 @@ jobs:
|
|||||||
const feat_bFoundPRTitle = Boolean( feat_findPRTitle.test( iss_title ) );
|
const feat_bFoundPRTitle = Boolean( feat_findPRTitle.test( iss_title ) );
|
||||||
|
|
||||||
console.log( "Title Lowercase ............... " + iss_title_lc )
|
console.log( "Title Lowercase ............... " + iss_title_lc )
|
||||||
console.log( "Startswith " + feat_tag.toLowerCase( ) + "............ " + iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) )
|
console.log( "Startswith " + feat_tag.toLowerCase( ) + "............ " + iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) )
|
||||||
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
||||||
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
||||||
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
||||||
@@ -447,14 +473,14 @@ jobs:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// change TAG per category
|
// change TAG per category
|
||||||
if ( iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
if ( iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
||||||
{
|
{
|
||||||
|
|
||||||
console.log( "⚠️ " + feat_tag + " ---------------------------------------" )
|
console.log( "⚠️ " + feat_tag + " ---------------------------------------" )
|
||||||
console.log( "Already starts with " + bug_tag + " ......... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + bug_tag + " ......... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + feat_tag + " ..... " + iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + feat_tag + " ..... " + iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + urgn_tag + " ...... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + urgn_tag + " ...... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + road_tag + " ..... " + iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + road_tag + " ..... " + iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
|
|
||||||
// change LBL per category
|
// change LBL per category
|
||||||
add_labels.push( `${ feat_lbl }` );
|
add_labels.push( `${ feat_lbl }` );
|
||||||
@@ -468,7 +494,7 @@ jobs:
|
|||||||
// Rename title to contain Feature:
|
// Rename title to contain Feature:
|
||||||
// Make sure issue / pr title doesnt already contain a beginning title tag
|
// Make sure issue / pr title doesnt already contain a beginning title tag
|
||||||
|
|
||||||
if ( iss_author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !feat_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
if ( iss_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( ) ) )
|
||||||
{
|
{
|
||||||
console.log( "Renaming Title" )
|
console.log( "Renaming Title" )
|
||||||
console.log( `Old Title: .................. ${ iss_title }` )
|
console.log( `Old Title: .................. ${ iss_title }` )
|
||||||
@@ -566,7 +592,7 @@ jobs:
|
|||||||
const urgn_bFoundPRTitle = Boolean( urgn_findPRTitle.test( iss_title ) );
|
const urgn_bFoundPRTitle = Boolean( urgn_findPRTitle.test( iss_title ) );
|
||||||
|
|
||||||
console.log( "Title Lowercase ............... " + iss_title_lc )
|
console.log( "Title Lowercase ............... " + iss_title_lc )
|
||||||
console.log( "Startswith " + urgn_tag.toLowerCase( ) + "............. " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) )
|
console.log( "Startswith " + urgn_tag.toLowerCase( ) + "............. " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) )
|
||||||
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
||||||
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
||||||
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
||||||
@@ -578,14 +604,14 @@ jobs:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// change TAG per category
|
// change TAG per category
|
||||||
if ( iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
if ( iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
||||||
{
|
{
|
||||||
|
|
||||||
console.log( "⚠️ " + urgn_tag + " ---------------------------------------" )
|
console.log( "⚠️ " + urgn_tag + " ---------------------------------------" )
|
||||||
console.log( "Already starts with " + bug_tag + " ......... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + bug_tag + " ......... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + feat_tag + " ..... " + iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + feat_tag + " ..... " + iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + urgn_tag + " ...... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + urgn_tag + " ...... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + road_tag + " ..... " + iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + road_tag + " ..... " + iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
|
|
||||||
// change LBL per category
|
// change LBL per category
|
||||||
add_labels.push( `${ urgn_lbl }` );
|
add_labels.push( `${ urgn_lbl }` );
|
||||||
@@ -599,7 +625,7 @@ jobs:
|
|||||||
// Rename title to contain Urgent:
|
// Rename title to contain Urgent:
|
||||||
// Make sure issue / pr title doesnt already contain a beginning title tag
|
// Make sure issue / pr title doesnt already contain a beginning title tag
|
||||||
|
|
||||||
if ( iss_author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !urgn_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
if ( iss_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( ) ) )
|
||||||
{
|
{
|
||||||
console.log( "Renaming Title" )
|
console.log( "Renaming Title" )
|
||||||
console.log( `Old Title: .................. ${ iss_title }` )
|
console.log( `Old Title: .................. ${ iss_title }` )
|
||||||
@@ -699,7 +725,7 @@ jobs:
|
|||||||
const road_bFoundPRTitle = Boolean( road_findPRTitle.test( iss_title ) );
|
const road_bFoundPRTitle = Boolean( road_findPRTitle.test( iss_title ) );
|
||||||
|
|
||||||
console.log( "Title Lowercase ............... " + iss_title_lc )
|
console.log( "Title Lowercase ............... " + iss_title_lc )
|
||||||
console.log( "Startswith " + road_tag.toLowerCase( ) + "............ " + iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
console.log( "Startswith " + road_tag.toLowerCase( ) + "............ " + iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
console.log( "Title Includes Keyword ........ " + bTriggerWordInTitle )
|
||||||
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
console.log( "Title Includes Regex .......... " + bFoundMatchTitle )
|
||||||
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
console.log( "Body Includes Regex ........... " + bFoundMatchBody )
|
||||||
@@ -711,14 +737,14 @@ jobs:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// change TAG per category
|
// change TAG per category
|
||||||
if ( iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
if ( iss_title_lc.startsWith( road_tag.toLowerCase( ) ) || bTriggerWordInTitle || bFoundMatchTitle || bFoundMatchBody )
|
||||||
{
|
{
|
||||||
|
|
||||||
console.log( "⚠️ " + road_tag + " ---------------------------------------" )
|
console.log( "⚠️ " + road_tag + " ---------------------------------------" )
|
||||||
console.log( "Already starts with " + bug_tag + " ...... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + bug_tag + " ...... " + iss_title_lc.startsWith( bug_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + feat_tag + " .. " + iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + feat_tag + " .. " + iss_title_lc.startsWith( feat_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + urgn_tag + " ... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + urgn_tag + " ... " + iss_title_lc.startsWith( urgn_tag.toLowerCase( ) ) )
|
||||||
console.log( "Already starts with " + road_tag + " .. " + iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
console.log( "Already starts with " + road_tag + " .. " + iss_title_lc.startsWith( road_tag.toLowerCase( ) ) )
|
||||||
|
|
||||||
// change LBL per category
|
// change LBL per category
|
||||||
add_labels.push( `${ road_lbl }` );
|
add_labels.push( `${ road_lbl }` );
|
||||||
@@ -732,7 +758,7 @@ jobs:
|
|||||||
// Rename title to contain Roadmap:
|
// Rename title to contain Roadmap:
|
||||||
// Make sure issue / pr title doesnt already contain a beginning title tag
|
// Make sure issue / pr title doesnt already contain a beginning title tag
|
||||||
|
|
||||||
if ( iss_author !== `${{ env.BOT_NAME_DEPENDABOT }}` && !road_bFoundPRTitle && !iss_title_lc.startsWith( bug_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( feat_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( urgn_tag.toLowerCase( ), 3 ) && !iss_title_lc.startsWith( road_tag.toLowerCase( ), 3 ) )
|
if ( iss_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( ) ) )
|
||||||
{
|
{
|
||||||
console.log( "Renaming Title" )
|
console.log( "Renaming Title" )
|
||||||
console.log( `Old Title: .................. ${ iss_title }` )
|
console.log( `Old Title: .................. ${ iss_title }` )
|
||||||
@@ -767,8 +793,7 @@ jobs:
|
|||||||
🏷️ Labels › Phrase Search
|
🏷️ Labels › Phrase Search
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
permissions:
|
permissions:
|
||||||
contents: 'read'
|
contents: 'read'
|
||||||
@@ -854,8 +879,7 @@ jobs:
|
|||||||
job-assign-assignees:
|
job-assign-assignees:
|
||||||
name: >-
|
name: >-
|
||||||
✍️ Issue › Assignees
|
✍️ Issue › Assignees
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
needs: [ job-assign-labels ]
|
needs: [ job-assign-labels ]
|
||||||
# disable
|
# disable
|
||||||
|
|||||||
254
.github/workflows/issues-scan.yml
vendored
@@ -1,12 +1,39 @@
|
|||||||
# #
|
# #
|
||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @desc pull request autoscan
|
# @author Aetherinox
|
||||||
|
# @url https://github.com/Aetherinox
|
||||||
|
# @desc 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.
|
||||||
# sends notifications to discord using webhooks
|
# sends notifications to discord using webhooks
|
||||||
# @author Aetherinox
|
#
|
||||||
# @url https://github.com/Aetherinox
|
# @notes skips title changes if the author of the PR is renovate[bat]
|
||||||
|
#
|
||||||
|
# @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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/issues-scan.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/issues-scan.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Issues › Scan"
|
name: "🎫 Issues › Scan"
|
||||||
@@ -38,8 +65,11 @@ env:
|
|||||||
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
|
||||||
BOT_NAME_1: EuropaServ
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
LABELS_JSON: |
|
LABELS_JSON: |
|
||||||
[
|
[
|
||||||
@@ -110,13 +140,14 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job [ Autoscan ]
|
# Job › Autoscan
|
||||||
# #
|
# #
|
||||||
|
|
||||||
pr-autoscan:
|
job-pr-autoscan:
|
||||||
|
name: 🎫 Issues › Autoscan
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
runs-on: apollo-x64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 7
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
actions: read
|
actions: read
|
||||||
@@ -195,15 +226,20 @@ jobs:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Otherwise return issue number from commit
|
const data = (
|
||||||
return (
|
|
||||||
await github.rest.repos.listPullRequestsAssociatedWithCommit(
|
await github.rest.repos.listPullRequestsAssociatedWithCommit(
|
||||||
{
|
{
|
||||||
commit_sha: context.sha,
|
commit_sha: context.sha,
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
})
|
})
|
||||||
).data[ 0 ].number;
|
).data[0];
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
return data.number;
|
||||||
|
} else {
|
||||||
|
return '32';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result-encoding: string
|
result-encoding: string
|
||||||
|
|
||||||
@@ -228,6 +264,7 @@ jobs:
|
|||||||
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 }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: "refs/pull/${{ steps.task_autocheck_issue_num_set.outputs.result }}/merge"
|
ref: "refs/pull/${{ steps.task_autocheck_issue_num_set.outputs.result }}/merge"
|
||||||
|
|
||||||
@@ -252,7 +289,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
📄 Get changed files
|
📄 Get changed files
|
||||||
id: task_autocheck_changed_files_get
|
id: task_autocheck_changed_files_get
|
||||||
uses: tj-actions/changed-files@v45
|
uses: tj-actions/changed-files@v46
|
||||||
with:
|
with:
|
||||||
separator: ","
|
separator: ","
|
||||||
|
|
||||||
@@ -298,16 +335,131 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
github-token: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
script: |
|
script: |
|
||||||
|
console.log('Running Autoscan')
|
||||||
|
console.log(JSON.stringify(context, null, 4));
|
||||||
|
console.log(JSON.stringify(github, null, 4));
|
||||||
|
let ct = context;
|
||||||
|
|
||||||
|
/* #
|
||||||
|
# Example PR used for local act testing
|
||||||
|
# Uncomment to use in local env
|
||||||
|
#
|
||||||
|
# can be tested using act:
|
||||||
|
# - https://github.com/nektos/act
|
||||||
|
# command:
|
||||||
|
# git pull https://github.com/username/repo
|
||||||
|
# act -W .github/workflows/issues-scan.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/issues-scan.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
|
# */
|
||||||
|
|
||||||
|
/*
|
||||||
|
ct = {
|
||||||
|
"issue": {
|
||||||
|
"number": 32
|
||||||
|
},
|
||||||
|
"repo": {
|
||||||
|
"owner": "TheBinaryNinja",
|
||||||
|
"repo": "TVApp2"
|
||||||
|
},
|
||||||
|
"payload": {
|
||||||
|
"action": "synchronize",
|
||||||
|
"after": "f087c5bea8800f41018ef328463531ea247547ef",
|
||||||
|
"before": "a8bdd791b80b2fbb78169234690ccb61b9d014f1",
|
||||||
|
"number": 32,
|
||||||
|
"organization": {
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/200161462?v=4",
|
||||||
|
"events_url": "https://api.github.com/orgs/TheBinaryNinja/events",
|
||||||
|
"hooks_url": "https://api.github.com/orgs/TheBinaryNinja/hooks",
|
||||||
|
"issues_url": "https://api.github.com/orgs/TheBinaryNinja/issues",
|
||||||
|
"login": "TheBinaryNinja",
|
||||||
|
"members_url": "https://api.github.com/orgs/TheBinaryNinja/members{/member}",
|
||||||
|
"public_members_url": "https://api.github.com/orgs/TheBinaryNinja/public_members{/member}",
|
||||||
|
"repos_url": "https://api.github.com/orgs/TheBinaryNinja/repos",
|
||||||
|
"url": "https://api.github.com/orgs/TheBinaryNinja"
|
||||||
|
},
|
||||||
|
"pull_request": {
|
||||||
|
"created_at": "2025-03-17T23:32:22Z",
|
||||||
|
"updated_at": "2025-03-17T23:32:22Z",
|
||||||
|
"url": "https://api.github.com/repos/TheBinaryNinja/tvapp2",
|
||||||
|
"title": "Test PR Workflow",
|
||||||
|
"head": {
|
||||||
|
"ref": "main"
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
"ref": "main"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"login": "Aetherinox"
|
||||||
|
},
|
||||||
|
"labels": [
|
||||||
|
{
|
||||||
|
"color": "146b4a",
|
||||||
|
"default": false,
|
||||||
|
"description": "Ready to be reviewed",
|
||||||
|
"id": 7821944832,
|
||||||
|
"name": "AC › Passed",
|
||||||
|
"node_id": "LA_kwDONW-GkM8AAAAB0jloAA",
|
||||||
|
"url": "https://api.github.com/repos/TheBinaryNinja/tvapp2/labels/AC%20%E2%80%BA%20Passed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "8F1784",
|
||||||
|
"default": false,
|
||||||
|
"description": "Normal pull request",
|
||||||
|
"id": 7821944963,
|
||||||
|
"name": "Type ◦ Pull Request",
|
||||||
|
"node_id": "LA_kwDONW-GkM8AAAAB0jlogw",
|
||||||
|
"url": "https://api.github.com/repos/TheBinaryNinja/tvapp2/labels/Type%20%E2%97%A6%20Pull%20Request"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"eventName": "pull_request_target",
|
||||||
|
"sha": "c938f7a21247f69b29cf352d0c6890a63f260d47",
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"workflow": "🎫 Issues › Scan",
|
||||||
|
"action": "task_autocheck_run",
|
||||||
|
"actor": "renovate[bot]",
|
||||||
|
"job": "job-pr-autoscan",
|
||||||
|
"runNumber": 45,
|
||||||
|
"runId": 13911964505,
|
||||||
|
"apiUrl": "https://api.github.com",
|
||||||
|
"serverUrl": "https://github.com",
|
||||||
|
"graphqlUrl": "https://api.github.com/graphql"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #
|
||||||
|
# if local env ct isn't used, set ct to context for production
|
||||||
|
# */
|
||||||
|
|
||||||
|
if (!ct) {
|
||||||
|
ct = context;
|
||||||
|
}
|
||||||
|
|
||||||
const fs = require( 'fs' );
|
const fs = require( 'fs' );
|
||||||
const escape_html = ( unsafe ) => unsafe.replace( /&/g, '&' ).replace( /</g, '<' ).replace( />/g, '>' ).replace( /"/g, '"' ).replace( /'/g, ''' );
|
const escape_html = ( unsafe ) => unsafe.replace( /&/g, '&' ).replace( /</g, '<' ).replace( />/g, '>' ).replace( /"/g, '"' ).replace( /'/g, ''' );
|
||||||
const labels = [];
|
const labels = [];
|
||||||
|
|
||||||
|
/* #
|
||||||
|
# Get existing labels and add to list
|
||||||
|
# */
|
||||||
|
|
||||||
|
const labelsExisting = await github.rest.issues.listLabelsOnIssue({
|
||||||
|
issue_number: ct.issue.number,
|
||||||
|
owner: ct.repo.owner,
|
||||||
|
repo: ct.repo.repo
|
||||||
|
})
|
||||||
|
|
||||||
|
labelsExisting.data.forEach(({ name }) => {
|
||||||
|
labels.push(name);
|
||||||
|
});
|
||||||
|
|
||||||
const files_List = `${{ steps.task_autocheck_changed_files_get.outputs.all_changed_files }}` || ''
|
const files_List = `${{ steps.task_autocheck_changed_files_get.outputs.all_changed_files }}` || ''
|
||||||
const files_Array = files_List.split(',')
|
const files_Array = files_List.split(',')
|
||||||
const branch_ref = `${ context.payload.pull_request.head.ref }`
|
const branch_ref = `${ ct.payload.pull_request.head.ref }`
|
||||||
|
|
||||||
let message = [ "\n<br />\n" ]
|
let message = [ "\n<br />\n" ]
|
||||||
message.push ( "## Automatic Self-Check - #" + context.issue.number + "\n" );
|
message.push ( "## Automatic Self-Check - #" + ct.issue.number + "\n" );
|
||||||
message.push ( `The details of our automated scan for your pull request are listed below. If our scan detected errors, they must be corrected before this pull request will be advanced to the review stage:\n` );
|
message.push ( `The details of our automated scan for your pull request are listed below. If our scan detected errors, they must be corrected before this pull request will be advanced to the review stage:\n` );
|
||||||
message.push ( "\n<br />\n\n---\n\n<br />\n\n" );
|
message.push ( "\n<br />\n\n---\n\n<br />\n\n" );
|
||||||
message.push ( "### About\nThis pull request includes the following information:" );
|
message.push ( "### About\nThis pull request includes the following information:" );
|
||||||
@@ -315,7 +467,7 @@ jobs:
|
|||||||
let bHasError = false;
|
let bHasError = false;
|
||||||
let bHasWarning = false;
|
let bHasWarning = false;
|
||||||
|
|
||||||
let date = new Date( `${ context.payload.pull_request.created_at }` );
|
let date = new Date( `${ ct.payload.pull_request.created_at }` );
|
||||||
date.toISOString( )
|
date.toISOString( )
|
||||||
|
|
||||||
const actor = '${{ github.actor }}';
|
const actor = '${{ github.actor }}';
|
||||||
@@ -341,20 +493,20 @@ jobs:
|
|||||||
|
|
||||||
let date_created = dateTimeformat( date ) + " UTC";
|
let date_created = dateTimeformat( date ) + " UTC";
|
||||||
|
|
||||||
/*
|
/* #
|
||||||
context.payload.pull_request.base.repo.owner.login
|
# ct.payload.pull_request.base.repo.owner.login
|
||||||
*/
|
# */
|
||||||
|
|
||||||
let md_table =
|
let md_table =
|
||||||
`
|
`
|
||||||
| Category | Value |
|
| Category | Value |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Title | [ ` + context.payload.pull_request.title + ` ](https://github.com/` + context.repo.owner + `/` + context.repo.repo + `/pull/` + context.payload.pull_request.number + `) |
|
| Title | [ ` + ct.payload.pull_request.title + ` ](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `/pull/` + ct.payload.pull_request.number + `) |
|
||||||
| Created | [ ` + date_created + ` ](https://worldtimebuddy.com) |
|
| Created | [ ` + date_created + ` ](https://worldtimebuddy.com) |
|
||||||
| ID | ` + context.payload.pull_request.html_url + ` |
|
| ID | ` + ct.payload.pull_request.html_url + ` |
|
||||||
| Author | [ ` + context.payload.pull_request.user.login + ` ](https://github.com/` + context.repo.owner + `/) |
|
| Author | [ ` + ct.payload.pull_request.user.login + ` ](https://github.com/` + ct.repo.owner + `/) |
|
||||||
| Repo | [ ` + context.repo.repo + ` ](https://github.com/` + context.repo.owner + `/` + context.repo.repo + `) |
|
| Repo | [ ` + ct.repo.repo + ` ](https://github.com/` + ct.repo.owner + `/` + ct.repo.repo + `) |
|
||||||
| Branch | [ ` + context.payload.pull_request.head.ref + `](https://github.com/` + context.repo.owner + `/` + context.repo.repo + `/tree/` + context.payload.pull_request.head.ref + `) ⇁ [ ` + context.payload.pull_request.base.ref + `](https://github.com/` + context.repo.owner + `/` + context.repo.repo + `/tree/` + context.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_autocheck_changed_files_get.outputs.added_files_count }} |
|
||||||
| Modified Files | ${{ steps.task_autocheck_changed_files_get.outputs.all_modified_files_count }} |
|
| Modified Files | ${{ steps.task_autocheck_changed_files_get.outputs.all_modified_files_count }} |
|
||||||
| Renamed Files | ${{ steps.task_autocheck_changed_files_get.outputs.renamed_files_count }} |
|
| Renamed Files | ${{ steps.task_autocheck_changed_files_get.outputs.renamed_files_count }} |
|
||||||
@@ -389,12 +541,14 @@ jobs:
|
|||||||
|
|
||||||
const type_dependency =
|
const type_dependency =
|
||||||
[
|
[
|
||||||
"dependabot/npm_and_yarn"
|
"dependabot/npm_and_yarn",
|
||||||
|
"renovate/github_actions"
|
||||||
];
|
];
|
||||||
|
|
||||||
const type_gitaction =
|
const type_gitaction =
|
||||||
[
|
[
|
||||||
"dependabot/github_actions"
|
"dependabot/github_actions",
|
||||||
|
"renovate/github_actions"
|
||||||
];
|
];
|
||||||
|
|
||||||
const files_skipList =
|
const files_skipList =
|
||||||
@@ -715,7 +869,7 @@ jobs:
|
|||||||
if ( bHasError == true )
|
if ( bHasError == true )
|
||||||
{
|
{
|
||||||
labels.push( "${{ env.LABEL_CHECK_STATUS_FAILED }}" );
|
labels.push( "${{ env.LABEL_CHECK_STATUS_FAILED }}" );
|
||||||
core.setFailed( "Pull Request Failed Autocheck: " + context.issue.number + ": " + context.payload.pull_request.title + "." );
|
core.setFailed( "Pull Request Failed Autocheck: " + ct.issue.number + ": " + ct.payload.pull_request.title + "." );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -729,21 +883,21 @@ jobs:
|
|||||||
change pr title
|
change pr title
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const pr_title = `${ context.payload.pull_request.title }`;
|
const pr_title = `${ ct.payload.pull_request.title }`;
|
||||||
const pr_title_append = `PR ${ context.issue.number }:`;
|
const pr_title_append = `PR ${ ct.issue.number }:`;
|
||||||
|
|
||||||
if ( !pr_title.startsWith( pr_title_append ) )
|
if ( !pr_title.startsWith( pr_title_append ) && actor != "${{ env.BOT_NAME_RENOVATE }}" )
|
||||||
{
|
{
|
||||||
await github.rest.pulls.update(
|
await github.rest.pulls.update(
|
||||||
{
|
{
|
||||||
owner: context.repo.owner,
|
owner: ct.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: ct.repo.repo,
|
||||||
pull_number: context.issue.number,
|
pull_number: ct.issue.number,
|
||||||
title: `${ pr_title_append } ${ context.payload.pull_request.title }`
|
title: `${ pr_title_append } ${ ct.payload.pull_request.title }`
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !context.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_CHANGES_REQ }}" ).length > 0 )
|
if ( !ct.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_CHANGES_REQ }}" ).length > 0 )
|
||||||
labels.push( "${{ env.LABEL_CHECK_REVIEW_READY }}" );
|
labels.push( "${{ env.LABEL_CHECK_REVIEW_READY }}" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,24 +908,24 @@ jobs:
|
|||||||
const bGitaction = type_gitaction.some( s => s.includes( branch_ref ) || branch_ref.includes( s ) );
|
const bGitaction = type_gitaction.some( s => s.includes( branch_ref ) || branch_ref.includes( s ) );
|
||||||
const bDependency = type_dependency.some( s => s.includes( branch_ref ) || branch_ref.includes( s ) );
|
const bDependency = type_dependency.some( s => s.includes( branch_ref ) || branch_ref.includes( s ) );
|
||||||
|
|
||||||
if ( actor == "${{ env.BOT_NAME_DEPENDABOT }}" && bDependency )
|
if ( actor == "${{ env.BOT_NAME_DEPENDABOT }}" && bDependency || actor == "${{ env.BOT_NAME_RENOVATE }}" && bDependency )
|
||||||
labels.push( "${{ env.LABEL_TYPE_DEPENDENCY }}" );
|
labels.push( "${{ env.LABEL_TYPE_DEPENDENCY }}" );
|
||||||
else if ( actor == "${{ env.BOT_NAME_DEPENDABOT }}" && bGitaction )
|
else if ( actor == "${{ env.BOT_NAME_DEPENDABOT }}" && bGitaction || actor == "${{ env.BOT_NAME_RENOVATE }}" && bGitaction )
|
||||||
labels.push( "${{ env.LABEL_TYPE_GITACTION }}" );
|
labels.push( "${{ env.LABEL_TYPE_GITACTION }}" );
|
||||||
|
|
||||||
if ( context.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_CHANGES_REQ }}" ).length > 0 )
|
if ( ct.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_CHANGES_REQ }}" ).length > 0 )
|
||||||
labels.push( "${{ env.LABEL_CHECK_CHANGES_REQ }}" );
|
labels.push( "${{ env.LABEL_CHECK_CHANGES_REQ }}" );
|
||||||
|
|
||||||
if (context.payload.pull_request.labels.filter(label => label.name === "${{ env.LABEL_CHECK_REBASE_REQ }}" ).length > 0 )
|
if (ct.payload.pull_request.labels.filter(label => label.name === "${{ env.LABEL_CHECK_REBASE_REQ }}" ).length > 0 )
|
||||||
labels.push( "${{ env.LABEL_CHECK_REBASE_REQ }}" );
|
labels.push( "${{ env.LABEL_CHECK_REBASE_REQ }}" );
|
||||||
|
|
||||||
if ( context.payload.pull_request.labels.filter(label => label.name === "${{ env.LABEL_CHECK_SECURITY_ERR }}" ).length > 0 )
|
if ( ct.payload.pull_request.labels.filter(label => label.name === "${{ env.LABEL_CHECK_SECURITY_ERR }}" ).length > 0 )
|
||||||
labels.push( "${{ env.LABEL_CHECK_SECURITY_ERR }}" );
|
labels.push( "${{ env.LABEL_CHECK_SECURITY_ERR }}" );
|
||||||
|
|
||||||
if (context.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_STATUS_CHGMADE }}" ).length > 0 )
|
if (ct.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_STATUS_CHGMADE }}" ).length > 0 )
|
||||||
labels.push( "${{ env.LABEL_CHECK_STATUS_CHGMADE }}" );
|
labels.push( "${{ env.LABEL_CHECK_STATUS_CHGMADE }}" );
|
||||||
|
|
||||||
if ( context.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_SCAN_SKIPPED }}" ).length > 0 )
|
if ( ct.payload.pull_request.labels.filter( label => label.name === "${{ env.LABEL_CHECK_SCAN_SKIPPED }}" ).length > 0 )
|
||||||
labels.push( "${{ env.LABEL_CHECK_SCAN_SKIPPED }}" );
|
labels.push( "${{ env.LABEL_CHECK_SCAN_SKIPPED }}" );
|
||||||
|
|
||||||
labels.push( "${{ env.LABEL_TYPE_PR }}" );
|
labels.push( "${{ env.LABEL_TYPE_PR }}" );
|
||||||
@@ -782,9 +936,9 @@ jobs:
|
|||||||
|
|
||||||
await github.rest.issues.setLabels(
|
await github.rest.issues.setLabels(
|
||||||
{
|
{
|
||||||
issue_number: context.issue.number,
|
issue_number: ct.issue.number,
|
||||||
owner: context.repo.owner,
|
owner: ct.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: ct.repo.repo,
|
||||||
labels,
|
labels,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
@@ -794,9 +948,9 @@ jobs:
|
|||||||
|
|
||||||
await github.rest.issues.createComment(
|
await github.rest.issues.createComment(
|
||||||
{
|
{
|
||||||
issue_number: context.issue.number,
|
issue_number: ct.issue.number,
|
||||||
owner: context.repo.owner,
|
owner: ct.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: ct.repo.repo,
|
||||||
body: message.join('\n'),
|
body: message.join('\n'),
|
||||||
} );
|
} );
|
||||||
|
|
||||||
@@ -819,7 +973,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Success)
|
🔔 Send Discord Webhook Message (Success)
|
||||||
id: task_autocheck_notify_discord_success
|
id: task_autocheck_notify_discord_success
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -870,7 +1024,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Failure)
|
🔔 Send Discord Webhook Message (Failure)
|
||||||
id: task_autocheck_notify_discord_failure
|
id: task_autocheck_notify_discord_failure
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
|
|||||||
112
.github/workflows/issues-stale.yml
vendored
@@ -1,27 +1,51 @@
|
|||||||
# #
|
# #
|
||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @desc creates repository labels if they are not yet installed
|
|
||||||
# issues marked as stale after 30 days, given tag Status 𐄂 Stale
|
|
||||||
# inactive issues closed after 180 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 closed 7 days after being marked stale, given tag Status 𐄂 Autoclosed
|
|
||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage creates repository labels if they are not yet installed
|
||||||
|
# issues marked as stale after 30 days, given tag Status 𐄂 Stale
|
||||||
|
# inactive issues closed after 180 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 closed 7 days after being marked stale, given tag Status 𐄂 Autoclosed
|
||||||
#
|
#
|
||||||
# This Github action must be activated manually. This workflow script will do the
|
# @notes This Github action must be activated manually. This workflow script will do the following:
|
||||||
# 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.
|
||||||
#
|
#
|
||||||
# - Workflow will `autoclose` pr or issues which haven't had action in `365 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.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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/issues-stale.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/issues-stale.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Issues › Stale"
|
name: "🎫 Issues › Stale"
|
||||||
@@ -41,28 +65,32 @@ 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_URGENT: "⚠ Urgent"
|
||||||
|
|
||||||
|
ASSIGN_USER: Aetherinox
|
||||||
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
BOT_NAME_1: EuropaServ
|
|
||||||
BOT_NAME_DEPENDABOT: dependabot[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" },
|
||||||
@@ -141,8 +169,7 @@ jobs:
|
|||||||
job-labels-create:
|
job-labels-create:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Verify Existing
|
🎫 Labels › Verify Existing
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
@@ -218,8 +245,7 @@ jobs:
|
|||||||
job-issues-nolabel:
|
job-issues-nolabel:
|
||||||
name: >-
|
name: >-
|
||||||
🎫 Labels › Assign Missing
|
🎫 Labels › Assign Missing
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
needs: job-labels-create
|
needs: job-labels-create
|
||||||
steps:
|
steps:
|
||||||
@@ -587,8 +613,7 @@ jobs:
|
|||||||
job-issues-stale:
|
job-issues-stale:
|
||||||
name: >-
|
name: >-
|
||||||
💤 Check › Stale
|
💤 Check › Stale
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
@@ -631,8 +656,7 @@ jobs:
|
|||||||
job-issues-lock:
|
job-issues-lock:
|
||||||
name: >-
|
name: >-
|
||||||
🔒 Check › Inactive
|
🔒 Check › Inactive
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
runs-on: apollo-x64
|
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
needs:
|
needs:
|
||||||
- job-labels-create
|
- job-labels-create
|
||||||
|
|||||||
41
.github/workflows/labels-clean.yml
vendored
@@ -4,10 +4,33 @@
|
|||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
#
|
#
|
||||||
# This Github action must be activated manually. This workflow script will do the
|
# @notes This Github action must be activated manually. This workflow script will do the following:
|
||||||
# following:
|
# - Remove all existing labels in repository
|
||||||
#
|
#
|
||||||
# - Remove all existing labels in repository
|
# @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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/labels-clean.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/labels-clean.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Labels › Remove"
|
name: "🎫 Labels › Remove"
|
||||||
@@ -25,8 +48,12 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BOT_NAME_1: EuropaServ
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
LABELS_JSON: |
|
LABELS_JSON: |
|
||||||
[
|
[
|
||||||
{ "name": "bug", "color": "8F1784", "description": "Default github label" },
|
{ "name": "bug", "color": "8F1784", "description": "Default github label" },
|
||||||
@@ -230,7 +257,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Success)
|
🔔 Send Discord Webhook Message (Success)
|
||||||
id: task_label_notify_discord_success
|
id: task_label_notify_discord_success
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -266,7 +293,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Failure)
|
🔔 Send Discord Webhook Message (Failure)
|
||||||
id: task_label_notify_discord_failure
|
id: task_label_notify_discord_failure
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
|
|||||||
58
.github/workflows/labels-create.yml
vendored
@@ -1,22 +1,46 @@
|
|||||||
# #
|
# #
|
||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @desc manually activated workflow to create issue labels
|
|
||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage manually activated workflow to create issue labels
|
||||||
#
|
#
|
||||||
# This Github action must be activated manually. This workflow script will do the
|
# @notes This Github action must be activated manually. This workflow script will do the following:
|
||||||
# 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.
|
||||||
#
|
#
|
||||||
# - Workflow will `autoclose` pr or issues which haven't had action in `365 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.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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/labels-create.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/labels-create.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "🎫 Labels › Create"
|
name: "🎫 Labels › Create"
|
||||||
@@ -34,8 +58,12 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BOT_NAME_1: EuropaServ
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[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" },
|
||||||
@@ -217,7 +245,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Success)
|
🔔 Send Discord Webhook Message (Success)
|
||||||
id: task_label_notify_discord_success
|
id: task_label_notify_discord_success
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
@@ -253,7 +281,7 @@ jobs:
|
|||||||
- name: >-
|
- name: >-
|
||||||
🔔 Send Discord Webhook Message (Failure)
|
🔔 Send Discord Webhook Message (Failure)
|
||||||
id: task_label_notify_discord_failure
|
id: task_label_notify_discord_failure
|
||||||
uses: tsickert/discord-webhook@v6.0.0
|
uses: tsickert/discord-webhook@v7.0.0
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
username: 'Io'
|
username: 'Io'
|
||||||
|
|||||||
316
.github/workflows/release.yml
vendored
@@ -1,12 +1,37 @@
|
|||||||
# #
|
# #
|
||||||
# @type github workflow
|
# @type github workflow
|
||||||
# @desc publishes a new release on Github
|
|
||||||
# @author Aetherinox
|
# @author Aetherinox
|
||||||
# @url https://github.com/Aetherinox
|
# @url https://github.com/Aetherinox
|
||||||
|
# @usage publishes a new release on Github
|
||||||
|
#
|
||||||
|
# @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_BINARYNINJA_TOKEN org github personal access token (fine-grained)
|
||||||
|
# secrets.ORG_BINARYNINJA_TOKEN_CL org github personal access token (classic)
|
||||||
|
# secrets.ORG_BINARYNINJA_DOCKERHUB_TOKEN org dockerhub secret
|
||||||
|
# secrets.ORG_BINARYNINJA_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.BINARYSERV_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_TVAPP2_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
|
||||||
|
#
|
||||||
|
# @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/labels-create.yml -P ubuntu-latest=catthehacker/ubuntu:full-22.04
|
||||||
|
# act -W .github/workflows/labels-create.yml -s TOKEN_CL=XXXXXXXXXX --pull=false
|
||||||
# #
|
# #
|
||||||
|
|
||||||
name: "📦 Release › Github"
|
name: '📦 Release › Github'
|
||||||
run-name: "📦 Release › Github"
|
run-name: '📦 Release › Github'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Triggers
|
# Triggers
|
||||||
@@ -22,10 +47,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
PROJECT_NAME:
|
PROJECT_NAME:
|
||||||
description: "📦 Name of App"
|
description: '📦 Name of App'
|
||||||
required: true
|
required: true
|
||||||
default: 'tvapp2'
|
default: 'tvapp2'
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# ENABLE: the changelog generated in releases tab will only display single commits.
|
# ENABLE: the changelog generated in releases tab will only display single commits.
|
||||||
@@ -33,10 +58,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
CHANGELOG_MODE_COMMIT:
|
CHANGELOG_MODE_COMMIT:
|
||||||
description: "📑 Use Commits Instead of PRs"
|
description: '📑 Use Commits Instead of PRs'
|
||||||
required: true
|
required: true
|
||||||
default: true
|
default: true
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# ENABLE: Will show all types of commits, including uncategorized
|
# ENABLE: Will show all types of commits, including uncategorized
|
||||||
@@ -46,10 +71,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
SHOW_UNCATEGORIZED:
|
SHOW_UNCATEGORIZED:
|
||||||
description: "🗂️ Show Uncategorized Commits"
|
description: '🗂️ Show Uncategorized Commits'
|
||||||
required: true
|
required: true
|
||||||
default: false
|
default: false
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# ENABLE: released version will be marked as pre-release
|
# ENABLE: released version will be marked as pre-release
|
||||||
@@ -57,10 +82,10 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
PRERELEASE:
|
PRERELEASE:
|
||||||
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
|
# Release Candidate version number
|
||||||
@@ -69,23 +94,26 @@ on:
|
|||||||
# #
|
# #
|
||||||
|
|
||||||
VERSION_RC:
|
VERSION_RC:
|
||||||
description: "🧪 RC (Pre-release) Ver (tvapp2-rc.v1)"
|
description: '🧪 RC (Pre-release) Ver (tvapp2-rc.v1)'
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
default: "1"
|
default: '1'
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# environment variables
|
# environment variables
|
||||||
# #
|
# #
|
||||||
|
|
||||||
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: true
|
||||||
SHOW_UNCATEGORIZED: false
|
SHOW_UNCATEGORIZED: false
|
||||||
PRERELEASE: false
|
PRERELEASE: false
|
||||||
VERSION_RC: '1'
|
VERSION_RC: '1'
|
||||||
BOT_NAME_1: EuropaServ
|
ASSIGN_USER: Aetherinox
|
||||||
BOT_NAME_DEPENDABOT: dependabot[bot]
|
BOT_NAME_1: EuropaServ
|
||||||
|
BOT_NAME_2: BinaryServ
|
||||||
|
BOT_NAME_DEPENDABOT: dependabot[bot]
|
||||||
|
BOT_NAME_RENOVATE: renovate[bot]
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Jobs
|
# Jobs
|
||||||
@@ -112,7 +140,7 @@ jobs:
|
|||||||
# Initialize › Start
|
# Initialize › Start
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "✅ Start"
|
- name: '✅ Start'
|
||||||
id: task_initialize_start
|
id: task_initialize_start
|
||||||
run: |
|
run: |
|
||||||
echo "Starting build"
|
echo "Starting build"
|
||||||
@@ -134,24 +162,28 @@ jobs:
|
|||||||
# Initialize › Checkout
|
# Initialize › Checkout
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "☑️ Checkout"
|
- name: '☑️ Checkout'
|
||||||
id: task_initialize_checkout
|
id: task_initialize_checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Initialize › Get version from package.json VERSION value
|
# Initialize › Set › Package.json › Version
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "👁️🗨️ Package Version › Set"
|
- name: '👁️🗨️ Package Version › Set'
|
||||||
id: task_initialize_package_getversion
|
id: task_initialize_package_getversion
|
||||||
working-directory: ./tvapp2
|
working-directory: ./tvapp2
|
||||||
run: |
|
run: |
|
||||||
VER=$(cat package.json | jq -r '.version')
|
VER=$(cat package.json | jq -r '.version')
|
||||||
echo "PACKAGE_VERSION=$VER" >> $GITHUB_OUTPUT
|
echo "PACKAGE_VERSION=$VER" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: "👁️🗨️ Package Version › Get"
|
# #
|
||||||
|
# Initialize › Get › Package.json › Version
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '👁️🗨️ Package Version › Get'
|
||||||
id: task_initialize_package_version_get
|
id: task_initialize_package_version_get
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}"
|
echo "VERSION: ${{ steps.task_initialize_package_getversion.outputs.PACKAGE_VERSION }}"
|
||||||
@@ -179,11 +211,11 @@ jobs:
|
|||||||
# Release › Checkout
|
# Release › Checkout
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "☑️ Checkout"
|
- name: '☑️ Checkout'
|
||||||
id: task_release_checkout
|
id: task_release_checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Release › Set Env Variables
|
# Release › Set Env Variables
|
||||||
@@ -202,7 +234,7 @@ jobs:
|
|||||||
# Release › Print Version Debug
|
# Release › Print Version Debug
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🪪 Test Next Job Version"
|
- name: '🪪 Test Next Job Version'
|
||||||
id: task_release_debug_print_ver
|
id: task_release_debug_print_ver
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION: ${{ env.PACKAGE_VERSION }}"
|
echo "VERSION: ${{ env.PACKAGE_VERSION }}"
|
||||||
@@ -211,11 +243,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 }}
|
||||||
|
|
||||||
@@ -223,39 +256,39 @@ jobs:
|
|||||||
# Release › Execute npm generate so that a uuid and guid can be created
|
# Release › Execute npm generate so that a uuid and guid can be created
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🪪 Generate IDs"
|
- name: '🪪 Generate IDs'
|
||||||
id: task_release_npm_env_generate
|
id: task_release_npm_env_generate
|
||||||
working-directory: ./tvapp2
|
working-directory: ./tvapp2
|
||||||
run: |
|
run: |
|
||||||
npm run root:generate
|
npm run root:generate
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# .ENV › Get
|
# Release › .ENV › Get
|
||||||
# Get guid and uuid from env variable generated by npm
|
# Get guid and uuid from env variable generated by npm
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🪪 .ENV › Get"
|
- name: '🪪 .ENV › Get'
|
||||||
id: task_release_dotenv_get
|
id: task_release_dotenv_get
|
||||||
uses: falti/dotenv-action@v1
|
uses: falti/dotenv-action@v1
|
||||||
with:
|
with:
|
||||||
path: "./tvapp2/.env"
|
path: "./tvapp2/.env"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# .ENV › Print (Debug)
|
# Release › .ENV › Print (Debug)
|
||||||
# Show guid and uuid from env variable generated by npm
|
# Show guid and uuid from env variable generated by npm
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🪪 .ENV › Read"
|
- name: '🪪 .ENV › Read'
|
||||||
id: task_dotenv_debug_print
|
id: task_dotenv_debug_print
|
||||||
run: |
|
run: |
|
||||||
echo "GUID: ${{ steps.task_release_dotenv_get.outputs.GUID }}"
|
echo "GUID: ${{ steps.task_release_dotenv_get.outputs.GUID }}"
|
||||||
echo "UUID: ${{ steps.task_release_dotenv_get.outputs.UUID }}"
|
echo "UUID: ${{ steps.task_release_dotenv_get.outputs.UUID }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Build Project & Create Zip
|
# 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.PRERELEASE, false ) }}
|
||||||
run: |
|
run: |
|
||||||
@@ -267,7 +300,11 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
|
|
||||||
- name: "🔨 Build › RC ( ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip )"
|
# #
|
||||||
|
# Release › Build › Release Candidate
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🔨 Build › RC ( ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}-rc.${{ inputs.VERSION_RC }}.zip )'
|
||||||
id: task_release_build_rc
|
id: task_release_build_rc
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
||||||
run: |
|
run: |
|
||||||
@@ -280,14 +317,14 @@ jobs:
|
|||||||
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
NODE_AUTH_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Tag ]: Pre Create
|
# Release › Tag › Pre Create
|
||||||
#
|
#
|
||||||
# in order to use the changelog github action, you must pre-create the tag otherwise
|
# in order to use the changelog github action, you must pre-create the tag otherwise
|
||||||
# the changelog action will have no idea what tag you are going to be creating and
|
# the changelog action will have no idea what tag you are going to be creating and
|
||||||
# the list of commits will not be for the correct release.
|
# the list of commits will not be for the correct release.
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🔖 Tag › Pre Create ${{ env.PACKAGE_VERSION }}"
|
- name: '🔖 Tag › Pre Create ${{ env.PACKAGE_VERSION }}'
|
||||||
id: task_release_tag_create
|
id: task_release_tag_create
|
||||||
uses: rickstaa/action-create-tag@v1
|
uses: rickstaa/action-create-tag@v1
|
||||||
with:
|
with:
|
||||||
@@ -298,22 +335,22 @@ jobs:
|
|||||||
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
gpg_passphrase: ${{ secrets.ADMINSERV_GPG_PASSPHRASE }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Tag ]: Confirm
|
# Release › Tag › Confirm
|
||||||
#
|
#
|
||||||
# check if tag already exists
|
# check if tag already exists
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🔖 Tag › Confirm ${{ env.PACKAGE_VERSION }}"
|
- name: '🔖 Tag › Confirm ${{ env.PACKAGE_VERSION }}'
|
||||||
id: task_release_tag_get
|
id: task_release_tag_get
|
||||||
run: |
|
run: |
|
||||||
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 }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Checksum › Generate
|
# 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.PRERELEASE, false ) }}
|
||||||
run: |
|
run: |
|
||||||
@@ -327,7 +364,11 @@ jobs:
|
|||||||
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
|
||||||
|
|
||||||
- name: "🆔 Checksum › RC"
|
# #
|
||||||
|
# Release › Checksum › Release Candidate
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '🆔 Checksum › RC'
|
||||||
id: task_release_checksum_rc_set
|
id: task_release_checksum_rc_set
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
||||||
run: |
|
run: |
|
||||||
@@ -342,19 +383,19 @@ jobs:
|
|||||||
echo "FILE_COMPOSE_ZIP=${filename_compose_zip}" >> $GITHUB_ENV
|
echo "FILE_COMPOSE_ZIP=${filename_compose_zip}" >> $GITHUB_ENV
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Checksum › Print
|
# Release › Checksum › Print
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🆔 Checksum › Print"
|
- name: '🆔 Checksum › Print'
|
||||||
id: task_release_checksum_st_get
|
id: task_release_checksum_st_get
|
||||||
run: |
|
run: |
|
||||||
echo ${{ env.SHA256SUM }}
|
echo "${{ env.SHA256SUM }}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Contributor Images
|
# Release › Contributor Images
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🥸 Contributors › Generate"
|
- name: '🥸 Contributors › Generate'
|
||||||
id: task_release_contribs_generate
|
id: task_release_contribs_generate
|
||||||
uses: jaywcjlove/github-action-contributors@main
|
uses: jaywcjlove/github-action-contributors@main
|
||||||
with:
|
with:
|
||||||
@@ -363,10 +404,10 @@ jobs:
|
|||||||
avatarSize: 42
|
avatarSize: 42
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Checksum › Add to ZIP file
|
# Release › Checksum › Add (Stable)
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "📦 Zip › Add Checksum › Stable"
|
- name: '📦 Zip › Add Checksum › Stable'
|
||||||
id: task_release_zip_st
|
id: task_release_zip_st
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, false ) }}
|
if: ${{ startsWith( inputs.PRERELEASE, false ) }}
|
||||||
run: |
|
run: |
|
||||||
@@ -374,7 +415,11 @@ jobs:
|
|||||||
zip -jr ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip SHA256SUMS.txt
|
zip -jr ${{ env.PROJECT_NAME }}-${{ env.PACKAGE_VERSION }}.zip SHA256SUMS.txt
|
||||||
ls
|
ls
|
||||||
|
|
||||||
- name: "📦 Zip › Add Checksum › RC"
|
# #
|
||||||
|
# Release › Checksum › Add (Release Candidate)
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📦 Zip › Add Checksum › RC'
|
||||||
id: task_release_zip_rc
|
id: task_release_zip_rc
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
||||||
run: |
|
run: |
|
||||||
@@ -383,24 +428,30 @@ jobs:
|
|||||||
ls
|
ls
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Changelog › Generate
|
# Release › 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: "📝 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: |
|
||||||
echo "TAG_LAST=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
|
echo "TAG_LAST=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
|
||||||
echo "COMMIT_LAST=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
echo "COMMIT_LAST=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: "📝 Changelog › Build (Categorized)"
|
# #
|
||||||
|
# Release › Changelog › Build (Categorized)
|
||||||
|
#
|
||||||
|
# generates a changelog from the github api. requires a TAG_LAST in order to figure
|
||||||
|
# out the changes made between the two versions.
|
||||||
|
#
|
||||||
|
# outputs:
|
||||||
|
# ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '📝 Changelog › Build (Categorized)'
|
||||||
id: task_release_changelog_categorized
|
id: task_release_changelog_categorized
|
||||||
if: ${{ startsWith( inputs.SHOW_UNCATEGORIZED, false ) }}
|
if: |
|
||||||
|
startsWith( inputs.SHOW_UNCATEGORIZED, false ) ||
|
||||||
|
startsWith( env.SHOW_UNCATEGORIZED, false )
|
||||||
uses: mikepenz/release-changelog-builder-action@v5
|
uses: mikepenz/release-changelog-builder-action@v5
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.ADMINSERV_TOKEN }}
|
token: ${{ secrets.ADMINSERV_TOKEN }}
|
||||||
@@ -408,7 +459,7 @@ jobs:
|
|||||||
#toTag: "${{ github.ref }}"
|
#toTag: "${{ github.ref }}"
|
||||||
configuration: ".github/changelog-configuration.json"
|
configuration: ".github/changelog-configuration.json"
|
||||||
ignorePreReleases: false
|
ignorePreReleases: false
|
||||||
commitMode: ${{ inputs.CHANGELOG_MODE_COMMIT }}
|
commitMode: ${{ inputs.CHANGELOG_MODE_COMMIT || env.CHANGELOG_MODE_COMMIT }}
|
||||||
fetchReleaseInformation: true
|
fetchReleaseInformation: true
|
||||||
fetchViaCommits: true
|
fetchViaCommits: true
|
||||||
configurationJson: |
|
configurationJson: |
|
||||||
@@ -419,14 +470,24 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
|
# Release › Changelog › Build (Uncategorized)
|
||||||
|
#
|
||||||
|
# generates a changelog from the github api. requires a TAG_LAST in order to figure
|
||||||
|
# out the changes made between the two versions.
|
||||||
|
#
|
||||||
|
# outputs:
|
||||||
|
# ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
#
|
||||||
# shows only categorized commits using the commit standards
|
# shows only categorized commits using the commit standards
|
||||||
# type(scope): description
|
# type(scope): description
|
||||||
# type: description
|
# type: description
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "📝 Changelog › Build (Uncategorized)"
|
- name: '📝 Changelog › Build (Uncategorized)'
|
||||||
id: task_release_changelog_uncategorized
|
id: task_release_changelog_uncategorized
|
||||||
if: ${{ startsWith( inputs.SHOW_UNCATEGORIZED, true ) }}
|
if: |
|
||||||
|
startsWith( inputs.SHOW_UNCATEGORIZED, true ) ||
|
||||||
|
startsWith( env.SHOW_UNCATEGORIZED, true )
|
||||||
uses: mikepenz/release-changelog-builder-action@v5
|
uses: mikepenz/release-changelog-builder-action@v5
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.ADMINSERV_TOKEN }}
|
token: ${{ secrets.ADMINSERV_TOKEN }}
|
||||||
@@ -434,7 +495,7 @@ jobs:
|
|||||||
#toTag: "${{ github.ref }}"
|
#toTag: "${{ github.ref }}"
|
||||||
configuration: ".github/changelog-configuration.json"
|
configuration: ".github/changelog-configuration.json"
|
||||||
ignorePreReleases: false
|
ignorePreReleases: false
|
||||||
commitMode: ${{ inputs.CHANGELOG_MODE_COMMIT }}
|
commitMode: ${{ inputs.CHANGELOG_MODE_COMMIT || env.CHANGELOG_MODE_COMMIT }}
|
||||||
fetchReleaseInformation: true
|
fetchReleaseInformation: true
|
||||||
fetchViaCommits: true
|
fetchViaCommits: true
|
||||||
configurationJson: |
|
configurationJson: |
|
||||||
@@ -445,32 +506,66 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Changelog › Fetch
|
# Release › Changelog › Convert step into ENV
|
||||||
|
#
|
||||||
|
# This is a requirement in order for the action mikepenz/release-changelog-builder-action@v5 to work properly.
|
||||||
|
# If you use special characters like quotes and tildes in your push comments, bash will have no way of knowing
|
||||||
|
# if it's part of the changelog, or code itself.
|
||||||
|
#
|
||||||
|
# By converting the step into an env var, we quote the text, and it fixes the issue.
|
||||||
|
#
|
||||||
|
# For every step that you need to print the changelog text, first define the env var
|
||||||
|
# env:
|
||||||
|
# CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
#
|
||||||
|
# Then you can call the changelog in the body / run command with
|
||||||
|
# echo "$CHANGELOG_CATEGORIZED"
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "📝 Changelog › Print (Categorized)"
|
- name: '🙊 Changelog › Step to Env › Categorized'
|
||||||
if: ${{ startsWith( inputs.SHOW_UNCATEGORIZED, false ) }}
|
id: task_release_changelog_escape_categorized
|
||||||
|
if: |
|
||||||
|
startsWith( inputs.SHOW_UNCATEGORIZED, false ) ||
|
||||||
|
startsWith( env.SHOW_UNCATEGORIZED, false )
|
||||||
|
env:
|
||||||
|
CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
run: |
|
run: |
|
||||||
echo "${{ steps.task_release_changelog_categorized.outputs.changelog }}"
|
echo "$CHANGELOG_CATEGORIZED"
|
||||||
|
|
||||||
- name: "📝 Changelog › Print (Uncategorized)"
|
- name: '🙊 Changelog › Step to Env › Uncategorized'
|
||||||
if: ${{ startsWith( inputs.SHOW_UNCATEGORIZED, true ) }}
|
id: task_release_changelog_escape_uncategorized
|
||||||
|
if: |
|
||||||
|
startsWith( inputs.SHOW_UNCATEGORIZED, true ) ||
|
||||||
|
startsWith( env.SHOW_UNCATEGORIZED, true )
|
||||||
|
env:
|
||||||
|
CHANGELOG_UNCATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
run: |
|
run: |
|
||||||
echo "${{ steps.task_release_changelog_uncategorized.outputs.changelog }}"
|
echo "$CHANGELOG_UNCATEGORIZED"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# [ Release ]: Post Release
|
# Release › List Tree
|
||||||
|
# #
|
||||||
|
|
||||||
|
- name: '⚙️ Debug › Tree Listing'
|
||||||
|
id: task_release_debug_tree
|
||||||
|
run: |
|
||||||
|
tree
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Post Release (Stable)
|
||||||
#
|
#
|
||||||
# outputs:
|
# outputs:
|
||||||
# [RELEASE ID]:
|
# [RELEASE ID]:
|
||||||
# ${{ steps.task_release_bundle_rc.outputs.id
|
# ${{ steps.task_release_bundle_rc.outputs.id
|
||||||
# ${{ steps.task_release_bundle_st.outputs.id
|
# ${{ steps.task_release_bundle_st.outputs.id
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🏳️ Post › Stable"
|
- name: '🏳️ Post › Stable'
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, false ) }}
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
id: task_release_bundle_st
|
id: task_release_bundle_st
|
||||||
|
if: |
|
||||||
|
startsWith( inputs.PRERELEASE, false ) ||
|
||||||
|
startsWith( env.PRERELEASE, false )
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN_CL }}
|
||||||
with:
|
with:
|
||||||
@@ -489,10 +584,21 @@ jobs:
|
|||||||
${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
${{ steps.task_release_changelog_uncategorized.outputs.changelog }}
|
${{ steps.task_release_changelog_uncategorized.outputs.changelog }}
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Release › Post Release (Release Candidate)
|
||||||
|
#
|
||||||
|
# outputs:
|
||||||
|
# [RELEASE ID]:
|
||||||
|
# ${{ steps.task_release_bundle_rc.outputs.id
|
||||||
|
# ${{ steps.task_release_bundle_st.outputs.id
|
||||||
|
# #
|
||||||
|
|
||||||
- name: "🏳️ Post › Release Candidate"
|
- name: "🏳️ Post › Release Candidate"
|
||||||
if: ${{ startsWith( inputs.PRERELEASE, true ) }}
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
id: task_release_bundle_rc
|
id: task_release_bundle_rc
|
||||||
|
if: |
|
||||||
|
startsWith( inputs.PRERELEASE, true ) ||
|
||||||
|
startsWith( env.PRERELEASE, true )
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.ADMINSERV_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -515,17 +621,27 @@ jobs:
|
|||||||
${{ steps.task_release_changelog_uncategorized.outputs.changelog }}
|
${{ steps.task_release_changelog_uncategorized.outputs.changelog }}
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Print Status
|
# Release › Print Status
|
||||||
|
#
|
||||||
|
# For every step that you need to print the changelog text, first define the env var
|
||||||
|
# env:
|
||||||
|
# CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
#
|
||||||
|
# Then you can call the changelog in the body / run command with
|
||||||
|
# echo "$CHANGELOG_CATEGORIZED"
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🎛️ Status › Print"
|
- name: "🎛️ Status › Print"
|
||||||
id: task_release_status_print
|
id: task_release_status_print
|
||||||
|
env:
|
||||||
|
CHANGELOG_CATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
|
CHANGELOG_UNCATEGORIZED: ${{ steps.task_release_changelog_categorized.outputs.changelog }}
|
||||||
run: |
|
run: |
|
||||||
echo "Printing Variables"
|
echo "Printing Variables"
|
||||||
echo
|
echo
|
||||||
echo "---- CHANGELOG ---------------------------------------------------------------"
|
echo "---- CHANGELOG ---------------------------------------------------------------"
|
||||||
echo "${{ steps.task_release_changelog_categorized.outputs.changelog }}"
|
echo "$CHANGELOG_CATEGORIZED"
|
||||||
echo "${{ steps.task_changelog_uncategorized.outputs.changelog }}"
|
echo "$CHANGELOG_UNCATEGORIZED"
|
||||||
echo "---- CHANGELOG ---------------------------------------------------------------"
|
echo "---- CHANGELOG ---------------------------------------------------------------"
|
||||||
echo ""
|
echo ""
|
||||||
echo ""
|
echo ""
|
||||||
@@ -539,7 +655,7 @@ jobs:
|
|||||||
echo "---- CHANGELOG ---------------------------------------------------------------"
|
echo "---- CHANGELOG ---------------------------------------------------------------"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Upload artifacts > release files
|
# Release › Upload Artifacts › Release Files
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
@@ -568,7 +684,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Complete › Download Artifacts
|
# Complete › Download Artifacts
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "📁 Download › Saved Artifacts"
|
- name: "📁 Download › Saved Artifacts"
|
||||||
@@ -576,7 +692,7 @@ jobs:
|
|||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Complete › Get publish timestamp
|
# Complete › Get publish timestamp
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: >-
|
- name: >-
|
||||||
@@ -589,7 +705,7 @@ jobs:
|
|||||||
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
echo "NOW_DOCKER_LABEL=$(date +'%Y%m%d')" >> $GITHUB_ENV
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job > Complete > Set ENVs
|
# Complete › Set ENVs
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🕛 Get Env Vars"
|
- name: "🕛 Get Env Vars"
|
||||||
@@ -602,7 +718,7 @@ jobs:
|
|||||||
echo "SHA_STABLE=${release_stable_sha256}" >> $GITHUB_ENV
|
echo "SHA_STABLE=${release_stable_sha256}" >> $GITHUB_ENV
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Job › Complete › Summary of publish
|
# Complete › Summary of publish
|
||||||
# #
|
# #
|
||||||
|
|
||||||
- name: "🆗 Completed: ${{ env.NOW }}"
|
- name: "🆗 Completed: ${{ env.NOW }}"
|
||||||
|
|||||||
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` | <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 -->
|
||||||
48
Dockerfile
@@ -19,12 +19,22 @@
|
|||||||
# 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 --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 .
|
||||||
# #
|
# #
|
||||||
|
|
||||||
FROM ghcr.io/aetherinox/alpine-base:3.20-amd64
|
# #
|
||||||
|
# FROM
|
||||||
|
# any args defined before FROM cannot be called after FROM and the ARE is classified outside the build process.
|
||||||
|
# You will have to re-define the arg after FROM to utilize it anywhere else in the build process.
|
||||||
|
#
|
||||||
|
# @ref https://docs.docker.com/reference/dockerfile/#understand-how-arg-and-from-interact
|
||||||
|
# #
|
||||||
|
|
||||||
|
ARG ARCH=amd64
|
||||||
|
FROM --platform=linux/${ARCH} ghcr.io/aetherinox/alpine-base:3.21
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Set Args
|
# Set Args
|
||||||
# #
|
# #
|
||||||
|
|
||||||
|
ARG ARCH=amd64
|
||||||
ARG BUILDDATE
|
ARG BUILDDATE
|
||||||
ARG VERSION
|
ARG VERSION
|
||||||
|
|
||||||
@@ -32,32 +42,42 @@ ARG VERSION
|
|||||||
# Set Labels
|
# Set Labels
|
||||||
# #
|
# #
|
||||||
|
|
||||||
LABEL maintainer="aetherinox, iFlip721"
|
LABEL org.opencontainers.image.authors="Aetherinox, iFlip721, Optx"
|
||||||
LABEL org.opencontainers.image.authors="aetherinox, iFlip721"
|
|
||||||
LABEL org.opencontainers.image.vendor="BinaryNinja"
|
LABEL org.opencontainers.image.vendor="BinaryNinja"
|
||||||
LABEL org.opencontainers.image.title="TVApp2"
|
LABEL org.opencontainers.image.title="TVApp2"
|
||||||
LABEL org.opencontainers.image.description="Automatic m3u and xml guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client."
|
LABEL org.opencontainers.image.description="Automatic m3u and xml guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client."
|
||||||
LABEL org.opencontainers.image.source="https://github.com/TheBinaryNinja/tvapp2"
|
LABEL org.opencontainers.image.source="https://github.com/thebinaryninja/tvapp2"
|
||||||
LABEL org.opencontainers.image.repo.1="https://github.com/TheBinaryNinja/tvapp2"
|
LABEL org.opencontainers.image.repo.1="https://github.com/thebinaryninja/tvapp2"
|
||||||
LABEL org.opencontainers.image.repo.2="https://git.binaryninja.net/BinaryNinja/tvapp2"
|
LABEL org.opencontainers.image.repo.2="https://git.binaryninja.net/binaryninja/tvapp2"
|
||||||
LABEL org.opencontainers.image.repo.3="https://github.com/aetherinox/docker-base-alpine"
|
LABEL org.opencontainers.image.repo.3="https://github.com/aetherinox/docker-base-alpine"
|
||||||
LABEL org.opencontainers.image.documentation="https://github.com/TheBinaryNinja/tvapp2/wiki"
|
LABEL org.opencontainers.image.documentation="https://thebinaryninja.github.io/tvapp2"
|
||||||
LABEL org.opencontainers.image.url="https://github.com/TheBinaryNinja/tvapp2/pkgs/container/tvapp2"
|
LABEL org.opencontainers.image.url="https://github.com/thebinaryninja/tvapp2/pkgs/container/tvapp2"
|
||||||
LABEL org.opencontainers.image.licenses="MIT"
|
LABEL org.opencontainers.image.licenses="MIT"
|
||||||
LABEL BUILDVERSION="TVApp2 v${VERSION} Build ${BUILDDATE}"
|
LABEL org.opencontainers.image.architecture="${ARCH}"
|
||||||
|
LABEL org.opencontainers.image.ref.name="main"
|
||||||
|
LABEL org.opencontainers.image.registry="local"
|
||||||
|
LABEL org.tvapp2.image.maintainers="Aetherinox, iFlip721, Optx"
|
||||||
|
LABEL org.tvapp2.image.build-version="Version:- ${VERSION} Date:- ${BUILDDATE}"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Set Env Var
|
# Set Env Var
|
||||||
# #
|
# #
|
||||||
|
|
||||||
ENV TZ="Etc/UTC"
|
ENV NODE_VERSION=22.8.0
|
||||||
ENV URL_REPO="https://git.binaryninja.net/BinaryNinja/"
|
|
||||||
ENV WEB_IP="0.0.0.0"
|
|
||||||
ENV WEB_PORT=4124
|
|
||||||
ENV NODE_VERSION=18.20.5
|
|
||||||
ENV YARN_VERSION=1.22.22
|
ENV YARN_VERSION=1.22.22
|
||||||
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 WEB_IP="0.0.0.0"
|
||||||
|
ENV WEB_PORT=4124
|
||||||
|
ENV WEB_ENCODING="deflate, br"
|
||||||
|
ENV STREAM_QUALITY="hd"
|
||||||
|
ENV FILE_URL="urls.txt"
|
||||||
|
ENV FILE_M3U="playlist.m3u8"
|
||||||
|
ENV FILE_EPG="xmltv.xml"
|
||||||
|
ENV FILE_TAR="xmltv.xml.gz"
|
||||||
|
ENV LOG_LEVEL=4
|
||||||
|
ENV TZ="Etc/UTC"
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# Install
|
# Install
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
# #
|
|
||||||
# @project TVApp2
|
|
||||||
# @usage docker image which allows you to download a m3u playlist and EPG guide data from
|
|
||||||
# multiple IPTV services.
|
|
||||||
# @file Dockerfile.aarch64
|
|
||||||
# @repo https://github.com/TheBinaryNinja/tvapp2
|
|
||||||
# https://git.binaryninja.net/BinaryNinja/tvapp2
|
|
||||||
# https://github.com/aetherinox/docker-base-alpine
|
|
||||||
#
|
|
||||||
# you can 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 .
|
|
||||||
# arm64 docker build --build-arg VERSION=1.0.0 --build-arg BUILDDATE=20250218 -t tvapp2:1.0.0-arm64 -f Dockerfile.aarch64 .
|
|
||||||
#
|
|
||||||
# if you prefer to use `docker buildx`
|
|
||||||
# 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 .
|
|
||||||
# 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 .
|
|
||||||
# #
|
|
||||||
|
|
||||||
FROM ghcr.io/aetherinox/alpine-base:3.20-arm64
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Set Args
|
|
||||||
# #
|
|
||||||
|
|
||||||
ARG BUILDDATE
|
|
||||||
ARG VERSION
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Set Labels
|
|
||||||
# #
|
|
||||||
|
|
||||||
LABEL maintainer="aetherinox, iFlip721"
|
|
||||||
LABEL org.opencontainers.image.authors="aetherinox, iFlip721"
|
|
||||||
LABEL org.opencontainers.image.vendor="BinaryNinja"
|
|
||||||
LABEL org.opencontainers.image.title="TVApp2"
|
|
||||||
LABEL org.opencontainers.image.description="Automatic m3u and xml guide updater for TheTvApp, TVPass, and MoveOnJoy utilized within your IPTV client."
|
|
||||||
LABEL org.opencontainers.image.source="https://github.com/TheBinaryNinja/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.repo.1="https://github.com/TheBinaryNinja/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.repo.2="https://git.binaryninja.net/BinaryNinja/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.repo.3="https://github.com/aetherinox/docker-base-alpine"
|
|
||||||
LABEL org.opencontainers.image.documentation="https://github.com/TheBinaryNinja/tvapp2/wiki"
|
|
||||||
LABEL org.opencontainers.image.url="https://github.com/TheBinaryNinja/tvapp2/pkgs/container/tvapp2"
|
|
||||||
LABEL org.opencontainers.image.licenses="MIT"
|
|
||||||
LABEL BUILDVERSION="TVApp2 v${VERSION} Build ${BUILDDATE}"
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Set Env Var
|
|
||||||
# #
|
|
||||||
|
|
||||||
ENV TZ="Etc/UTC"
|
|
||||||
ENV URL_REPO="https://git.binaryninja.net/BinaryNinja/"
|
|
||||||
ENV WEB_IP="0.0.0.0"
|
|
||||||
ENV WEB_PORT=4124
|
|
||||||
ENV NODE_VERSION=18.20.5
|
|
||||||
ENV YARN_VERSION=1.22.22
|
|
||||||
ENV DIR_BUILD=/usr/src/app
|
|
||||||
ENV DIR_RUN=/usr/bin/app
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Install
|
|
||||||
# #
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
apk add --no-cache \
|
|
||||||
wget \
|
|
||||||
bash \
|
|
||||||
nano \
|
|
||||||
npm \
|
|
||||||
openssl
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Copy docker-entrypoint
|
|
||||||
# #
|
|
||||||
|
|
||||||
COPY docker-entrypoint.sh /usr/local/bin/
|
|
||||||
|
|
||||||
# #
|
|
||||||
# copy s6-overlays root to image root
|
|
||||||
# #
|
|
||||||
|
|
||||||
COPY root/ /
|
|
||||||
|
|
||||||
# #
|
|
||||||
# set work directory
|
|
||||||
# #
|
|
||||||
|
|
||||||
WORKDIR ${DIR_BUILD}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# copy tvapp2 project to workdir
|
|
||||||
# #
|
|
||||||
|
|
||||||
COPY tvapp2/ ./
|
|
||||||
|
|
||||||
# #
|
|
||||||
# set work dir to built app
|
|
||||||
# #
|
|
||||||
|
|
||||||
WORKDIR ${DIR_RUN}
|
|
||||||
|
|
||||||
# #
|
|
||||||
# Ports and volumes
|
|
||||||
# #
|
|
||||||
|
|
||||||
EXPOSE ${WEB_PORT}/tcp
|
|
||||||
|
|
||||||
# #
|
|
||||||
# In case user sets up the cron for a longer duration, do a first run
|
|
||||||
# and then keep the container running. Hacky, but whatever.
|
|
||||||
# #
|
|
||||||
|
|
||||||
ENTRYPOINT ["/init"]
|
|
||||||
@@ -44,3 +44,7 @@ services:
|
|||||||
memlock:
|
memlock:
|
||||||
soft: -1
|
soft: -1
|
||||||
hard: -1
|
hard: -1
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD", "curl", "--fail", "http://127.0.0.1:4124" ]
|
||||||
|
interval: 30s
|
||||||
|
retries: 5
|
||||||
|
|||||||
@@ -6,21 +6,139 @@ 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.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 />
|
||||||
|
|
||||||
|
### <!-- 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 />
|
||||||
|
|
||||||
@@ -106,4 +125,59 @@ 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 />
|
||||||
|
|||||||
218
docs/docs/about/what_is_tvapp.md
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
---
|
||||||
|
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 />
|
||||||
|
|
||||||
|
## Associated Links
|
||||||
|
|
||||||
|
Check out the following websites for additional resources for the TVApp2 docker image below.
|
||||||
|
|
||||||
|
|
||||||
|
<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.
|
||||||
|
- 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 />
|
|
||||||
429
docs/docs/config/env.md
Normal file
@@ -0,0 +1,429 @@
|
|||||||
|
---
|
||||||
|
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 />
|
||||||
|
|
||||||
|
## 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 />
|
||||||
|
|
||||||
|
## 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 />
|
||||||
|
|
||||||
|
## 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 />
|
||||||
|
|
||||||
|
## FILE_PLAYLIST
|
||||||
|
<!-- md:control env -->
|
||||||
|
<!-- md:version stable-1.1.0 -->
|
||||||
|
<!-- md:default `playlist.m3u8` -->
|
||||||
|
|
||||||
|
The `FILE_PLAYLIST` environment variable specifies the filename that will be utilized when
|
||||||
|
your .m3u 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_PLAYLIST=playlist.m3u8 # (1)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. :information: Changing this file only changes the filename locally; it does
|
||||||
|
not affect the server-side fetching mechanism.
|
||||||
|
|
||||||
|
<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 />
|
||||||
|
|
||||||
|
## 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).
|
||||||
|
|
||||||
|
=== "Logging Options"
|
||||||
|
|
||||||
|
| Log Level | Name | Description |
|
||||||
|
| --------------- | ----------- | ------------------------------------------------------------------------------- |
|
||||||
|
| `6` | Trace | Displays all possible logs in console, along with anything below this line. |
|
||||||
|
| `5` | Debug | Displays debug / developer logs, along with anything below this line. |
|
||||||
|
| `4` | Info | Displays informative logs, along with anything below this line. |
|
||||||
|
| `3` | Notice | Displays important notices, along with anything below this line. |
|
||||||
|
| `2` | Warm | Displays warnings, along with anything below this line. |
|
||||||
|
| `1` | Error | Displays only errors, none of the log levels above this line will be shown |
|
||||||
120
docs/docs/config/volumes.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
---
|
||||||
|
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 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 />
|
||||||
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
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -233,29 +216,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 +260,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 +272,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 +317,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 +411,7 @@
|
|||||||
|
|
||||||
.md-typeset .tabbed-labels
|
.md-typeset .tabbed-labels
|
||||||
{
|
{
|
||||||
background-color: #090909;
|
background-color: #0d0d0d;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Badge > Left Box (Icon
|
|
||||||
*/
|
|
||||||
|
|
||||||
.md-typeset .mdx-badge__icon
|
|
||||||
{
|
|
||||||
background-color: #3f4faa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -453,8 +438,7 @@
|
|||||||
|
|
||||||
h3 .mdx-badge svg
|
h3 .mdx-badge svg
|
||||||
{
|
{
|
||||||
padding-left: 2px;
|
padding-left: 0px;
|
||||||
padding-top: 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -476,15 +460,6 @@
|
|||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Badge > Icon Color
|
|
||||||
*/
|
|
||||||
|
|
||||||
.md-typeset .mdx-badge svg
|
|
||||||
{
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -509,6 +484,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 +506,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 +552,34 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 +601,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 +614,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 +646,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 +704,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 +825,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 +919,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 +934,7 @@ figure img
|
|||||||
{
|
{
|
||||||
.mkde-right
|
.mkde-right
|
||||||
{
|
{
|
||||||
padding: 12px 12px;
|
padding: 0px 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,10 +944,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 +957,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 +969,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 +981,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 +1161,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 +1186,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 +1204,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 +1328,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 +1366,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 +1387,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
|
||||||
|
}
|
||||||
|
|||||||
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.png
Normal file
|
After Width: | Height: | Size: 61 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/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,35 @@ 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 == "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 +173,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 +212,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 +225,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 +262,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 +290,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 +304,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 +316,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 +340,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 +354,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 +374,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 +413,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 +443,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 +481,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 +505,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 +528,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 +550,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 +679,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 +710,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 +739,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 +767,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 +796,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 +813,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 +832,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 +869,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 +886,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 +903,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 +920,31 @@ 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 slider -->
|
||||||
|
# #
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|||||||
550
docs/mkdocs.yml
@@ -1,262 +1,332 @@
|
|||||||
|
# #
|
||||||
|
# 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
|
- markdown.extensions.extra
|
||||||
- toc:
|
- toc:
|
||||||
permalink: true
|
permalink: true
|
||||||
- abbr
|
- abbr
|
||||||
- admonition
|
- admonition
|
||||||
- attr_list
|
- attr_list
|
||||||
- pymdownx.magiclink:
|
- pymdownx.magiclink:
|
||||||
normalize_issue_symbols: true
|
normalize_issue_symbols: true
|
||||||
repo_url_shorthand: true
|
repo_url_shorthand: true
|
||||||
user: TheBinaryNinja
|
user: TheBinaryNinja
|
||||||
repo: tvapp2
|
repo: tvapp2
|
||||||
- pymdownx.emoji:
|
- pymdownx.emoji:
|
||||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||||
options:
|
options:
|
||||||
custom_icons:
|
custom_icons:
|
||||||
- material/overrides/.icons
|
- material/overrides/.icons
|
||||||
- md_in_html
|
- md_in_html
|
||||||
- def_list
|
- def_list
|
||||||
- footnotes
|
- footnotes
|
||||||
- tables
|
- tables
|
||||||
- pymdownx.inlinehilite
|
- pymdownx.inlinehilite
|
||||||
- pymdownx.betterem:
|
- pymdownx.betterem:
|
||||||
smart_enable: all
|
smart_enable: all
|
||||||
- pymdownx.tasklist:
|
- pymdownx.tasklist:
|
||||||
custom_checkbox: true
|
custom_checkbox: true
|
||||||
- pymdownx.highlight:
|
- pymdownx.highlight:
|
||||||
use_pygments: true
|
use_pygments: true
|
||||||
anchor_linenums: true
|
anchor_linenums: true
|
||||||
line_spans: __span
|
line_spans: __span
|
||||||
pygments_lang_class: true
|
pygments_lang_class: true
|
||||||
- pymdownx.superfences:
|
- pymdownx.superfences:
|
||||||
custom_fences:
|
custom_fences:
|
||||||
- name: mermaid
|
- name: mermaid
|
||||||
class: mermaid
|
class: mermaid
|
||||||
format: !!python/name:pymdownx.superfences.fence_code_format
|
format: !!python/name:pymdownx.superfences.fence_code_format
|
||||||
- pymdownx.tabbed:
|
- pymdownx.tabbed:
|
||||||
alternate_style: true
|
alternate_style: true
|
||||||
combine_header_slug: true
|
combine_header_slug: true
|
||||||
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
||||||
kwds:
|
kwds:
|
||||||
case: lower
|
case: lower
|
||||||
- pymdownx.tabbed
|
- pymdownx.tabbed
|
||||||
- pymdownx.caret
|
- pymdownx.caret
|
||||||
- pymdownx.mark
|
- pymdownx.mark
|
||||||
- pymdownx.smartsymbols
|
- pymdownx.smartsymbols
|
||||||
- pymdownx.tilde
|
- pymdownx.tilde
|
||||||
- pymdownx.blocks.html
|
- pymdownx.blocks.html
|
||||||
- pymdownx.details
|
- pymdownx.details
|
||||||
- pymdownx.magiclink:
|
- pymdownx.magiclink:
|
||||||
normalize_issue_symbols: true
|
normalize_issue_symbols: true
|
||||||
repo_url_shorthand: true
|
repo_url_shorthand: true
|
||||||
user: TheBinaryNinja
|
user: TheBinaryNinja
|
||||||
repo: tvapp2
|
repo: tvapp2
|
||||||
- pymdownx.keys
|
- pymdownx.keys
|
||||||
- pymdownx.snippets:
|
- pymdownx.snippets:
|
||||||
auto_append:
|
auto_append:
|
||||||
- includes/abbreviations.md
|
- docs/includes/abbreviations.md
|
||||||
url_download: true
|
url_download: true
|
||||||
- pymdownx.arithmatex:
|
- pymdownx.arithmatex:
|
||||||
generic: true
|
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'
|
||||||
|
- Config:
|
||||||
|
- Environment Variables: 'config/env.md'
|
||||||
|
- Volumes: 'config/volumes.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
|
||||||
|
|||||||
83
renovate.json
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": [
|
||||||
|
"config:recommended",
|
||||||
|
":preserveSemverRanges"
|
||||||
|
],
|
||||||
|
"timezone": "Etc/UTC",
|
||||||
|
"includeForks": true,
|
||||||
|
"forkProcessing": "enabled",
|
||||||
|
"baseBranches": ["main"],
|
||||||
|
"prCreation": "immediate",
|
||||||
|
"rebaseWhen": "conflicted",
|
||||||
|
"rebaseLabel": "AC › Needs Rebase",
|
||||||
|
"gitAuthor": "EuropaServ <161414668+EuropaServ@users.noreply.github.com>",
|
||||||
|
"updatePinnedDependencies": false,
|
||||||
|
"dependencyDashboard": true,
|
||||||
|
"dependencyDashboardTitle": "📁 Dependency Dashboard",
|
||||||
|
"dependencyDashboardLabels": ["📰 Progress Report"],
|
||||||
|
"vulnerabilityAlerts": {
|
||||||
|
"enabled": true,
|
||||||
|
"labels": ["Type ◦ Vulnerability"]
|
||||||
|
},
|
||||||
|
"labels": [
|
||||||
|
"Type ◦ Dependency"
|
||||||
|
],
|
||||||
|
"major": {
|
||||||
|
"automerge": false
|
||||||
|
},
|
||||||
|
"lockFileMaintenance": {
|
||||||
|
"enabled": true,
|
||||||
|
"automerge": true
|
||||||
|
},
|
||||||
|
"packageRules": [
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"nodenv",
|
||||||
|
"npm",
|
||||||
|
"nvm"
|
||||||
|
],
|
||||||
|
"addLabels": [
|
||||||
|
"Type ◦ Dependency"
|
||||||
|
],
|
||||||
|
"rangeStrategy": "auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"nodenv",
|
||||||
|
"npm",
|
||||||
|
"nvm"
|
||||||
|
],
|
||||||
|
"matchUpdateTypes": [
|
||||||
|
"minor",
|
||||||
|
"patch"
|
||||||
|
],
|
||||||
|
"addLabels": [
|
||||||
|
"Type ◦ Dependency"
|
||||||
|
],
|
||||||
|
"automerge": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"github-actions"
|
||||||
|
],
|
||||||
|
"addLabels": [
|
||||||
|
"Type ◦ Git Action"
|
||||||
|
],
|
||||||
|
"rangeStrategy": "auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"github-actions"
|
||||||
|
],
|
||||||
|
"addLabels": [
|
||||||
|
"Type ◦ Git Action"
|
||||||
|
],
|
||||||
|
"matchUpdateTypes": [
|
||||||
|
"minor",
|
||||||
|
"patch"
|
||||||
|
],
|
||||||
|
"automerge": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,5 +1,18 @@
|
|||||||
#!/usr/bin/with-contenv sh
|
#!/usr/bin/with-contenv sh
|
||||||
|
|
||||||
|
# #
|
||||||
|
# Store env variables in s6
|
||||||
|
# #
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
|
printf "$ip_gateway" > /var/run/s6/container_environment/IP_GATEWAY
|
||||||
|
printf "$ip_container" > /var/run/s6/container_environment/IP_CONTAINER
|
||||||
|
|
||||||
|
export IP_GATEWAY=$ip_gateway
|
||||||
|
export IP_GATEWAY=$ip_container
|
||||||
|
|
||||||
# #
|
# #
|
||||||
# install and startup for tvapp2
|
# install and startup for tvapp2
|
||||||
# #
|
# #
|
||||||
@@ -7,4 +20,5 @@
|
|||||||
cp -r ${DIR_BUILD}/* ${DIR_RUN}
|
cp -r ${DIR_BUILD}/* ${DIR_RUN}
|
||||||
rm -rf ${DIR_BUILD}/*
|
rm -rf ${DIR_BUILD}/*
|
||||||
cd ${DIR_RUN}
|
cd ${DIR_RUN}
|
||||||
|
npm install --omit=dev
|
||||||
npm start
|
npm start
|
||||||
|
|||||||
273
tvapp2/eslint.config.mjs
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
Eslint 9 Flat Config
|
||||||
|
|
||||||
|
old eslint < 8 .rc files are no longer supported! do not place .eslintrc files in subfolders.
|
||||||
|
eslint developers are currently working on an experimental feature to allow for sub-folder
|
||||||
|
override rules
|
||||||
|
@ref https://github.com/eslint/eslint/discussions/18574#discussioncomment-9729092
|
||||||
|
https://eslint.org/docs/latest/use/configure/configuration-files#experimental-configuration-file-resolution
|
||||||
|
|
||||||
|
eslint config migration docs
|
||||||
|
@ref https://eslint.org/docs/latest/use/configure/migration-guide
|
||||||
|
*/
|
||||||
|
|
||||||
|
import path from 'path';
|
||||||
|
import globals from 'globals';
|
||||||
|
import js from '@eslint/js';
|
||||||
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
|
|
||||||
|
/*
|
||||||
|
Plugins
|
||||||
|
*/
|
||||||
|
|
||||||
|
import pluginImport from 'eslint-plugin-import';
|
||||||
|
import pluginNode from 'eslint-plugin-n'
|
||||||
|
import pluginChaiFriendly from 'eslint-plugin-chai-friendly';
|
||||||
|
import pluginStylisticJs from '@stylistic/eslint-plugin-js'
|
||||||
|
|
||||||
|
/*
|
||||||
|
Globals
|
||||||
|
*/
|
||||||
|
|
||||||
|
const customGlobals =
|
||||||
|
{
|
||||||
|
guid: 'readable',
|
||||||
|
uuid: 'readable',
|
||||||
|
Buffer: "readonly",
|
||||||
|
BufferEncoding: "readonly"
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compatibility
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
const __filename = fileURLToPath(import.meta.url); // get resolved path to file
|
||||||
|
const __dirname = path.dirname(__filename); // get name of directory
|
||||||
|
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname, // optional; default: process.cwd()
|
||||||
|
resolvePluginsRelativeTo: __dirname, // optional
|
||||||
|
recommendedConfig: js.configs.recommended, // optional unless using 'eslint:recommended'
|
||||||
|
allConfig: js.configs.all, // optional unless using 'eslint:all'
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
Eslint > Flat Config
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default
|
||||||
|
[
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'coverage/**',
|
||||||
|
'node_modules/**',
|
||||||
|
'**/dist/**/*',
|
||||||
|
'**/__tmp__/**/*',
|
||||||
|
'eslint.config.mjs',
|
||||||
|
'eslint.config.cjs',
|
||||||
|
"root.js",
|
||||||
|
"www/**/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...compat.extends('eslint:recommended'),
|
||||||
|
{
|
||||||
|
plugins: {
|
||||||
|
'n': pluginNode,
|
||||||
|
'import': pluginImport,
|
||||||
|
'@stylistic/js': pluginStylisticJs,
|
||||||
|
'chai-friendly': pluginChaiFriendly
|
||||||
|
},
|
||||||
|
linterOptions: {
|
||||||
|
reportUnusedDisableDirectives: false
|
||||||
|
},
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...customGlobals,
|
||||||
|
...globals.browser,
|
||||||
|
process: true, // Node.js global
|
||||||
|
_: true,
|
||||||
|
$: true
|
||||||
|
},
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
parserOptions: {
|
||||||
|
requireConfigFile: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// eslint/js rules
|
||||||
|
'one-var': 'off',
|
||||||
|
'no-throw-literal': 'off',
|
||||||
|
|
||||||
|
'camelcase': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'properties': 'always'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'no-console': 'off',
|
||||||
|
'no-alert': 'error',
|
||||||
|
'no-debugger': 'error',
|
||||||
|
'prefer-arrow-callback': 'error',
|
||||||
|
'no-useless-escape': 'off',
|
||||||
|
'no-var': 'error',
|
||||||
|
'prefer-const': 'error',
|
||||||
|
'no-unused-expressions': 0,
|
||||||
|
'chai-friendly/no-unused-expressions': 'off',
|
||||||
|
'strict': ['error', 'never'],
|
||||||
|
'prefer-promise-reject-errors': 'off',
|
||||||
|
'no-object-constructor': 'error',
|
||||||
|
'object-shorthand': 'off',
|
||||||
|
'no-array-constructor': 'error',
|
||||||
|
'array-callback-return': 'error',
|
||||||
|
'no-eval': 'error',
|
||||||
|
'no-new-func': 'error',
|
||||||
|
'prefer-rest-params': 'error',
|
||||||
|
'prefer-spread': 'error',
|
||||||
|
'no-useless-constructor': 'error',
|
||||||
|
'no-dupe-class-members': 'error',
|
||||||
|
'no-duplicate-imports': 'error',
|
||||||
|
'eqeqeq': 'error',
|
||||||
|
'no-unneeded-ternary': 'error',
|
||||||
|
'curly': 'off',
|
||||||
|
|
||||||
|
'no-empty': 'off',
|
||||||
|
'no-restricted-syntax': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'selector': 'ExportDefaultDeclaration',
|
||||||
|
'message': 'Prefer named exports'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'import/no-webpack-loader-syntax': 'off',
|
||||||
|
'import/no-relative-parent-imports': 'error',
|
||||||
|
'import/first': 'error',
|
||||||
|
'import/no-default-export': 'error',
|
||||||
|
'node/no-callback-literal': 0,
|
||||||
|
|
||||||
|
/*
|
||||||
|
@plugin eslint-plugin-n
|
||||||
|
*/
|
||||||
|
|
||||||
|
'n/no-callback-literal': 0,
|
||||||
|
'n/no-deprecated-api': 'error',
|
||||||
|
'n/no-exports-assign': 'error',
|
||||||
|
'n/no-extraneous-import': 'error',
|
||||||
|
'n/no-extraneous-require': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'allowModules': ['electron', 'electron-notarize'],
|
||||||
|
'resolvePaths': [],
|
||||||
|
'tryExtensions': []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'n/no-missing-import': 'off',
|
||||||
|
'n/no-missing-require': 'off',
|
||||||
|
'n/no-mixed-requires': 'error',
|
||||||
|
'n/no-new-require': 'error',
|
||||||
|
'n/no-path-concat': 'error',
|
||||||
|
'n/no-process-env': 'off',
|
||||||
|
'n/no-process-exit': 'off',
|
||||||
|
'n/no-restricted-import': 'error',
|
||||||
|
'n/no-restricted-require': 'error',
|
||||||
|
'n/no-sync': 'off',
|
||||||
|
'n/no-unpublished-bin': 'error',
|
||||||
|
'n/no-unpublished-import': 'error',
|
||||||
|
'n/no-unpublished-require': 'error',
|
||||||
|
'n/no-unsupported-features/es-builtins': 'error',
|
||||||
|
'n/no-unsupported-features/es-syntax': 'error',
|
||||||
|
'n/no-unsupported-features/node-builtins': 'off',
|
||||||
|
'n/prefer-global/buffer': 'error',
|
||||||
|
'n/prefer-global/console': 'error',
|
||||||
|
'n/prefer-global/process': 'error',
|
||||||
|
'n/prefer-global/text-decoder': 'error',
|
||||||
|
'n/prefer-global/text-encoder': 'error',
|
||||||
|
'n/prefer-global/url': 'error',
|
||||||
|
'n/prefer-global/url-search-params': 'error',
|
||||||
|
'n/prefer-node-protocol': 'off',
|
||||||
|
'n/prefer-promises/dns': 'off',
|
||||||
|
'n/prefer-promises/fs': 'off',
|
||||||
|
'n/process-exit-as-throw': 'error',
|
||||||
|
'@stylistic/js/object-property-newline': 'off',
|
||||||
|
'@stylistic/js/no-multi-spaces': [ 0, { ignoreEOLComments: true } ],
|
||||||
|
'@stylistic/js/arrow-spacing': [ 'error', { before: true, after: true } ],
|
||||||
|
'@stylistic/js/semi-spacing': ['error', {
|
||||||
|
before: false,
|
||||||
|
after: false,
|
||||||
|
}],
|
||||||
|
"@stylistic/js/space-before-function-paren": ["error", {
|
||||||
|
anonymous: "always",
|
||||||
|
asyncArrow: "never",
|
||||||
|
named: "never"
|
||||||
|
}],
|
||||||
|
'@stylistic/js/padded-blocks': ['error', {
|
||||||
|
blocks: 'never',
|
||||||
|
switches: 'never',
|
||||||
|
classes: 'never',
|
||||||
|
}],
|
||||||
|
'@stylistic/js/arrow-parens': [ 'error', 'always' ],
|
||||||
|
'@stylistic/js/block-spacing': [ 'error', 'always' ],
|
||||||
|
'@stylistic/js/comma-dangle': [ 'error', 'never' ],
|
||||||
|
'@stylistic/js/comma-spacing': [ 'error', { before: false, after: true }],
|
||||||
|
'@stylistic/js/computed-property-spacing': ['error', 'never'],
|
||||||
|
'@stylistic/js/no-mixed-operators': ['off'],
|
||||||
|
'@stylistic/js/eol-last': ['error', 'always'],
|
||||||
|
'@stylistic/js/jsx-quotes': ['error', 'prefer-single'],
|
||||||
|
'@stylistic/js/linebreak-style': ['error', 'unix'],
|
||||||
|
'@stylistic/js/no-mixed-spaces-and-tabs': ['error'],
|
||||||
|
'@stylistic/js/no-tabs': ['error'],
|
||||||
|
'@stylistic/js/no-trailing-spaces': ['error', { skipBlankLines: true, ignoreComments: true }],
|
||||||
|
'@stylistic/js/no-whitespace-before-property': ['error'],
|
||||||
|
'@stylistic/js/object-curly-spacing': ['error', 'always'],
|
||||||
|
'@stylistic/js/quote-props': ['error', 'as-needed'],
|
||||||
|
'@stylistic/js/quotes': ['error', 'single', { allowTemplateLiterals: true }],
|
||||||
|
'@stylistic/js/semi': ['error', 'always'],
|
||||||
|
'@stylistic/js/space-infix-ops': ['error'],
|
||||||
|
'@stylistic/js/template-curly-spacing': ['error', 'always'],
|
||||||
|
'@stylistic/js/template-tag-spacing': ['error', 'always'],
|
||||||
|
'@stylistic/js/space-in-parens': [ 'error', 'always',
|
||||||
|
{
|
||||||
|
exceptions: ["{}", "[]"]
|
||||||
|
}],
|
||||||
|
'@stylistic/js/spaced-comment': [ 'error', 'always',
|
||||||
|
{
|
||||||
|
markers: ['/']
|
||||||
|
}],
|
||||||
|
'@stylistic/js/array-bracket-newline': [ 'warn',
|
||||||
|
{
|
||||||
|
multiline: true,
|
||||||
|
minItems: 5,
|
||||||
|
}],
|
||||||
|
'@stylistic/js/brace-style': [ 'error', 'allman',
|
||||||
|
{
|
||||||
|
allowSingleLine: true,
|
||||||
|
}],
|
||||||
|
'@stylistic/js/array-bracket-spacing': [ 'error', 'always',
|
||||||
|
{
|
||||||
|
arraysInArrays: false,
|
||||||
|
objectsInArrays: false,
|
||||||
|
singleValue: false,
|
||||||
|
}],
|
||||||
|
'@stylistic/js/wrap-iife': [2, 'inside', { functionPrototypeMethods: true }],
|
||||||
|
'@stylistic/js/keyword-spacing': [ 'error',
|
||||||
|
{
|
||||||
|
before: true,
|
||||||
|
after: true,
|
||||||
|
overrides:
|
||||||
|
{
|
||||||
|
return: { before: true, after: true },
|
||||||
|
throw: { before: true, after: true },
|
||||||
|
case: { before: true, after: true },
|
||||||
|
as: { before: true, after: true },
|
||||||
|
if: { before: true, after: true },
|
||||||
|
for: { before: true, after: true },
|
||||||
|
while: { before: true, after: true },
|
||||||
|
static: { before: true, after: true }
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
];
|
||||||
1689
tvapp2/index.js
4579
tvapp2/node_modules/.package-lock.json
generated
vendored
32
tvapp2/node_modules/playwright-core/browsers.json
generated
vendored
@@ -3,31 +3,43 @@
|
|||||||
"browsers": [
|
"browsers": [
|
||||||
{
|
{
|
||||||
"name": "chromium",
|
"name": "chromium",
|
||||||
"revision": "1155",
|
"revision": "1161",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"browserVersion": "133.0.6943.16"
|
"browserVersion": "134.0.6998.35"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "chromium-headless-shell",
|
||||||
|
"revision": "1161",
|
||||||
|
"installByDefault": true,
|
||||||
|
"browserVersion": "134.0.6998.35"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chromium-tip-of-tree",
|
"name": "chromium-tip-of-tree",
|
||||||
"revision": "1293",
|
"revision": "1304",
|
||||||
"installByDefault": false,
|
"installByDefault": false,
|
||||||
"browserVersion": "133.0.6943.0"
|
"browserVersion": "135.0.7021.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "chromium-tip-of-tree-headless-shell",
|
||||||
|
"revision": "1304",
|
||||||
|
"installByDefault": false,
|
||||||
|
"browserVersion": "135.0.7021.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox",
|
"name": "firefox",
|
||||||
"revision": "1471",
|
"revision": "1475",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"browserVersion": "134.0"
|
"browserVersion": "135.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firefox-beta",
|
"name": "firefox-beta",
|
||||||
"revision": "1467",
|
"revision": "1471",
|
||||||
"installByDefault": false,
|
"installByDefault": false,
|
||||||
"browserVersion": "133.0b9"
|
"browserVersion": "136.0b4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webkit",
|
"name": "webkit",
|
||||||
"revision": "2123",
|
"revision": "2140",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"revisionOverrides": {
|
"revisionOverrides": {
|
||||||
"debian11-x64": "2105",
|
"debian11-x64": "2105",
|
||||||
@@ -41,7 +53,7 @@
|
|||||||
"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 +
|
||||||
|
|||||||
8
tvapp2/node_modules/playwright-core/lib/androidServerImpl.js
generated
vendored
@@ -4,10 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.AndroidServerLauncherImpl = void 0;
|
exports.AndroidServerLauncherImpl = void 0;
|
||||||
var _utilsBundle = require("./utilsBundle");
|
|
||||||
var _utils = require("./utils");
|
|
||||||
var _playwright = require("./server/playwright");
|
|
||||||
var _playwrightServer = require("./remote/playwrightServer");
|
var _playwrightServer = require("./remote/playwrightServer");
|
||||||
|
var _playwright = require("./server/playwright");
|
||||||
|
var _crypto = require("./server/utils/crypto");
|
||||||
|
var _utilsBundle = require("./utilsBundle");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -43,7 +43,7 @@ class AndroidServerLauncherImpl {
|
|||||||
}
|
}
|
||||||
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, _crypto.createGuid)()}`;
|
||||||
|
|
||||||
// 2. Start the server
|
// 2. Start the server
|
||||||
const server = new _playwrightServer.PlaywrightServer({
|
const server = new _playwrightServer.PlaywrightServer({
|
||||||
|
|||||||
27
tvapp2/node_modules/playwright-core/lib/browserServerImpl.js
generated
vendored
@@ -4,15 +4,14 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.BrowserServerLauncherImpl = void 0;
|
exports.BrowserServerLauncherImpl = void 0;
|
||||||
var _utilsBundle = require("./utilsBundle");
|
var _socksProxy = require("./server/utils/socksProxy");
|
||||||
var _clientHelper = require("./client/clientHelper");
|
|
||||||
var _utils = require("./utils");
|
|
||||||
var _instrumentation = require("./server/instrumentation");
|
|
||||||
var _playwright = require("./server/playwright");
|
|
||||||
var _playwrightServer = require("./remote/playwrightServer");
|
var _playwrightServer = require("./remote/playwrightServer");
|
||||||
var _helper = require("./server/helper");
|
var _helper = require("./server/helper");
|
||||||
var _stackTrace = require("./utils/stackTrace");
|
var _instrumentation = require("./server/instrumentation");
|
||||||
var _socksProxy = require("./common/socksProxy");
|
var _playwright = require("./server/playwright");
|
||||||
|
var _crypto = require("./server/utils/crypto");
|
||||||
|
var _stackTrace = require("./utils/isomorphic/stackTrace");
|
||||||
|
var _utilsBundle = require("./utilsBundle");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -49,13 +48,13 @@ class BrowserServerLauncherImpl {
|
|||||||
...options,
|
...options,
|
||||||
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
|
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
|
||||||
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) : undefined
|
||||||
}, toProtocolLogger(options.logger)).catch(e => {
|
}, toProtocolLogger(options.logger)).catch(e => {
|
||||||
const log = _helper.helper.formatBrowserLogs(metadata.log);
|
const log = _helper.helper.formatBrowserLogs(metadata.log);
|
||||||
(0, _stackTrace.rewriteErrorMessage)(e, `${e.message} Failed to launch browser.${log}`);
|
(0, _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, _crypto.createGuid)()}`;
|
||||||
|
|
||||||
// 2. Start the server
|
// 2. Start the server
|
||||||
const server = new _playwrightServer.PlaywrightServer({
|
const server = new _playwrightServer.PlaywrightServer({
|
||||||
@@ -89,4 +88,14 @@ 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')) logger.log('protocol', 'verbose', (direction === 'send' ? 'SEND ► ' : '◀ RECV ') + JSON.stringify(message), [], {});
|
||||||
} : undefined;
|
} : undefined;
|
||||||
|
}
|
||||||
|
function envObjectToArray(env) {
|
||||||
|
const result = [];
|
||||||
|
for (const name in env) {
|
||||||
|
if (!Object.is(env[name], undefined)) result.push({
|
||||||
|
name,
|
||||||
|
value: String(env[name])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
12
tvapp2/node_modules/playwright-core/lib/cli/driver.js
generated
vendored
@@ -9,13 +9,13 @@ exports.runDriver = runDriver;
|
|||||||
exports.runServer = runServer;
|
exports.runServer = runServer;
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var _fs = _interopRequireDefault(require("fs"));
|
||||||
var playwright = _interopRequireWildcard(require("../.."));
|
var playwright = _interopRequireWildcard(require("../.."));
|
||||||
var _server = require("../server");
|
var _pipeTransport = require("../server/utils/pipeTransport");
|
||||||
var _transport = require("../protocol/transport");
|
|
||||||
var _playwrightServer = require("../remote/playwrightServer");
|
var _playwrightServer = require("../remote/playwrightServer");
|
||||||
var _processLauncher = require("../utils/processLauncher");
|
var _server = require("../server");
|
||||||
|
var _processLauncher = require("../server/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 _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 _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 && {}.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 }; }
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -48,7 +48,7 @@ function runDriver() {
|
|||||||
});
|
});
|
||||||
return new _server.PlaywrightDispatcher(rootScope, playwright);
|
return new _server.PlaywrightDispatcher(rootScope, playwright);
|
||||||
});
|
});
|
||||||
const transport = new _transport.PipeTransport(process.stdout, process.stdin);
|
const transport = new _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.
|
// 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';
|
||||||
|
|||||||
18
tvapp2/node_modules/playwright-core/lib/cli/program.js
generated
vendored
@@ -12,16 +12,16 @@ Object.defineProperty(exports, "program", {
|
|||||||
var _fs = _interopRequireDefault(require("fs"));
|
var _fs = _interopRequireDefault(require("fs"));
|
||||||
var _os = _interopRequireDefault(require("os"));
|
var _os = _interopRequireDefault(require("os"));
|
||||||
var _path = _interopRequireDefault(require("path"));
|
var _path = _interopRequireDefault(require("path"));
|
||||||
var _utilsBundle = require("../utilsBundle");
|
|
||||||
var _driver = require("./driver");
|
|
||||||
var _traceViewer = require("../server/trace/viewer/traceViewer");
|
|
||||||
var playwright = _interopRequireWildcard(require("../.."));
|
var playwright = _interopRequireWildcard(require("../.."));
|
||||||
var _utils = require("../utils");
|
var _driver = require("./driver");
|
||||||
var _server = require("../server");
|
var _server = require("../server");
|
||||||
var _errors = require("../client/errors");
|
var _utils = require("../utils");
|
||||||
|
var _traceViewer = require("../server/trace/viewer/traceViewer");
|
||||||
|
var _ascii = require("../server/utils/ascii");
|
||||||
|
var _utilsBundle = require("../utilsBundle");
|
||||||
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 _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 _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 && {}.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 }; }
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -97,7 +97,7 @@ _utilsBundle.program.command('install [browser...]').description('ensure browser
|
|||||||
// For '--no-shell' option, commander sets `shell: false` instead.
|
// For '--no-shell' option, commander sets `shell: false` instead.
|
||||||
if (options.shell === false) options.noShell = true;
|
if (options.shell === false) options.noShell = true;
|
||||||
if ((0, _utils.isLikelyNpxGlobal)()) {
|
if ((0, _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, _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;
|
||||||
@@ -408,7 +408,7 @@ async function openPage(context, url) {
|
|||||||
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 (_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;
|
||||||
await page.goto(url).catch(error => {
|
await page.goto(url).catch(error => {
|
||||||
if (process.env.PWTEST_CLI_AUTO_EXIT_WHEN && (0, _errors.isTargetClosedError)(error)) {
|
if (process.env.PWTEST_CLI_AUTO_EXIT_WHEN) {
|
||||||
// Tests with PWTEST_CLI_AUTO_EXIT_WHEN might close page too fast, resulting
|
// Tests with PWTEST_CLI_AUTO_EXIT_WHEN might close page too fast, resulting
|
||||||
// in a stray navigation aborted error. We should ignore it.
|
// in a stray navigation aborted error. We should ignore it.
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
3
tvapp2/node_modules/playwright-core/lib/cli/programWithTestStub.js
generated
vendored
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "program", {
|
|||||||
return _program.program;
|
return _program.program;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
var _processLauncher = require("../server/utils/processLauncher");
|
||||||
var _utils = require("../utils");
|
var _utils = require("../utils");
|
||||||
var _program = require("./program");
|
var _program = require("./program");
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +61,7 @@ function addExternalPlaywrightTestCommands() {
|
|||||||
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, _processLauncher.gracefullyProcessExitDoNotHang)(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
95
tvapp2/node_modules/playwright-core/lib/client/android.js
generated
vendored
@@ -4,18 +4,17 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.AndroidWebView = exports.AndroidSocket = exports.AndroidInput = exports.AndroidDevice = exports.Android = void 0;
|
exports.AndroidWebView = exports.AndroidSocket = exports.AndroidInput = exports.AndroidDevice = exports.Android = void 0;
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var _eventEmitter = require("./eventEmitter");
|
||||||
var _utils = require("../utils");
|
|
||||||
var _events = require("./events");
|
|
||||||
var _browserContext = require("./browserContext");
|
var _browserContext = require("./browserContext");
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _timeoutSettings = require("../common/timeoutSettings");
|
|
||||||
var _waiter = require("./waiter");
|
|
||||||
var _events2 = require("events");
|
|
||||||
var _connection = require("./connection");
|
|
||||||
var _errors = require("./errors");
|
var _errors = require("./errors");
|
||||||
var _timeoutRunner = require("../utils/timeoutRunner");
|
var _events = require("./events");
|
||||||
let _Symbol$asyncDispose;
|
var _waiter = require("./waiter");
|
||||||
|
var _timeoutSettings = require("./timeoutSettings");
|
||||||
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
|
var _time = require("../utils/isomorphic/time");
|
||||||
|
var _timeoutRunner = require("../utils/isomorphic/timeoutRunner");
|
||||||
|
var _webSocket = require("./webSocket");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -31,7 +30,7 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
class Android extends _channelOwner.ChannelOwner {
|
class Android extends _channelOwner.ChannelOwner {
|
||||||
static from(android) {
|
static from(android) {
|
||||||
return android._object;
|
return android._object;
|
||||||
@@ -40,13 +39,15 @@ class Android extends _channelOwner.ChannelOwner {
|
|||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._timeoutSettings = void 0;
|
this._timeoutSettings = void 0;
|
||||||
this._serverLauncher = void 0;
|
this._serverLauncher = void 0;
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings();
|
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(this._platform);
|
||||||
}
|
}
|
||||||
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 {
|
||||||
@@ -60,68 +61,44 @@ class Android extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
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, _time.monotonicTime)() + options.timeout : 0;
|
||||||
const headers = {
|
const headers = {
|
||||||
'x-playwright-browser': 'android',
|
'x-playwright-browser': 'android',
|
||||||
...options.headers
|
...options.headers
|
||||||
};
|
};
|
||||||
const localUtils = this._connection.localUtils();
|
|
||||||
const connectParams = {
|
const connectParams = {
|
||||||
wsEndpoint,
|
wsEndpoint,
|
||||||
headers,
|
headers,
|
||||||
slowMo: options.slowMo,
|
slowMo: options.slowMo,
|
||||||
timeout: options.timeout
|
timeout: options.timeout
|
||||||
};
|
};
|
||||||
const {
|
const connection = await (0, _webSocket.connectOverWebSocket)(this._connection, connectParams);
|
||||||
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 = () => {
|
|
||||||
var _device;
|
var _device;
|
||||||
(_device = device) === null || _device === void 0 || _device._didClose();
|
(_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, _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(_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;
|
exports.Android = Android;
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class AndroidDevice extends _channelOwner.ChannelOwner {
|
class AndroidDevice extends _channelOwner.ChannelOwner {
|
||||||
static from(androidDevice) {
|
static from(androidDevice) {
|
||||||
return androidDevice._object;
|
return androidDevice._object;
|
||||||
@@ -133,7 +110,7 @@ class AndroidDevice extends _channelOwner.ChannelOwner {
|
|||||||
this._shouldCloseConnectionOnClose = false;
|
this._shouldCloseConnectionOnClose = false;
|
||||||
this.input = void 0;
|
this.input = void 0;
|
||||||
this.input = new AndroidInput(this);
|
this.input = new AndroidInput(this);
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(parent._timeoutSettings);
|
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(this._platform, parent._timeoutSettings);
|
||||||
this._channel.on('webViewAdded', ({
|
this._channel.on('webViewAdded', ({
|
||||||
webView
|
webView
|
||||||
}) => this._onWebViewAdded(webView));
|
}) => this._onWebViewAdded(webView));
|
||||||
@@ -154,9 +131,11 @@ class AndroidDevice extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
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() {
|
||||||
return this._initializer.serial;
|
return this._initializer.serial;
|
||||||
@@ -262,10 +241,10 @@ class AndroidDevice extends _channelOwner.ChannelOwner {
|
|||||||
const {
|
const {
|
||||||
binary
|
binary
|
||||||
} = await this._channel.screenshot();
|
} = await this._channel.screenshot();
|
||||||
if (options.path) await _fs.default.promises.writeFile(options.path, binary);
|
if (options.path) await this._platform.fs().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() {
|
||||||
@@ -294,19 +273,19 @@ class AndroidDevice extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async installApk(file, options) {
|
async installApk(file, options) {
|
||||||
await this._channel.installApk({
|
await this._channel.installApk({
|
||||||
file: await loadFile(file),
|
file: await loadFile(this._platform, file),
|
||||||
args: options && options.args
|
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(file),
|
file: await loadFile(this._platform, file),
|
||||||
path,
|
path,
|
||||||
mode: options ? options.mode : undefined
|
mode: options ? options.mode : undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async launchBrowser(options = {}) {
|
async launchBrowser(options = {}) {
|
||||||
const contextOptions = await (0, _browserContext.prepareBrowserContextParams)(options);
|
const contextOptions = await (0, _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 = _browserContext.BrowserContext.from(result.context);
|
||||||
context._setOptions(contextOptions, {});
|
context._setOptions(contextOptions, {});
|
||||||
@@ -350,8 +329,8 @@ class AndroidSocket extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.AndroidSocket = AndroidSocket;
|
exports.AndroidSocket = AndroidSocket;
|
||||||
async function loadFile(file) {
|
async function loadFile(platform, file) {
|
||||||
if ((0, _utils.isString)(file)) return await _fs.default.promises.readFile(file);
|
if ((0, _rtti.isString)(file)) return await platform.fs().promises.readFile(file);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
class AndroidInput {
|
class AndroidInput {
|
||||||
@@ -411,7 +390,7 @@ function toSelectorChannel(selector) {
|
|||||||
} = selector;
|
} = selector;
|
||||||
const toRegex = value => {
|
const toRegex = value => {
|
||||||
if (value === undefined) return undefined;
|
if (value === undefined) return undefined;
|
||||||
if ((0, _utils.isRegExp)(value)) return value.source;
|
if ((0, _rtti.isRegExp)(value)) return value.source;
|
||||||
return '^' + value.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d') + '$';
|
return '^' + value.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d') + '$';
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
@@ -439,9 +418,9 @@ function toSelectorChannel(selector) {
|
|||||||
selected
|
selected
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
class AndroidWebView extends _events2.EventEmitter {
|
class AndroidWebView extends _eventEmitter.EventEmitter {
|
||||||
constructor(device, data) {
|
constructor(device, data) {
|
||||||
super();
|
super(device._platform);
|
||||||
this._device = void 0;
|
this._device = void 0;
|
||||||
this._data = void 0;
|
this._data = void 0;
|
||||||
this._pagePromise = void 0;
|
this._pagePromise = void 0;
|
||||||
|
|||||||
11
tvapp2/node_modules/playwright-core/lib/client/artifact.js
generated
vendored
@@ -4,12 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Artifact = void 0;
|
exports.Artifact = void 0;
|
||||||
var fs = _interopRequireWildcard(require("fs"));
|
|
||||||
var _stream = require("./stream");
|
|
||||||
var _fileUtils = require("../utils/fileUtils");
|
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./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); }
|
var _stream = require("./stream");
|
||||||
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 _fileUtils = require("./fileUtils");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -43,9 +40,9 @@ class Artifact extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
const result = await this._channel.saveAsStream();
|
const result = await this._channel.saveAsStream();
|
||||||
const stream = _stream.Stream.from(result.stream);
|
const stream = _stream.Stream.from(result.stream);
|
||||||
await (0, _fileUtils.mkdirIfNeeded)(path);
|
await (0, _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() {
|
||||||
|
|||||||
29
tvapp2/node_modules/playwright-core/lib/client/browser.js
generated
vendored
@@ -4,15 +4,13 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Browser = void 0;
|
exports.Browser = void 0;
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
|
||||||
var _browserContext = require("./browserContext");
|
|
||||||
var _channelOwner = require("./channelOwner");
|
|
||||||
var _events = require("./events");
|
|
||||||
var _errors = require("./errors");
|
|
||||||
var _cdpSession = require("./cdpSession");
|
|
||||||
var _artifact = require("./artifact");
|
var _artifact = require("./artifact");
|
||||||
var _utils = require("../utils");
|
var _browserContext = require("./browserContext");
|
||||||
let _Symbol$asyncDispose;
|
var _cdpSession = require("./cdpSession");
|
||||||
|
var _channelOwner = require("./channelOwner");
|
||||||
|
var _errors = require("./errors");
|
||||||
|
var _events = require("./events");
|
||||||
|
var _fileUtils = require("./fileUtils");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -28,8 +26,7 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class Browser extends _channelOwner.ChannelOwner {
|
class Browser extends _channelOwner.ChannelOwner {
|
||||||
static from(browser) {
|
static from(browser) {
|
||||||
return browser._object;
|
return browser._object;
|
||||||
@@ -44,8 +41,6 @@ class Browser extends _channelOwner.ChannelOwner {
|
|||||||
this._options = {};
|
this._options = {};
|
||||||
this._name = void 0;
|
this._name = void 0;
|
||||||
this._path = void 0;
|
this._path = void 0;
|
||||||
// Used from @playwright/test fixtures.
|
|
||||||
this._connectHeaders = void 0;
|
|
||||||
this._closeReason = 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());
|
||||||
@@ -76,10 +71,10 @@ class Browser extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async _innerNewContext(options = {}, forReuse) {
|
async _innerNewContext(options = {}, forReuse) {
|
||||||
options = {
|
options = {
|
||||||
...this._browserType._defaultContextOptions,
|
...this._browserType._playwright._defaultContextOptions,
|
||||||
...options
|
...options
|
||||||
};
|
};
|
||||||
const contextOptions = await (0, _browserContext.prepareBrowserContextParams)(options);
|
const contextOptions = await (0, _browserContext.prepareBrowserContextParams)(this._platform, 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 = _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);
|
||||||
@@ -118,13 +113,13 @@ class Browser extends _channelOwner.ChannelOwner {
|
|||||||
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, _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 = undefined;
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close(options = {}) {
|
async close(options = {}) {
|
||||||
|
|||||||
133
tvapp2/node_modules/playwright-core/lib/client/browserContext.js
generated
vendored
@@ -6,31 +6,33 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
exports.BrowserContext = void 0;
|
exports.BrowserContext = void 0;
|
||||||
exports.prepareBrowserContextParams = prepareBrowserContextParams;
|
exports.prepareBrowserContextParams = prepareBrowserContextParams;
|
||||||
exports.toClientCertificatesProtocol = toClientCertificatesProtocol;
|
exports.toClientCertificatesProtocol = toClientCertificatesProtocol;
|
||||||
var _page = require("./page");
|
var _artifact = require("./artifact");
|
||||||
var _frame = require("./frame");
|
var _browser = require("./browser");
|
||||||
var network = _interopRequireWildcard(require("./network"));
|
var _cdpSession = require("./cdpSession");
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
|
||||||
var _path = _interopRequireDefault(require("path"));
|
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _clientHelper = require("./clientHelper");
|
var _clientHelper = require("./clientHelper");
|
||||||
var _browser = require("./browser");
|
var _clock = require("./clock");
|
||||||
var _worker = require("./worker");
|
|
||||||
var _events = require("./events");
|
|
||||||
var _timeoutSettings = require("../common/timeoutSettings");
|
|
||||||
var _waiter = require("./waiter");
|
|
||||||
var _utils = require("../utils");
|
|
||||||
var _cdpSession = require("./cdpSession");
|
|
||||||
var _tracing = require("./tracing");
|
|
||||||
var _artifact = require("./artifact");
|
|
||||||
var _fetch = require("./fetch");
|
|
||||||
var _stackTrace = require("../utils/stackTrace");
|
|
||||||
var _harRouter = require("./harRouter");
|
|
||||||
var _consoleMessage = require("./consoleMessage");
|
var _consoleMessage = require("./consoleMessage");
|
||||||
var _dialog = require("./dialog");
|
var _dialog = require("./dialog");
|
||||||
var _webError = require("./webError");
|
|
||||||
var _errors = require("./errors");
|
var _errors = require("./errors");
|
||||||
var _clock = require("./clock");
|
var _events = require("./events");
|
||||||
let _Symbol$asyncDispose;
|
var _fetch = require("./fetch");
|
||||||
|
var _frame = require("./frame");
|
||||||
|
var _harRouter = require("./harRouter");
|
||||||
|
var network = _interopRequireWildcard(require("./network"));
|
||||||
|
var _page = require("./page");
|
||||||
|
var _tracing = require("./tracing");
|
||||||
|
var _waiter = require("./waiter");
|
||||||
|
var _webError = require("./webError");
|
||||||
|
var _worker = require("./worker");
|
||||||
|
var _timeoutSettings = require("./timeoutSettings");
|
||||||
|
var _fileUtils = require("./fileUtils");
|
||||||
|
var _headers = require("../utils/isomorphic/headers");
|
||||||
|
var _urlMatch = require("../utils/isomorphic/urlMatch");
|
||||||
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
|
var _stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
|
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 && {}.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 2017 Google Inc. All rights reserved.
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
@@ -47,10 +49,7 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
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; }
|
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class BrowserContext extends _channelOwner.ChannelOwner {
|
class BrowserContext extends _channelOwner.ChannelOwner {
|
||||||
static from(context) {
|
static from(context) {
|
||||||
return context._object;
|
return context._object;
|
||||||
@@ -67,7 +66,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
this._browser = null;
|
this._browser = null;
|
||||||
this._browserType = void 0;
|
this._browserType = void 0;
|
||||||
this._bindings = new Map();
|
this._bindings = new Map();
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings();
|
this._timeoutSettings = void 0;
|
||||||
this._ownerPage = void 0;
|
this._ownerPage = void 0;
|
||||||
this._closedPromise = void 0;
|
this._closedPromise = void 0;
|
||||||
this._options = {};
|
this._options = {};
|
||||||
@@ -81,6 +80,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
this._closeWasCalled = false;
|
this._closeWasCalled = false;
|
||||||
this._closeReason = void 0;
|
this._closeReason = void 0;
|
||||||
this._harRouters = [];
|
this._harRouters = [];
|
||||||
|
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(this._platform);
|
||||||
if (parent instanceof _browser.Browser) this._browser = parent;
|
if (parent instanceof _browser.Browser) this._browser = parent;
|
||||||
(_this$_browser = this._browser) === null || _this$_browser === void 0 || _this$_browser._contexts.add(this);
|
(_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._isChromium = ((_this$_browser2 = this._browser) === null || _this$_browser2 === void 0 ? void 0 : _this$_browser2._name) === 'chromium';
|
||||||
@@ -116,7 +116,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
this.emit(_events.Events.BrowserContext.ServiceWorker, serviceWorker);
|
this.emit(_events.Events.BrowserContext.ServiceWorker, serviceWorker);
|
||||||
});
|
});
|
||||||
this._channel.on('console', event => {
|
this._channel.on('console', event => {
|
||||||
const consoleMessage = new _consoleMessage.ConsoleMessage(event);
|
const consoleMessage = new _consoleMessage.ConsoleMessage(this._platform, event);
|
||||||
this.emit(_events.Events.BrowserContext.Console, consoleMessage);
|
this.emit(_events.Events.BrowserContext.Console, consoleMessage);
|
||||||
const page = consoleMessage.page();
|
const page = consoleMessage.page();
|
||||||
if (page) page.emit(_events.Events.Page.Console, consoleMessage);
|
if (page) page.emit(_events.Events.Page.Console, consoleMessage);
|
||||||
@@ -233,18 +233,18 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
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
|
||||||
}).catch(() => {});
|
});
|
||||||
}, true);
|
}, true).catch(() => {});
|
||||||
}
|
}
|
||||||
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
|
||||||
}).catch(() => {});
|
});
|
||||||
}, true);
|
}, true).catch(() => {});
|
||||||
}
|
}
|
||||||
browser() {
|
browser() {
|
||||||
return this._browser;
|
return this._browser;
|
||||||
@@ -270,15 +270,15 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
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, _rtti.isString)(options.name) ? options.name : undefined,
|
||||||
nameRegexSource: (0, _utils.isRegExp)(options.name) ? options.name.source : undefined,
|
nameRegexSource: (0, _rtti.isRegExp)(options.name) ? options.name.source : undefined,
|
||||||
nameRegexFlags: (0, _utils.isRegExp)(options.name) ? options.name.flags : undefined,
|
nameRegexFlags: (0, _rtti.isRegExp)(options.name) ? options.name.flags : undefined,
|
||||||
domain: (0, _utils.isString)(options.domain) ? options.domain : undefined,
|
domain: (0, _rtti.isString)(options.domain) ? options.domain : undefined,
|
||||||
domainRegexSource: (0, _utils.isRegExp)(options.domain) ? options.domain.source : undefined,
|
domainRegexSource: (0, _rtti.isRegExp)(options.domain) ? options.domain.source : undefined,
|
||||||
domainRegexFlags: (0, _utils.isRegExp)(options.domain) ? options.domain.flags : undefined,
|
domainRegexFlags: (0, _rtti.isRegExp)(options.domain) ? options.domain.flags : undefined,
|
||||||
path: (0, _utils.isString)(options.path) ? options.path : undefined,
|
path: (0, _rtti.isString)(options.path) ? options.path : undefined,
|
||||||
pathRegexSource: (0, _utils.isRegExp)(options.path) ? options.path.source : undefined,
|
pathRegexSource: (0, _rtti.isRegExp)(options.path) ? options.path.source : undefined,
|
||||||
pathRegexFlags: (0, _utils.isRegExp)(options.path) ? options.path.flags : undefined
|
pathRegexFlags: (0, _rtti.isRegExp)(options.path) ? options.path.flags : undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async grantPermissions(permissions, options) {
|
async grantPermissions(permissions, options) {
|
||||||
@@ -298,7 +298,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
async setExtraHTTPHeaders(headers) {
|
async setExtraHTTPHeaders(headers) {
|
||||||
network.validateHeaders(headers);
|
network.validateHeaders(headers);
|
||||||
await this._channel.setExtraHTTPHeaders({
|
await this._channel.setExtraHTTPHeaders({
|
||||||
headers: (0, _utils.headersObjectToArray)(headers)
|
headers: (0, _headers.headersObjectToArray)(headers)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async setOffline(offline) {
|
async setOffline(offline) {
|
||||||
@@ -312,7 +312,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async addInitScript(script, arg) {
|
async addInitScript(script, arg) {
|
||||||
const source = await (0, _clientHelper.evaluationScript)(script, arg);
|
const source = await (0, _clientHelper.evaluationScript)(this._platform, script, arg);
|
||||||
await this._channel.addInitScript({
|
await this._channel.addInitScript({
|
||||||
source
|
source
|
||||||
});
|
});
|
||||||
@@ -332,7 +332,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
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) {
|
||||||
@@ -358,11 +358,13 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
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 _harRouter.HarRouter.create(localUtils, har, options.notFound || 'abort', {
|
||||||
urlMatch: options.url
|
urlMatch: options.url
|
||||||
});
|
});
|
||||||
this._harRouters.push(harRouter);
|
this._harRouters.push(harRouter);
|
||||||
@@ -380,7 +382,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
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, _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');
|
||||||
}
|
}
|
||||||
@@ -420,10 +422,12 @@ class BrowserContext 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, _utils.mkdirIfNeeded)(options.path);
|
await (0, _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, undefined, 2), 'utf8');
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -451,7 +455,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
this.tracing._resetStackCounter();
|
this.tracing._resetStackCounter();
|
||||||
this.emit(_events.Events.BrowserContext.Close, this);
|
this.emit(_events.Events.BrowserContext.Close, this);
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close(options = {}) {
|
async close(options = {}) {
|
||||||
@@ -473,8 +477,10 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
const isCompressed = harParams.content === 'attach' || harParams.path.endsWith('.zip');
|
const isCompressed = harParams.content === 'attach' || harParams.path.endsWith('.zip');
|
||||||
const needCompressed = harParams.path.endsWith('.zip');
|
const needCompressed = harParams.path.endsWith('.zip');
|
||||||
if (isCompressed && !needCompressed) {
|
if (isCompressed && !needCompressed) {
|
||||||
|
const localUtils = this._connection.localUtils();
|
||||||
|
if (!localUtils) throw new Error('Uncompressed har is not supported in thin clients');
|
||||||
await artifact.saveAs(harParams.path + '.tmp');
|
await artifact.saveAs(harParams.path + '.tmp');
|
||||||
await this._connection.localUtils()._channel.harUnzip({
|
await localUtils.harUnzip({
|
||||||
zipFile: harParams.path + '.tmp',
|
zipFile: harParams.path + '.tmp',
|
||||||
harFile: harParams.path
|
harFile: harParams.path
|
||||||
});
|
});
|
||||||
@@ -492,10 +498,10 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.BrowserContext = BrowserContext;
|
exports.BrowserContext = BrowserContext;
|
||||||
async function prepareStorageState(options) {
|
async function prepareStorageState(platform, options) {
|
||||||
if (typeof options.storageState !== 'string') return options.storageState;
|
if (typeof options.storageState !== 'string') 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, _stackTrace.rewriteErrorMessage)(e, `Error reading storage state from ${options.storageState}:\n` + e.message);
|
||||||
throw e;
|
throw e;
|
||||||
@@ -506,28 +512,29 @@ function prepareRecordHarOptions(options) {
|
|||||||
return {
|
return {
|
||||||
path: options.path,
|
path: options.path,
|
||||||
content: options.content || (options.omitContent ? 'omit' : undefined),
|
content: options.content || (options.omitContent ? 'omit' : undefined),
|
||||||
urlGlob: (0, _utils.isString)(options.urlFilter) ? options.urlFilter : undefined,
|
urlGlob: (0, _rtti.isString)(options.urlFilter) ? options.urlFilter : undefined,
|
||||||
urlRegexSource: (0, _utils.isRegExp)(options.urlFilter) ? options.urlFilter.source : undefined,
|
urlRegexSource: (0, _rtti.isRegExp)(options.urlFilter) ? options.urlFilter.source : undefined,
|
||||||
urlRegexFlags: (0, _utils.isRegExp)(options.urlFilter) ? options.urlFilter.flags : undefined,
|
urlRegexFlags: (0, _rtti.isRegExp)(options.urlFilter) ? options.urlFilter.flags : undefined,
|
||||||
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) throw new Error(`"videoSize" option requires "videosPath" to be specified`);
|
||||||
if (options.extraHTTPHeaders) network.validateHeaders(options.extraHTTPHeaders);
|
if (options.extraHTTPHeaders) network.validateHeaders(options.extraHTTPHeaders);
|
||||||
const contextParams = {
|
const contextParams = {
|
||||||
...options,
|
...options,
|
||||||
viewport: options.viewport === null ? undefined : options.viewport,
|
viewport: options.viewport === null ? undefined : options.viewport,
|
||||||
noDefaultViewport: options.viewport === null,
|
noDefaultViewport: options.viewport === null,
|
||||||
extraHTTPHeaders: options.extraHTTPHeaders ? (0, _utils.headersObjectToArray)(options.extraHTTPHeaders) : undefined,
|
extraHTTPHeaders: options.extraHTTPHeaders ? (0, _headers.headersObjectToArray)(options.extraHTTPHeaders) : undefined,
|
||||||
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,7 +542,7 @@ 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) {
|
||||||
@@ -543,11 +550,11 @@ function toAcceptDownloadsProtocol(acceptDownloads) {
|
|||||||
if (acceptDownloads) return 'accept';
|
if (acceptDownloads) return 'accept';
|
||||||
return 'deny';
|
return 'deny';
|
||||||
}
|
}
|
||||||
async function toClientCertificatesProtocol(certs) {
|
async function toClientCertificatesProtocol(platform, certs) {
|
||||||
if (!certs) return undefined;
|
if (!certs) return undefined;
|
||||||
const bufferizeContent = async (value, path) => {
|
const bufferizeContent = async (value, path) => {
|
||||||
if (value) return value;
|
if (value) return value;
|
||||||
if (path) return await _fs.default.promises.readFile(path);
|
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,
|
||||||
|
|||||||
94
tvapp2/node_modules/playwright-core/lib/client/browserType.js
generated
vendored
@@ -7,11 +7,13 @@ exports.BrowserType = void 0;
|
|||||||
var _browser3 = require("./browser");
|
var _browser3 = require("./browser");
|
||||||
var _browserContext = require("./browserContext");
|
var _browserContext = require("./browserContext");
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _connection = require("./connection");
|
|
||||||
var _events = require("./events");
|
|
||||||
var _clientHelper = require("./clientHelper");
|
var _clientHelper = require("./clientHelper");
|
||||||
var _utils = require("../utils");
|
var _events = require("./events");
|
||||||
var _timeoutRunner = require("../utils/timeoutRunner");
|
var _assert = require("../utils/isomorphic/assert");
|
||||||
|
var _headers = require("../utils/isomorphic/headers");
|
||||||
|
var _time = require("../utils/isomorphic/time");
|
||||||
|
var _timeoutRunner = require("../utils/isomorphic/timeoutRunner");
|
||||||
|
var _webSocket = require("./webSocket");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -36,11 +38,6 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
this._serverLauncher = void 0;
|
this._serverLauncher = void 0;
|
||||||
this._contexts = new Set();
|
this._contexts = new Set();
|
||||||
this._playwright = void 0;
|
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;
|
||||||
@@ -53,12 +50,12 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
return this._initializer.name;
|
return this._initializer.name;
|
||||||
}
|
}
|
||||||
async launch(options = {}) {
|
async launch(options = {}) {
|
||||||
var _this$_defaultLaunchO;
|
var _this$_playwright$_de;
|
||||||
(0, _utils.assert)(!options.userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
(0, _assert.assert)(!options.userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||||
(0, _utils.assert)(!options.port, 'Cannot specify a port without launching as a server.');
|
(0, _assert.assert)(!options.port, 'Cannot specify a port without launching as a server.');
|
||||||
const logger = options.logger || ((_this$_defaultLaunchO = this._defaultLaunchOptions) === null || _this$_defaultLaunchO === void 0 ? void 0 : _this$_defaultLaunchO.logger);
|
const logger = options.logger || ((_this$_playwright$_de = this._playwright._defaultLaunchOptions) === null || _this$_playwright$_de === void 0 ? void 0 : _this$_playwright$_de.logger);
|
||||||
options = {
|
options = {
|
||||||
...this._defaultLaunchOptions,
|
...this._playwright._defaultLaunchOptions,
|
||||||
...options
|
...options
|
||||||
};
|
};
|
||||||
const launchOptions = {
|
const launchOptions = {
|
||||||
@@ -76,28 +73,28 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
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');
|
||||||
options = {
|
options = {
|
||||||
...this._defaultLaunchOptions,
|
...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;
|
var _this$_playwright$_de2;
|
||||||
const logger = options.logger || ((_this$_defaultLaunchO2 = this._defaultLaunchOptions) === null || _this$_defaultLaunchO2 === void 0 ? void 0 : _this$_defaultLaunchO2.logger);
|
const logger = options.logger || ((_this$_playwright$_de2 = this._playwright._defaultLaunchOptions) === null || _this$_playwright$_de2 === void 0 ? void 0 : _this$_playwright$_de2.logger);
|
||||||
(0, _utils.assert)(!options.port, 'Cannot specify a port without launching as a server.');
|
(0, _assert.assert)(!options.port, 'Cannot specify a port without launching as a server.');
|
||||||
options = {
|
options = {
|
||||||
...this._defaultLaunchOptions,
|
...this._playwright._defaultLaunchOptions,
|
||||||
...this._defaultContextOptions,
|
...this._playwright._defaultContextOptions,
|
||||||
...options
|
...options
|
||||||
};
|
};
|
||||||
const contextParams = await (0, _browserContext.prepareBrowserContextParams)(options);
|
const contextParams = await (0, _browserContext.prepareBrowserContextParams)(this._platform, options);
|
||||||
const persistentParams = {
|
const persistentParams = {
|
||||||
...contextParams,
|
...contextParams,
|
||||||
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
|
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
|
||||||
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, _clientHelper.envObjectToArray)(options.env) : undefined,
|
||||||
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);
|
||||||
@@ -111,19 +108,18 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
...options,
|
...options,
|
||||||
wsEndpoint: optionsOrWsEndpoint
|
wsEndpoint: optionsOrWsEndpoint
|
||||||
});
|
});
|
||||||
(0, _utils.assert)(optionsOrWsEndpoint.wsEndpoint, 'options.wsEndpoint is required');
|
(0, _assert.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;
|
var _params$exposeNetwork;
|
||||||
const deadline = params.timeout ? (0, _utils.monotonicTime)() + params.timeout : 0;
|
const deadline = params.timeout ? (0, _time.monotonicTime)() + params.timeout : 0;
|
||||||
const headers = {
|
const headers = {
|
||||||
'x-playwright-browser': this.name(),
|
'x-playwright-browser': this.name(),
|
||||||
...params.headers
|
...params.headers
|
||||||
};
|
};
|
||||||
const localUtils = this._connection.localUtils();
|
|
||||||
const connectParams = {
|
const connectParams = {
|
||||||
wsEndpoint: params.wsEndpoint,
|
wsEndpoint: params.wsEndpoint,
|
||||||
headers,
|
headers,
|
||||||
@@ -132,69 +128,39 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
timeout: params.timeout
|
timeout: params.timeout
|
||||||
};
|
};
|
||||||
if (params.__testHookRedirectPortForwarding) connectParams.socksProxyRedirectPortForTest = params.__testHookRedirectPortForwarding;
|
if (params.__testHookRedirectPortForwarding) connectParams.socksProxyRedirectPortForTest = params.__testHookRedirectPortForwarding;
|
||||||
const {
|
const connection = await (0, _webSocket.connectOverWebSocket)(this._connection, connectParams);
|
||||||
pipe,
|
|
||||||
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 => {
|
|
||||||
// Emulate all pages, contexts and the browser closing upon disconnect.
|
// Emulate all pages, contexts and the browser closing upon disconnect.
|
||||||
for (const context of ((_browser = browser) === null || _browser === void 0 ? void 0 : _browser.contexts()) || []) {
|
for (const context of ((_browser = browser) === null || _browser === void 0 ? void 0 : _browser.contexts()) || []) {
|
||||||
var _browser;
|
var _browser;
|
||||||
for (const page of context.pages()) page._onClose();
|
for (const page of context.pages()) page._onClose();
|
||||||
context._onClose();
|
context._onClose();
|
||||||
}
|
}
|
||||||
connection.close(reason || closeError);
|
|
||||||
// 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(() => {
|
setTimeout(() => {
|
||||||
var _browser2;
|
var _browser2;
|
||||||
return (_browser2 = browser) === null || _browser2 === void 0 ? void 0 : _browser2._didClose();
|
return (_browser2 = browser) === null || _browser2 === void 0 ? void 0 : _browser2._didClose();
|
||||||
}, 0);
|
}, 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, _timeoutRunner.raceAgainstDeadline)(async () => {
|
||||||
// For tests.
|
// For tests.
|
||||||
if (params.__testHookBeforeCreateBrowser) await params.__testHookBeforeCreateBrowser();
|
if (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 = _browser3.Browser.from(playwright._initializer.preLaunchedBrowser);
|
||||||
this._didLaunchBrowser(browser, {}, logger);
|
this._didLaunchBrowser(browser, {}, logger);
|
||||||
browser._shouldCloseConnectionOnClose = true;
|
browser._shouldCloseConnectionOnClose = true;
|
||||||
browser._connectHeaders = connectHeaders;
|
browser.on(_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`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -202,12 +168,12 @@ class BrowserType extends _channelOwner.ChannelOwner {
|
|||||||
async connectOverCDP(endpointURLOrOptions, options) {
|
async connectOverCDP(endpointURLOrOptions, options) {
|
||||||
if (typeof endpointURLOrOptions === 'string') return await this._connectOverCDP(endpointURLOrOptions, options);
|
if (typeof endpointURLOrOptions === 'string') return await this._connectOverCDP(endpointURLOrOptions, options);
|
||||||
const endpointURL = 'endpointURL' in endpointURLOrOptions ? endpointURLOrOptions.endpointURL : endpointURLOrOptions.wsEndpoint;
|
const endpointURL = 'endpointURL' in endpointURLOrOptions ? endpointURLOrOptions.endpointURL : endpointURLOrOptions.wsEndpoint;
|
||||||
(0, _utils.assert)(endpointURL, 'Cannot connect over CDP without wsEndpoint.');
|
(0, _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') throw new Error('Connecting over CDP is only supported in Chromium.');
|
||||||
const headers = params.headers ? (0, _utils.headersObjectToArray)(params.headers) : undefined;
|
const headers = params.headers ? (0, _headers.headersObjectToArray)(params.headers) : undefined;
|
||||||
const result = await this._channel.connectOverCDP({
|
const result = await this._channel.connectOverCDP({
|
||||||
endpointURL,
|
endpointURL,
|
||||||
headers,
|
headers,
|
||||||
@@ -229,8 +195,8 @@ 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 !== undefined) context.setDefaultTimeout(this._playwright._defaultContextTimeout);
|
||||||
if (this._defaultContextNavigationTimeout !== undefined) context.setDefaultNavigationTimeout(this._defaultContextNavigationTimeout);
|
if (this._playwright._defaultContextNavigationTimeout !== undefined) context.setDefaultNavigationTimeout(this._playwright._defaultContextNavigationTimeout);
|
||||||
await this._instrumentation.runAfterCreateBrowserContext(context);
|
await this._instrumentation.runAfterCreateBrowserContext(context);
|
||||||
}
|
}
|
||||||
async _willCloseContext(context) {
|
async _willCloseContext(context) {
|
||||||
|
|||||||
43
tvapp2/node_modules/playwright-core/lib/client/channelOwner.js
generated
vendored
@@ -6,10 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
exports.ChannelOwner = void 0;
|
exports.ChannelOwner = void 0;
|
||||||
var _eventEmitter = require("./eventEmitter");
|
var _eventEmitter = require("./eventEmitter");
|
||||||
var _validator = require("../protocol/validator");
|
var _validator = require("../protocol/validator");
|
||||||
var _debugLogger = require("../utils/debugLogger");
|
var _clientStackTrace = require("./clientStackTrace");
|
||||||
var _stackTrace = require("../utils/stackTrace");
|
var _stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
var _utils = require("../utils");
|
|
||||||
var _zones = require("../utils/zones");
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -28,7 +26,8 @@ var _zones = require("../utils/zones");
|
|||||||
|
|
||||||
class ChannelOwner extends _eventEmitter.EventEmitter {
|
class ChannelOwner extends _eventEmitter.EventEmitter {
|
||||||
constructor(parent, type, guid, initializer) {
|
constructor(parent, type, guid, initializer) {
|
||||||
super();
|
const connection = parent instanceof ChannelOwner ? parent._connection : parent;
|
||||||
|
super(connection._platform);
|
||||||
this._connection = void 0;
|
this._connection = void 0;
|
||||||
this._parent = void 0;
|
this._parent = void 0;
|
||||||
this._objects = new Map();
|
this._objects = new Map();
|
||||||
@@ -42,7 +41,7 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
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 : undefined;
|
||||||
@@ -52,7 +51,7 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
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 _eventEmitter.EventEmitter(connection._platform));
|
||||||
this._initializer = initializer;
|
this._initializer = initializer;
|
||||||
}
|
}
|
||||||
markAsInternalType() {
|
markAsInternalType() {
|
||||||
@@ -118,6 +117,13 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
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) => {
|
||||||
@@ -126,16 +132,13 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
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.
|
// 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,
|
// Since this api call is either internal, or has already been reported/traced once,
|
||||||
@@ -153,10 +156,10 @@ 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) return await func(existingApiZone);
|
||||||
if (isInternal === undefined) isInternal = this._isInternalType;
|
if (isInternal === undefined) isInternal = this._isInternalType;
|
||||||
const stackTrace = (0, _stackTrace.captureLibraryStackTrace)();
|
const stackTrace = (0, _clientStackTrace.captureLibraryStackTrace)(this._platform);
|
||||||
const apiZone = {
|
const apiZone = {
|
||||||
apiName: stackTrace.apiName,
|
apiName: stackTrace.apiName,
|
||||||
frames: stackTrace.frames,
|
frames: stackTrace.frames,
|
||||||
@@ -166,20 +169,20 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
stepId: 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>')) e.message = apiZone.apiName + ': ' + e.message;
|
||||||
const stackFrames = '\n' + (0, _stackTrace.stringifyStackFrames)(stackTrace.frames).join('\n') + innerError;
|
const stackFrames = '\n' + (0, _stackTrace.stringifyStackFrames)(stackTrace.frames).join('\n') + innerError;
|
||||||
if (stackFrames.trim()) e.stack = e.message + stackFrames;else e.stack = '';
|
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;
|
||||||
@@ -201,11 +204,11 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.ChannelOwner = ChannelOwner;
|
exports.ChannelOwner = ChannelOwner;
|
||||||
function logApiCall(logger, message) {
|
function logApiCall(platform, logger, message) {
|
||||||
if (logger && logger.isEnabled('api', 'info')) logger.log('api', 'info', message, [], {
|
if (logger && logger.isEnabled('api', 'info')) logger.log('api', 'info', message, [], {
|
||||||
color: 'cyan'
|
color: 'cyan'
|
||||||
});
|
});
|
||||||
_debugLogger.debugLogger.log('api', message);
|
platform.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))) return {
|
||||||
|
|||||||
10
tvapp2/node_modules/playwright-core/lib/client/clientHelper.js
generated
vendored
@@ -6,9 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
exports.addSourceUrlToScript = addSourceUrlToScript;
|
exports.addSourceUrlToScript = addSourceUrlToScript;
|
||||||
exports.envObjectToArray = envObjectToArray;
|
exports.envObjectToArray = envObjectToArray;
|
||||||
exports.evaluationScript = evaluationScript;
|
exports.evaluationScript = evaluationScript;
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
var _utils = require("../utils");
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
/**
|
/**
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
@@ -36,17 +34,17 @@ function envObjectToArray(env) {
|
|||||||
}
|
}
|
||||||
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, undefined) ? 'undefined' : JSON.stringify(arg);
|
||||||
return `(${source})(${argString})`;
|
return `(${source})(${argString})`;
|
||||||
}
|
}
|
||||||
if (arg !== undefined) throw new Error('Cannot evaluate a string with arguments');
|
if (arg !== undefined) throw new Error('Cannot evaluate a string with arguments');
|
||||||
if ((0, _utils.isString)(fun)) return fun;
|
if ((0, _rtti.isString)(fun)) return fun;
|
||||||
if (fun.content !== undefined) return fun.content;
|
if (fun.content !== undefined) return fun.content;
|
||||||
if (fun.path !== undefined) {
|
if (fun.path !== undefined) {
|
||||||
let source = await _fs.default.promises.readFile(fun.path, 'utf8');
|
let source = await platform.fs().promises.readFile(fun.path, 'utf8');
|
||||||
if (addSourceUrl) source = addSourceUrlToScript(source, fun.path);
|
if (addSourceUrl) source = addSourceUrlToScript(source, fun.path);
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|||||||
85
tvapp2/node_modules/playwright-core/lib/client/connection.js
generated
vendored
@@ -4,35 +4,34 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Connection = void 0;
|
exports.Connection = void 0;
|
||||||
|
var _eventEmitter = require("./eventEmitter");
|
||||||
|
var _android = require("./android");
|
||||||
|
var _artifact = require("./artifact");
|
||||||
var _browser = require("./browser");
|
var _browser = require("./browser");
|
||||||
var _browserContext = require("./browserContext");
|
var _browserContext = require("./browserContext");
|
||||||
var _browserType = require("./browserType");
|
var _browserType = require("./browserType");
|
||||||
|
var _cdpSession = require("./cdpSession");
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
|
var _clientInstrumentation = require("./clientInstrumentation");
|
||||||
|
var _dialog = require("./dialog");
|
||||||
|
var _electron = require("./electron");
|
||||||
var _elementHandle = require("./elementHandle");
|
var _elementHandle = require("./elementHandle");
|
||||||
|
var _errors = require("./errors");
|
||||||
|
var _fetch = require("./fetch");
|
||||||
var _frame = require("./frame");
|
var _frame = require("./frame");
|
||||||
var _jsHandle = require("./jsHandle");
|
var _jsHandle = require("./jsHandle");
|
||||||
|
var _jsonPipe = require("./jsonPipe");
|
||||||
|
var _localUtils = require("./localUtils");
|
||||||
var _network = require("./network");
|
var _network = require("./network");
|
||||||
var _page = require("./page");
|
var _page = require("./page");
|
||||||
var _worker = require("./worker");
|
|
||||||
var _dialog = require("./dialog");
|
|
||||||
var _errors = require("./errors");
|
|
||||||
var _cdpSession = require("./cdpSession");
|
|
||||||
var _playwright = require("./playwright");
|
var _playwright = require("./playwright");
|
||||||
var _electron = require("./electron");
|
|
||||||
var _stream = require("./stream");
|
|
||||||
var _writableStream = require("./writableStream");
|
|
||||||
var _debugLogger = require("../utils/debugLogger");
|
|
||||||
var _selectors = require("./selectors");
|
var _selectors = require("./selectors");
|
||||||
var _android = require("./android");
|
var _stream = require("./stream");
|
||||||
var _artifact = require("./artifact");
|
|
||||||
var _events = require("events");
|
|
||||||
var _jsonPipe = require("./jsonPipe");
|
|
||||||
var _fetch = require("./fetch");
|
|
||||||
var _localUtils = require("./localUtils");
|
|
||||||
var _tracing = require("./tracing");
|
var _tracing = require("./tracing");
|
||||||
|
var _worker = require("./worker");
|
||||||
|
var _writableStream = require("./writableStream");
|
||||||
var _validator = require("../protocol/validator");
|
var _validator = require("../protocol/validator");
|
||||||
var _clientInstrumentation = require("./clientInstrumentation");
|
var _stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
var _utils = require("../utils");
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -60,9 +59,9 @@ class Root extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class DummyChannelOwner extends _channelOwner.ChannelOwner {}
|
class DummyChannelOwner extends _channelOwner.ChannelOwner {}
|
||||||
class Connection extends _events.EventEmitter {
|
class Connection extends _eventEmitter.EventEmitter {
|
||||||
constructor(localUtils, instrumentation) {
|
constructor(platform, localUtils, instrumentation, headers = []) {
|
||||||
super();
|
super(platform);
|
||||||
this._objects = new Map();
|
this._objects = new Map();
|
||||||
this.onmessage = message => {};
|
this.onmessage = message => {};
|
||||||
this._lastId = 0;
|
this._lastId = 0;
|
||||||
@@ -76,9 +75,12 @@ class Connection extends _events.EventEmitter {
|
|||||||
this.toImpl = void 0;
|
this.toImpl = void 0;
|
||||||
this._tracingCount = 0;
|
this._tracingCount = 0;
|
||||||
this._instrumentation = void 0;
|
this._instrumentation = void 0;
|
||||||
|
// Used from @playwright/test fixtures -> TODO remove?
|
||||||
|
this.headers = void 0;
|
||||||
this._instrumentation = instrumentation || (0, _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;
|
||||||
@@ -117,9 +119,9 @@ class Connection extends _events.EventEmitter {
|
|||||||
method,
|
method,
|
||||||
params
|
params
|
||||||
};
|
};
|
||||||
if (_debugLogger.debugLogger.isEnabled('channel')) {
|
if (this._platform.isLogEnabled('channel')) {
|
||||||
// Do not include metadata in debug logs to avoid noise.
|
// Do not include metadata in debug logs to avoid noise.
|
||||||
_debugLogger.debugLogger.log('channel', 'SEND> ' + JSON.stringify(message));
|
this._platform.log('channel', 'SEND> ' + JSON.stringify(message));
|
||||||
}
|
}
|
||||||
const location = frames[0] ? {
|
const location = frames[0] ? {
|
||||||
file: frames[0].file,
|
file: frames[0].file,
|
||||||
@@ -132,7 +134,7 @@ class Connection extends _events.EventEmitter {
|
|||||||
internal: !apiName,
|
internal: !apiName,
|
||||||
stepId
|
stepId
|
||||||
};
|
};
|
||||||
if (this._tracingCount && frames && type !== 'LocalUtils') (_this$_localUtils = this._localUtils) === null || _this$_localUtils === void 0 || _this$_localUtils._channel.addStackToTracingNoReply({
|
if (this._tracingCount && frames && type !== 'LocalUtils') (_this$_localUtils = this._localUtils) === null || _this$_localUtils === void 0 || _this$_localUtils.addStackToTracingNoReply({
|
||||||
callData: {
|
callData: {
|
||||||
stack: frames,
|
stack: frames,
|
||||||
id
|
id
|
||||||
@@ -140,7 +142,7 @@ class Connection extends _events.EventEmitter {
|
|||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
// We need to exit zones before calling into the server, otherwise
|
// 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.
|
// when we receive events from the server, we would be in an API zone.
|
||||||
_utils.zones.empty().run(() => this.onmessage({
|
this._platform.zones.empty.run(() => this.onmessage({
|
||||||
...message,
|
...message,
|
||||||
metadata
|
metadata
|
||||||
}));
|
}));
|
||||||
@@ -152,6 +154,13 @@ class Connection extends _events.EventEmitter {
|
|||||||
method
|
method
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
_validatorFromWireContext() {
|
||||||
|
return {
|
||||||
|
tChannelImpl: this._tChannelImplFromWire.bind(this),
|
||||||
|
binary: this._rawBuffers ? 'buffer' : 'fromBase64',
|
||||||
|
isUnderTest: () => this._platform.isUnderTest()
|
||||||
|
};
|
||||||
|
}
|
||||||
dispatch(message) {
|
dispatch(message) {
|
||||||
if (this._closedError) return;
|
if (this._closedError) return;
|
||||||
const {
|
const {
|
||||||
@@ -164,24 +173,21 @@ class Connection extends _events.EventEmitter {
|
|||||||
log
|
log
|
||||||
} = message;
|
} = 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, _errors.parseError)(error);
|
||||||
(0, _utils.rewriteErrorMessage)(parsedError, parsedError.message + (0, _utils.formatCallLog)(log));
|
(0, _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 validator = (0, _validator.findValidator)(callback.type, callback.method, 'Result');
|
||||||
callback.resolve(validator(result, '', {
|
callback.resolve(validator(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')) this._platform.log('channel', '<EVENT ' + JSON.stringify(message));
|
||||||
if (method === '__create__') {
|
if (method === '__create__') {
|
||||||
this._createRemoteObject(guid, params.type, params.guid, params.initializer);
|
this._createRemoteObject(guid, params.type, params.guid, params.initializer);
|
||||||
return;
|
return;
|
||||||
@@ -199,10 +205,7 @@ class Connection extends _events.EventEmitter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const validator = (0, _validator.findValidator)(object._type, method, 'Event');
|
const validator = (0, _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) return;
|
||||||
@@ -225,10 +228,7 @@ class Connection extends _events.EventEmitter {
|
|||||||
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, _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 _android.Android(parent, type, guid, initializer);
|
||||||
@@ -330,4 +330,11 @@ class Connection extends _events.EventEmitter {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Connection = Connection;
|
exports.Connection = Connection;
|
||||||
|
function formatCallLog(platform, log) {
|
||||||
|
if (!log || !log.some(l => !!l)) return '';
|
||||||
|
return `
|
||||||
|
Call log:
|
||||||
|
${platform.colors.dim(log.join('\n'))}
|
||||||
|
`;
|
||||||
|
}
|
||||||
11
tvapp2/node_modules/playwright-core/lib/client/consoleMessage.js
generated
vendored
@@ -4,10 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.ConsoleMessage = void 0;
|
exports.ConsoleMessage = void 0;
|
||||||
var util = _interopRequireWildcard(require("util"));
|
|
||||||
var _jsHandle = require("./jsHandle");
|
var _jsHandle = require("./jsHandle");
|
||||||
var _page = require("./page");
|
var _page = require("./page");
|
||||||
let _util$inspect$custom;
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -23,15 +21,14 @@ let _util$inspect$custom;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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 = void 0;
|
||||||
this._event = void 0;
|
this._event = void 0;
|
||||||
this._page = 'page' in event && event.page ? _page.Page.from(event.page) : null;
|
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;
|
||||||
@@ -48,7 +45,7 @@ class ConsoleMessage {
|
|||||||
location() {
|
location() {
|
||||||
return this._event.location;
|
return this._event.location;
|
||||||
}
|
}
|
||||||
[_util$inspect$custom]() {
|
_inspect() {
|
||||||
return this.text();
|
return this.text();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
tvapp2/node_modules/playwright-core/lib/client/electron.js
generated
vendored
@@ -4,16 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.ElectronApplication = exports.Electron = void 0;
|
exports.ElectronApplication = exports.Electron = void 0;
|
||||||
var _timeoutSettings = require("../common/timeoutSettings");
|
|
||||||
var _browserContext = require("./browserContext");
|
var _browserContext = require("./browserContext");
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _clientHelper = require("./clientHelper");
|
var _clientHelper = require("./clientHelper");
|
||||||
|
var _consoleMessage = require("./consoleMessage");
|
||||||
|
var _errors = require("./errors");
|
||||||
var _events = require("./events");
|
var _events = require("./events");
|
||||||
var _jsHandle = require("./jsHandle");
|
var _jsHandle = require("./jsHandle");
|
||||||
var _consoleMessage = require("./consoleMessage");
|
|
||||||
var _waiter = require("./waiter");
|
var _waiter = require("./waiter");
|
||||||
var _errors = require("./errors");
|
var _timeoutSettings = require("./timeoutSettings");
|
||||||
let _Symbol$asyncDispose;
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -29,6 +28,7 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Electron extends _channelOwner.ChannelOwner {
|
class Electron extends _channelOwner.ChannelOwner {
|
||||||
static from(electron) {
|
static from(electron) {
|
||||||
return electron._object;
|
return electron._object;
|
||||||
@@ -38,8 +38,8 @@ class Electron extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async launch(options = {}) {
|
async launch(options = {}) {
|
||||||
const params = {
|
const params = {
|
||||||
...(await (0, _browserContext.prepareBrowserContextParams)(options)),
|
...(await (0, _browserContext.prepareBrowserContextParams)(this._platform, options)),
|
||||||
env: (0, _clientHelper.envObjectToArray)(options.env ? options.env : process.env),
|
env: (0, _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);
|
||||||
@@ -48,7 +48,6 @@ class Electron extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Electron = Electron;
|
exports.Electron = Electron;
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class ElectronApplication extends _channelOwner.ChannelOwner {
|
class ElectronApplication extends _channelOwner.ChannelOwner {
|
||||||
static from(electronApplication) {
|
static from(electronApplication) {
|
||||||
return electronApplication._object;
|
return electronApplication._object;
|
||||||
@@ -57,14 +56,15 @@ class ElectronApplication extends _channelOwner.ChannelOwner {
|
|||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
this._context = void 0;
|
this._context = void 0;
|
||||||
this._windows = new Set();
|
this._windows = new Set();
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings();
|
this._timeoutSettings = void 0;
|
||||||
|
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(this._platform);
|
||||||
this._context = _browserContext.BrowserContext.from(initializer.context);
|
this._context = _browserContext.BrowserContext.from(initializer.context);
|
||||||
for (const page of this._context._pages) this._onPage(page);
|
for (const page of this._context._pages) this._onPage(page);
|
||||||
this._context.on(_events.Events.BrowserContext.Page, page => this._onPage(page));
|
this._context.on(_events.Events.BrowserContext.Page, page => this._onPage(page));
|
||||||
this._channel.on('close', () => {
|
this._channel.on('close', () => {
|
||||||
this.emit(_events.Events.ElectronApplication.Close);
|
this.emit(_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(_events.Events.ElectronApplication.Console, new _consoleMessage.ConsoleMessage(this._platform, event)));
|
||||||
this._setEventToSubscriptionMapping(new Map([[_events.Events.ElectronApplication.Console, 'console']]));
|
this._setEventToSubscriptionMapping(new Map([[_events.Events.ElectronApplication.Console, 'console']]));
|
||||||
}
|
}
|
||||||
process() {
|
process() {
|
||||||
@@ -86,7 +86,7 @@ class ElectronApplication extends _channelOwner.ChannelOwner {
|
|||||||
context() {
|
context() {
|
||||||
return this._context;
|
return this._context;
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close() {
|
async close() {
|
||||||
|
|||||||
65
tvapp2/node_modules/playwright-core/lib/client/elementHandle.js
generated
vendored
@@ -9,15 +9,11 @@ exports.convertSelectOptionValues = convertSelectOptionValues;
|
|||||||
exports.determineScreenshotType = determineScreenshotType;
|
exports.determineScreenshotType = determineScreenshotType;
|
||||||
var _frame = require("./frame");
|
var _frame = require("./frame");
|
||||||
var _jsHandle = require("./jsHandle");
|
var _jsHandle = require("./jsHandle");
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var _assert = require("../utils/isomorphic/assert");
|
||||||
var _utilsBundle = require("../utilsBundle");
|
var _fileUtils = require("./fileUtils");
|
||||||
var _path = _interopRequireDefault(require("path"));
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
var _utils = require("../utils");
|
|
||||||
var _fileUtils = require("../utils/fileUtils");
|
|
||||||
var _writableStream = require("./writableStream");
|
var _writableStream = require("./writableStream");
|
||||||
var _stream = require("stream");
|
var _mimeType = require("../utils/isomorphic/mimeType");
|
||||||
var _util = require("util");
|
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -34,7 +30,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const pipelineAsync = (0, _util.promisify)(_stream.pipeline);
|
|
||||||
class ElementHandle extends _jsHandle.JSHandle {
|
class ElementHandle extends _jsHandle.JSHandle {
|
||||||
static from(handle) {
|
static from(handle) {
|
||||||
return handle._object;
|
return handle._object;
|
||||||
@@ -56,6 +51,10 @@ class ElementHandle extends _jsHandle.JSHandle {
|
|||||||
async contentFrame() {
|
async contentFrame() {
|
||||||
return _frame.Frame.fromNullable((await this._elementChannel.contentFrame()).frame);
|
return _frame.Frame.fromNullable((await this._elementChannel.contentFrame()).frame);
|
||||||
}
|
}
|
||||||
|
async _generateLocatorString() {
|
||||||
|
const value = (await this._elementChannel.generateLocatorString()).value;
|
||||||
|
return value === undefined ? null : value;
|
||||||
|
}
|
||||||
async getAttribute(name) {
|
async getAttribute(name) {
|
||||||
const value = (await this._elementChannel.getAttribute({
|
const value = (await this._elementChannel.getAttribute({
|
||||||
name
|
name
|
||||||
@@ -133,7 +132,7 @@ class ElementHandle extends _jsHandle.JSHandle {
|
|||||||
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) throw new Error('Cannot set input files to detached element');
|
||||||
const converted = await convertInputFiles(files, frame.page().context());
|
const converted = await convertInputFiles(this._platform, files, frame.page().context());
|
||||||
await this._elementChannel.setInputFiles({
|
await this._elementChannel.setInputFiles({
|
||||||
...converted,
|
...converted,
|
||||||
...options
|
...options
|
||||||
@@ -168,21 +167,22 @@ class ElementHandle extends _jsHandle.JSHandle {
|
|||||||
return value === undefined ? null : value;
|
return value === undefined ? null : value;
|
||||||
}
|
}
|
||||||
async screenshot(options = {}) {
|
async screenshot(options = {}) {
|
||||||
|
const mask = options.mask;
|
||||||
const copy = {
|
const copy = {
|
||||||
...options,
|
...options,
|
||||||
mask: undefined
|
mask: undefined
|
||||||
};
|
};
|
||||||
if (!copy.type) copy.type = determineScreenshotType(options);
|
if (!copy.type) copy.type = determineScreenshotType(options);
|
||||||
if (options.mask) {
|
if (mask) {
|
||||||
copy.mask = options.mask.map(locator => ({
|
copy.mask = 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, _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;
|
||||||
}
|
}
|
||||||
@@ -234,11 +234,11 @@ function convertSelectOptionValues(values) {
|
|||||||
if (values === null) return {};
|
if (values === null) return {};
|
||||||
if (!Array.isArray(values)) values = [values];
|
if (!Array.isArray(values)) values = [values];
|
||||||
if (!values.length) return {};
|
if (!values.length) return {};
|
||||||
for (let i = 0; i < values.length; i++) (0, _utils.assert)(values[i] !== null, `options[${i}]: expected object, got null`);
|
for (let i = 0; i < values.length; i++) (0, _assert.assert)(values[i] !== null, `options[${i}]: expected object, got null`);
|
||||||
if (values[0] instanceof ElementHandle) return {
|
if (values[0] instanceof ElementHandle) return {
|
||||||
elements: values.map(v => v._elementChannel)
|
elements: values.map(v => v._elementChannel)
|
||||||
};
|
};
|
||||||
if ((0, _utils.isString)(values[0])) return {
|
if ((0, _rtti.isString)(values[0])) return {
|
||||||
options: values.map(valueOrLabel => ({
|
options: values.map(valueOrLabel => ({
|
||||||
valueOrLabel
|
valueOrLabel
|
||||||
}))
|
}))
|
||||||
@@ -250,50 +250,49 @@ function convertSelectOptionValues(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) >= _fileUtils.fileUploadSizeLimit;
|
||||||
}
|
}
|
||||||
async function resolvePathsAndDirectoryForInputFiles(items) {
|
async function resolvePathsAndDirectoryForInputFiles(platform, items) {
|
||||||
var _localPaths2;
|
var _localPaths;
|
||||||
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) throw new Error('Multiple directories are not supported');
|
||||||
localDirectory = _path.default.resolve(item);
|
localDirectory = platform.path().resolve(item);
|
||||||
} else {
|
} else {
|
||||||
var _localPaths;
|
localPaths !== null && localPaths !== void 0 ? 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 = localPaths) !== null && _localPaths !== void 0 && _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')) throw new Error('File paths cannot be mixed with buffers');
|
||||||
const [localPaths, localDirectory] = await resolvePathsAndDirectoryForInputFiles(items);
|
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 files = localDirectory ? (await platform.fs().promises.readdir(localDirectory, {
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
recursive: true
|
recursive: true
|
||||||
})).filter(f => f.isFile()).map(f => _path.default.join(f.path, f.name)) : localPaths;
|
})).filter(f => f.isFile()).map(f => platform.path().join(f.path, f.name)) : localPaths;
|
||||||
const {
|
const {
|
||||||
writableStreams,
|
writableStreams,
|
||||||
rootDir
|
rootDir
|
||||||
} = await context._wrapApiCall(async () => context._channel.createTempFiles({
|
} = await context._wrapApiCall(async () => context._channel.createTempFiles({
|
||||||
rootDirName: localDirectory ? _path.default.basename(localDirectory) : undefined,
|
rootDirName: localDirectory ? platform.path().basename(localDirectory) : undefined,
|
||||||
items: await Promise.all(files.map(async file => {
|
items: await Promise.all(files.map(async file => {
|
||||||
const lastModifiedMs = (await _fs.default.promises.stat(file)).mtimeMs;
|
const lastModifiedMs = (await platform.fs().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 < files.length; i++) {
|
||||||
const writable = _writableStream.WritableStream.from(writableStreams[i]);
|
const writable = _writableStream.WritableStream.from(writableStreams[i]);
|
||||||
await pipelineAsync(_fs.default.createReadStream(files[i]), writable.stream());
|
await platform.streamFile(files[i], writable.stream());
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
directoryStream: rootDir,
|
directoryStream: rootDir,
|
||||||
@@ -313,7 +312,7 @@ async function convertInputFiles(files, context) {
|
|||||||
}
|
}
|
||||||
function determineScreenshotType(options) {
|
function determineScreenshotType(options) {
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
const mimeType = _utilsBundle.mime.getType(options.path);
|
const mimeType = (0, _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}"`);
|
||||||
}
|
}
|
||||||
|
|||||||
4
tvapp2/node_modules/playwright-core/lib/client/errors.js
generated
vendored
@@ -7,8 +7,8 @@ exports.TimeoutError = exports.TargetClosedError = void 0;
|
|||||||
exports.isTargetClosedError = isTargetClosedError;
|
exports.isTargetClosedError = isTargetClosedError;
|
||||||
exports.parseError = parseError;
|
exports.parseError = parseError;
|
||||||
exports.serializeError = serializeError;
|
exports.serializeError = serializeError;
|
||||||
var _utils = require("../utils");
|
|
||||||
var _serializers = require("../protocol/serializers");
|
var _serializers = require("../protocol/serializers");
|
||||||
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -42,7 +42,7 @@ 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, _rtti.isError)(e)) return {
|
||||||
error: {
|
error: {
|
||||||
message: e.message,
|
message: e.message,
|
||||||
stack: e.stack,
|
stack: e.stack,
|
||||||
|
|||||||
13
tvapp2/node_modules/playwright-core/lib/client/eventEmitter.js
generated
vendored
@@ -4,8 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.EventEmitter = void 0;
|
exports.EventEmitter = void 0;
|
||||||
var _events = require("events");
|
|
||||||
var _utils = require("../utils");
|
|
||||||
/**
|
/**
|
||||||
* Copyright Joyent, Inc. and other Node contributors.
|
* Copyright Joyent, Inc. and other Node contributors.
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
@@ -31,12 +29,14 @@ var _utils = require("../utils");
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class EventEmitter {
|
class EventEmitter {
|
||||||
constructor() {
|
constructor(platform) {
|
||||||
this._events = undefined;
|
this._events = undefined;
|
||||||
this._eventsCount = 0;
|
this._eventsCount = 0;
|
||||||
this._maxListeners = undefined;
|
this._maxListeners = undefined;
|
||||||
this._pendingHandlers = new Map();
|
this._pendingHandlers = new Map();
|
||||||
this._rejectionHandler = void 0;
|
this._rejectionHandler = void 0;
|
||||||
|
this._platform = void 0;
|
||||||
|
this._platform = platform;
|
||||||
if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) {
|
if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) {
|
||||||
this._events = Object.create(null);
|
this._events = Object.create(null);
|
||||||
this._eventsCount = 0;
|
this._eventsCount = 0;
|
||||||
@@ -51,7 +51,7 @@ class EventEmitter {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
getMaxListeners() {
|
getMaxListeners() {
|
||||||
return this._maxListeners === undefined ? _events.EventEmitter.defaultMaxListeners : this._maxListeners;
|
return this._maxListeners === undefined ? this._platform.defaultMaxListeners() : this._maxListeners;
|
||||||
}
|
}
|
||||||
emit(type, ...args) {
|
emit(type, ...args) {
|
||||||
const events = this._events;
|
const events = this._events;
|
||||||
@@ -130,7 +130,7 @@ class EventEmitter {
|
|||||||
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
|
// eslint-disable-next-line no-console
|
||||||
console.warn(w);
|
console.warn(w);
|
||||||
}
|
}
|
||||||
@@ -191,14 +191,11 @@ class EventEmitter {
|
|||||||
if (options.behavior === 'wait') {
|
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) {
|
||||||
|
|||||||
121
tvapp2/node_modules/playwright-core/lib/client/fetch.js
generated
vendored
@@ -4,17 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.APIResponse = exports.APIRequestContext = exports.APIRequest = void 0;
|
exports.APIResponse = exports.APIRequestContext = exports.APIRequest = void 0;
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
var _browserContext = require("./browserContext");
|
||||||
var _path = _interopRequireDefault(require("path"));
|
|
||||||
var util = _interopRequireWildcard(require("util"));
|
|
||||||
var _utils = require("../utils");
|
|
||||||
var _fileUtils = require("../utils/fileUtils");
|
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
|
var _errors = require("./errors");
|
||||||
var _network = require("./network");
|
var _network = require("./network");
|
||||||
var _tracing = require("./tracing");
|
var _tracing = require("./tracing");
|
||||||
var _errors = require("./errors");
|
var _assert = require("../utils/isomorphic/assert");
|
||||||
var _browserContext = require("./browserContext");
|
var _fileUtils = require("./fileUtils");
|
||||||
let _Symbol$asyncDispose, _Symbol$asyncDispose2, _util$inspect$custom;
|
var _headers = require("../utils/isomorphic/headers");
|
||||||
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -30,42 +28,37 @@ let _Symbol$asyncDispose, _Symbol$asyncDispose2, _util$inspect$custom;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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._playwright = void 0;
|
||||||
this._contexts = 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;
|
var _this$_playwright$_de, _this$_playwright$_de2;
|
||||||
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, _headers.headersObjectToArray)(options.extraHTTPHeaders) : undefined,
|
||||||
storageState,
|
storageState,
|
||||||
tracesDir,
|
tracesDir: (_this$_playwright$_de = this._playwright._defaultLaunchOptions) === null || _this$_playwright$_de === void 0 ? void 0 : _this$_playwright$_de.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, _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$_de2 = this._playwright._defaultLaunchOptions) === null || _this$_playwright$_de2 === void 0 ? void 0 : _this$_playwright$_de2.tracesDir;
|
||||||
await context._instrumentation.runAfterCreateRequestContext(context);
|
await context._instrumentation.runAfterCreateRequestContext(context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.APIRequest = APIRequest;
|
exports.APIRequest = APIRequest;
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class APIRequestContext extends _channelOwner.ChannelOwner {
|
class APIRequestContext extends _channelOwner.ChannelOwner {
|
||||||
static from(channel) {
|
static from(channel) {
|
||||||
return channel._object;
|
return channel._object;
|
||||||
@@ -77,7 +70,7 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|||||||
this._closeReason = void 0;
|
this._closeReason = void 0;
|
||||||
this._tracing = _tracing.Tracing.from(initializer.tracing);
|
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 = {}) {
|
||||||
@@ -130,8 +123,8 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async fetch(urlOrRequest, options = {}) {
|
async fetch(urlOrRequest, options = {}) {
|
||||||
const url = (0, _utils.isString)(urlOrRequest) ? urlOrRequest : undefined;
|
const url = (0, _rtti.isString)(urlOrRequest) ? urlOrRequest : undefined;
|
||||||
const request = (0, _utils.isString)(urlOrRequest) ? undefined : urlOrRequest;
|
const request = (0, _rtti.isString)(urlOrRequest) ? undefined : urlOrRequest;
|
||||||
return await this._innerFetch({
|
return await this._innerFetch({
|
||||||
url,
|
url,
|
||||||
request,
|
request,
|
||||||
@@ -142,23 +135,23 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|||||||
return await this._wrapApiCall(async () => {
|
return await this._wrapApiCall(async () => {
|
||||||
var _options$request, _options$request2, _options$request3;
|
var _options$request, _options$request2, _options$request3;
|
||||||
if (this._closeReason) throw new _errors.TargetClosedError(this._closeReason);
|
if (this._closeReason) throw new _errors.TargetClosedError(this._closeReason);
|
||||||
(0, _utils.assert)(options.request || typeof options.url === 'string', 'First argument must be either URL string or Request');
|
(0, _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, _assert.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, _utils.assert)(options.maxRedirects === undefined || options.maxRedirects >= 0, `'maxRedirects' must be greater than or equal to '0'`);
|
(0, _assert.assert)(options.maxRedirects === undefined || 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, _assert.assert)(options.maxRetries === undefined || 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 !== undefined ? 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 = options.request) === null || _options$request === void 0 ? void 0 : _options$request.method());
|
||||||
let encodedParams = undefined;
|
let encodedParams = undefined;
|
||||||
if (typeof options.params === 'string') encodedParams = options.params;else if (options.params instanceof URLSearchParams) encodedParams = options.params.toString();
|
if (typeof options.params === 'string') encodedParams = options.params;else if (options.params instanceof URLSearchParams) encodedParams = options.params.toString();
|
||||||
// Cannot call allHeaders() here as the request may be paused inside route handler.
|
// Cannot call allHeaders() here as the request may be paused inside route handler.
|
||||||
const headersObj = options.headers || ((_options$request2 = options.request) === null || _options$request2 === void 0 ? void 0 : _options$request2.headers());
|
const headersObj = options.headers || ((_options$request2 = options.request) === null || _options$request2 === void 0 ? void 0 : _options$request2.headers());
|
||||||
const headers = headersObj ? (0, _utils.headersObjectToArray)(headersObj) : undefined;
|
const headers = headersObj ? (0, _headers.headersObjectToArray)(headersObj) : undefined;
|
||||||
let jsonData;
|
let jsonData;
|
||||||
let formData;
|
let formData;
|
||||||
let multipartData;
|
let multipartData;
|
||||||
let postDataBuffer;
|
let postDataBuffer;
|
||||||
if (options.data !== undefined) {
|
if (options.data !== undefined) {
|
||||||
if ((0, _utils.isString)(options.data)) {
|
if ((0, _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;
|
||||||
@@ -185,7 +178,7 @@ 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, _rtti.isString)(value)) {
|
||||||
multipartData.push({
|
multipartData.push({
|
||||||
name,
|
name,
|
||||||
value
|
value
|
||||||
@@ -204,7 +197,7 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Convert file-like values to ServerFilePayload structs.
|
// Convert file-like values to ServerFilePayload structs.
|
||||||
for (const [name, value] of Object.entries(options.multipart)) multipartData.push(await toFormField(name, value));
|
for (const [name, value] of Object.entries(options.multipart)) 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 === undefined && jsonData === undefined && formData === undefined && multipartData === undefined) postDataBuffer = ((_options$request3 = options.request) === null || _options$request3 === void 0 ? void 0 : _options$request3.postDataBuffer()) || undefined;
|
||||||
@@ -232,16 +225,19 @@ 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, _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, undefined, 2), 'utf8');
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.APIRequestContext = APIRequestContext;
|
exports.APIRequestContext = APIRequestContext;
|
||||||
async function toFormField(name, value) {
|
async function toFormField(platform, 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)) throw new Error(`Unexpected buffer type of 'data.${name}'`);
|
||||||
@@ -249,15 +245,15 @@ async function toFormField(name, value) {
|
|||||||
name,
|
name,
|
||||||
file: filePayloadToJson(payload)
|
file: filePayloadToJson(payload)
|
||||||
};
|
};
|
||||||
} else if (value instanceof _fs.default.ReadStream) {
|
} else if (typeOfValue === 'string' || typeOfValue === 'number' || typeOfValue === 'boolean') {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
file: await readStreamToJson(value)
|
value: String(value)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
value: String(value)
|
file: await readStreamToJson(platform, value)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,8 +266,6 @@ function isJsonParsable(value) {
|
|||||||
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._initializer = void 0;
|
||||||
@@ -280,6 +274,7 @@ class APIResponse {
|
|||||||
this._request = context;
|
this._request = context;
|
||||||
this._initializer = initializer;
|
this._initializer = initializer;
|
||||||
this._headers = new _network.RawHeaders(this._initializer.headers);
|
this._headers = new _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,16 +295,18 @@ 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 === undefined) throw new Error('Response has been disposed');
|
});
|
||||||
return result.binary;
|
if (result.binary === undefined) throw new Error('Response has been disposed');
|
||||||
} catch (e) {
|
return result.binary;
|
||||||
if ((0, _errors.isTargetClosedError)(e)) throw new Error('Response has been disposed');
|
} catch (e) {
|
||||||
throw e;
|
if ((0, _errors.isTargetClosedError)(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();
|
||||||
@@ -319,7 +316,7 @@ class APIResponse {
|
|||||||
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() {
|
||||||
@@ -327,7 +324,7 @@ class APIResponse {
|
|||||||
fetchUid: this._fetchUid()
|
fetchUid: this._fetchUid()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
[_util$inspect$custom]() {
|
_inspect() {
|
||||||
const headers = this.headersArray().map(({
|
const headers = this.headersArray().map(({
|
||||||
name,
|
name,
|
||||||
value
|
value
|
||||||
@@ -354,7 +351,7 @@ 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));
|
||||||
@@ -363,7 +360,7 @@ async function readStreamToJson(stream) {
|
|||||||
});
|
});
|
||||||
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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -380,10 +377,12 @@ function isJsonContentType(headers) {
|
|||||||
function objectToArray(map) {
|
function objectToArray(map) {
|
||||||
if (!map) return undefined;
|
if (!map) return undefined;
|
||||||
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 !== undefined) result.push({
|
||||||
value: String(value)
|
name,
|
||||||
});
|
value: String(value)
|
||||||
|
});
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
function isFilePayload(value) {
|
function isFilePayload(value) {
|
||||||
|
|||||||
51
tvapp2/node_modules/playwright-core/lib/client/frame.js
generated
vendored
@@ -5,22 +5,21 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
});
|
});
|
||||||
exports.Frame = void 0;
|
exports.Frame = void 0;
|
||||||
exports.verifyLoadState = verifyLoadState;
|
exports.verifyLoadState = verifyLoadState;
|
||||||
var _utils = require("../utils");
|
var _eventEmitter = require("./eventEmitter");
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _locator = require("./locator");
|
|
||||||
var _locatorUtils = require("../utils/isomorphic/locatorUtils");
|
|
||||||
var _elementHandle = require("./elementHandle");
|
|
||||||
var _jsHandle = require("./jsHandle");
|
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
|
||||||
var network = _interopRequireWildcard(require("./network"));
|
|
||||||
var _events = require("events");
|
|
||||||
var _waiter = require("./waiter");
|
|
||||||
var _events2 = require("./events");
|
|
||||||
var _types = require("./types");
|
|
||||||
var _clientHelper = require("./clientHelper");
|
var _clientHelper = require("./clientHelper");
|
||||||
|
var _elementHandle = require("./elementHandle");
|
||||||
|
var _events = require("./events");
|
||||||
|
var _jsHandle = require("./jsHandle");
|
||||||
|
var _locator = require("./locator");
|
||||||
|
var network = _interopRequireWildcard(require("./network"));
|
||||||
|
var _types = require("./types");
|
||||||
|
var _waiter = require("./waiter");
|
||||||
|
var _assert = require("../utils/isomorphic/assert");
|
||||||
|
var _locatorUtils = require("../utils/isomorphic/locatorUtils");
|
||||||
|
var _urlMatch = require("../utils/isomorphic/urlMatch");
|
||||||
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 _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 _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 && {}.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 2017 Google Inc. All rights reserved.
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
@@ -55,7 +54,7 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
this._detached = false;
|
this._detached = false;
|
||||||
this._childFrames = new Set();
|
this._childFrames = new Set();
|
||||||
this._page = void 0;
|
this._page = void 0;
|
||||||
this._eventEmitter = new _events.EventEmitter();
|
this._eventEmitter = new _eventEmitter.EventEmitter(parent._platform);
|
||||||
this._eventEmitter.setMaxListeners(0);
|
this._eventEmitter.setMaxListeners(0);
|
||||||
this._parentFrame = Frame.fromNullable(initializer.parentFrame);
|
this._parentFrame = Frame.fromNullable(initializer.parentFrame);
|
||||||
if (this._parentFrame) this._parentFrame._childFrames.add(this);
|
if (this._parentFrame) this._parentFrame._childFrames.add(this);
|
||||||
@@ -68,14 +67,14 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
this._eventEmitter.emit('loadstate', event.add);
|
this._eventEmitter.emit('loadstate', event.add);
|
||||||
}
|
}
|
||||||
if (event.remove) this._loadStates.delete(event.remove);
|
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 === 'load' && this._page) this._page.emit(_events.Events.Page.Load, this._page);
|
||||||
if (!this._parentFrame && event.add === 'domcontentloaded' && this._page) this._page.emit(_events2.Events.Page.DOMContentLoaded, this._page);
|
if (!this._parentFrame && event.add === 'domcontentloaded' && this._page) this._page.emit(_events.Events.Page.DOMContentLoaded, this._page);
|
||||||
});
|
});
|
||||||
this._channel.on('navigated', event => {
|
this._channel.on('navigated', event => {
|
||||||
this._url = event.url;
|
this._url = event.url;
|
||||||
this._name = event.name;
|
this._name = event.name;
|
||||||
this._eventEmitter.emit('navigated', event);
|
this._eventEmitter.emit('navigated', event);
|
||||||
if (!event.error && this._page) this._page.emit(_events2.Events.Page.FrameNavigated, this);
|
if (!event.error && this._page) this._page.emit(_events.Events.Page.FrameNavigated, this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
page() {
|
page() {
|
||||||
@@ -92,9 +91,9 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
_setupNavigationWaiter(options) {
|
_setupNavigationWaiter(options) {
|
||||||
const waiter = new _waiter.Waiter(this._page, '');
|
const waiter = new _waiter.Waiter(this._page, '');
|
||||||
if (this._page.isClosed()) waiter.rejectImmediately(this._page._closeErrorWithReason());
|
if (this._page.isClosed()) waiter.rejectImmediately(this._page._closeErrorWithReason());
|
||||||
waiter.rejectOnEvent(this._page, _events2.Events.Page.Close, () => this._page._closeErrorWithReason());
|
waiter.rejectOnEvent(this._page, _events.Events.Page.Close, () => this._page._closeErrorWithReason());
|
||||||
waiter.rejectOnEvent(this._page, _events2.Events.Page.Crash, new Error('Navigation failed because page crashed!'));
|
waiter.rejectOnEvent(this._page, _events.Events.Page.Crash, new Error('Navigation failed because page crashed!'));
|
||||||
waiter.rejectOnEvent(this._page, _events2.Events.Page.FrameDetached, new Error('Navigating frame was detached!'), frame => frame === this);
|
waiter.rejectOnEvent(this._page, _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;
|
||||||
@@ -110,7 +109,7 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
// Any failed navigation results in a rejection.
|
// Any failed navigation results in a rejection.
|
||||||
if (event.error) 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, _urlMatch.urlMatches)((_this$_page = this._page) === null || _this$_page === void 0 ? void 0 : _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);
|
||||||
@@ -146,7 +145,7 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async waitForURL(url, options = {}) {
|
async waitForURL(url, options = {}) {
|
||||||
var _this$_page2;
|
var _this$_page2;
|
||||||
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);
|
if ((0, _urlMatch.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);
|
||||||
await this.waitForNavigation({
|
await this.waitForNavigation({
|
||||||
url,
|
url,
|
||||||
...options
|
...options
|
||||||
@@ -268,7 +267,7 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
...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, _clientHelper.addSourceUrlToScript)(copy.content, copy.path);
|
||||||
}
|
}
|
||||||
return _elementHandle.ElementHandle.from((await this._channel.addScriptTag({
|
return _elementHandle.ElementHandle.from((await this._channel.addScriptTag({
|
||||||
@@ -280,7 +279,7 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
...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 _elementHandle.ElementHandle.from((await this._channel.addStyleTag({
|
||||||
@@ -440,7 +439,7 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
})).values;
|
})).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, _elementHandle.convertInputFiles)(this._platform, files, this.page().context());
|
||||||
await this._channel.setInputFiles({
|
await this._channel.setInputFiles({
|
||||||
selector,
|
selector,
|
||||||
...converted,
|
...converted,
|
||||||
@@ -482,7 +481,7 @@ class Frame extends _channelOwner.ChannelOwner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
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, _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' ? undefined : options.polling,
|
||||||
|
|||||||
16
tvapp2/node_modules/playwright-core/lib/client/harRouter.js
generated
vendored
@@ -4,8 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.HarRouter = void 0;
|
exports.HarRouter = void 0;
|
||||||
var _debugLogger = require("../utils/debugLogger");
|
|
||||||
let _Symbol$asyncDispose;
|
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -21,13 +19,13 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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,
|
harId,
|
||||||
error
|
error
|
||||||
} = await localUtils._channel.harOpen({
|
} = await localUtils.harOpen({
|
||||||
file
|
file
|
||||||
});
|
});
|
||||||
if (error) throw new Error(error);
|
if (error) throw new Error(error);
|
||||||
@@ -45,7 +43,7 @@ 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(),
|
||||||
@@ -54,7 +52,7 @@ class HarRouter {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
@@ -72,7 +70,7 @@ class HarRouter {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (response.action === 'error') _debugLogger.debugLogger.log('api', 'HAR: ' + response.message);
|
if (response.action === 'error') route._platform.log('api', 'HAR: ' + response.message);
|
||||||
// Report the error, but fall through to the default handler.
|
// Report the error, but fall through to the default handler.
|
||||||
|
|
||||||
if (this._notFoundAction === 'abort') {
|
if (this._notFoundAction === 'abort') {
|
||||||
@@ -87,11 +85,11 @@ class HarRouter {
|
|||||||
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
|
harId: this._harId
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|||||||
7
tvapp2/node_modules/playwright-core/lib/client/jsHandle.js
generated
vendored
@@ -8,9 +8,8 @@ exports.assertMaxArguments = assertMaxArguments;
|
|||||||
exports.parseResult = parseResult;
|
exports.parseResult = parseResult;
|
||||||
exports.serializeArgument = serializeArgument;
|
exports.serializeArgument = serializeArgument;
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _serializers = require("../protocol/serializers");
|
|
||||||
var _errors = require("./errors");
|
var _errors = require("./errors");
|
||||||
let _Symbol$asyncDispose;
|
var _serializers = require("../protocol/serializers");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -26,7 +25,7 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class JSHandle extends _channelOwner.ChannelOwner {
|
class JSHandle extends _channelOwner.ChannelOwner {
|
||||||
static from(handle) {
|
static from(handle) {
|
||||||
return handle._object;
|
return handle._object;
|
||||||
@@ -75,7 +74,7 @@ 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() {
|
||||||
|
|||||||
24
tvapp2/node_modules/playwright-core/lib/client/localUtils.js
generated
vendored
@@ -32,5 +32,29 @@ class LocalUtils extends _channelOwner.ChannelOwner {
|
|||||||
descriptor
|
descriptor
|
||||||
} of initializer.deviceDescriptors) this.devices[name] = 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;
|
exports.LocalUtils = LocalUtils;
|
||||||
33
tvapp2/node_modules/playwright-core/lib/client/locator.js
generated
vendored
@@ -6,13 +6,13 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
exports.Locator = exports.FrameLocator = void 0;
|
exports.Locator = exports.FrameLocator = void 0;
|
||||||
exports.setTestIdAttribute = setTestIdAttribute;
|
exports.setTestIdAttribute = setTestIdAttribute;
|
||||||
exports.testIdAttributeName = testIdAttributeName;
|
exports.testIdAttributeName = testIdAttributeName;
|
||||||
var util = _interopRequireWildcard(require("util"));
|
|
||||||
var _utils = require("../utils");
|
|
||||||
var _elementHandle = require("./elementHandle");
|
var _elementHandle = require("./elementHandle");
|
||||||
var _jsHandle = require("./jsHandle");
|
var _jsHandle = require("./jsHandle");
|
||||||
var _stringUtils = require("../utils/isomorphic/stringUtils");
|
var _locatorGenerators = require("../utils/isomorphic/locatorGenerators");
|
||||||
var _locatorUtils = require("../utils/isomorphic/locatorUtils");
|
var _locatorUtils = require("../utils/isomorphic/locatorUtils");
|
||||||
let _util$inspect$custom;
|
var _stringUtils = require("../utils/isomorphic/stringUtils");
|
||||||
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
|
var _time = require("../utils/isomorphic/time");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -28,9 +28,7 @@ let _util$inspect$custom;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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._frame = void 0;
|
||||||
@@ -49,12 +47,14 @@ class Locator {
|
|||||||
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 === null || options === void 0 ? void 0 : options.visible) !== undefined) 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, _utils.monotonicTime)() + timeout : 0;
|
const deadline = timeout ? (0, _time.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,
|
selector: this._selector,
|
||||||
@@ -65,7 +65,7 @@ class Locator {
|
|||||||
const handle = _elementHandle.ElementHandle.fromNullable(result.element);
|
const handle = _elementHandle.ElementHandle.fromNullable(result.element);
|
||||||
if (!handle) throw new Error(`Could not resolve ${this._selector} to DOM 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, _time.monotonicTime)() : 0);
|
||||||
} finally {
|
} finally {
|
||||||
await handle.dispose();
|
await handle.dispose();
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ class Locator {
|
|||||||
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, _rtti.isString)(selectorOrLocator)) return new Locator(this._frame, this._selector + ' >> ' + selectorOrLocator, options);
|
||||||
if (selectorOrLocator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
|
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);
|
return new Locator(this._frame, this._selector + ' >> internal:chain=' + JSON.stringify(selectorOrLocator._selector), options);
|
||||||
}
|
}
|
||||||
@@ -213,6 +213,9 @@ class Locator {
|
|||||||
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,
|
strict: true,
|
||||||
@@ -286,14 +289,18 @@ class Locator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async screenshot(options = {}) {
|
async screenshot(options = {}) {
|
||||||
|
const mask = options.mask;
|
||||||
return await this._withElement((h, timeout) => h.screenshot({
|
return await this._withElement((h, timeout) => h.screenshot({
|
||||||
...options,
|
...options,
|
||||||
|
mask,
|
||||||
timeout
|
timeout
|
||||||
}), options.timeout);
|
}), options.timeout);
|
||||||
}
|
}
|
||||||
async ariaSnapshot(options) {
|
async ariaSnapshot(options) {
|
||||||
const result = await this._frame._channel.ariaSnapshot({
|
const result = await this._frame._channel.ariaSnapshot({
|
||||||
...options,
|
...options,
|
||||||
|
id: options === null || options === void 0 ? void 0 : options._id,
|
||||||
|
mode: options === null || options === void 0 ? void 0 : options._mode,
|
||||||
selector: this._selector
|
selector: this._selector
|
||||||
});
|
});
|
||||||
return result.snapshot;
|
return result.snapshot;
|
||||||
@@ -381,11 +388,11 @@ class Locator {
|
|||||||
if (result.received !== undefined) result.received = (0, _jsHandle.parseResult)(result.received);
|
if (result.received !== undefined) result.received = (0, _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, _locatorGenerators.asLocator)('javascript', this._selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Locator = Locator;
|
exports.Locator = Locator;
|
||||||
@@ -397,7 +404,7 @@ class FrameLocator {
|
|||||||
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, _rtti.isString)(selectorOrLocator)) return new Locator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selectorOrLocator, options);
|
||||||
if (selectorOrLocator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
|
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);
|
return new Locator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selectorOrLocator._selector, options);
|
||||||
}
|
}
|
||||||
|
|||||||
82
tvapp2/node_modules/playwright-core/lib/client/network.js
generated
vendored
@@ -5,19 +5,21 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
});
|
});
|
||||||
exports.WebSocketRouteHandler = exports.WebSocketRoute = exports.WebSocket = exports.RouteHandler = exports.Route = exports.Response = exports.Request = exports.RawHeaders = void 0;
|
exports.WebSocketRouteHandler = exports.WebSocketRoute = exports.WebSocket = exports.RouteHandler = exports.Route = exports.Response = exports.Request = exports.RawHeaders = void 0;
|
||||||
exports.validateHeaders = validateHeaders;
|
exports.validateHeaders = validateHeaders;
|
||||||
var _url = require("url");
|
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _frame = require("./frame");
|
|
||||||
var _worker = require("./worker");
|
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
|
||||||
var _utilsBundle = require("../utilsBundle");
|
|
||||||
var _utils = require("../utils");
|
|
||||||
var _manualPromise = require("../utils/manualPromise");
|
|
||||||
var _events = require("./events");
|
|
||||||
var _waiter = require("./waiter");
|
|
||||||
var _fetch = require("./fetch");
|
|
||||||
var _errors = require("./errors");
|
var _errors = require("./errors");
|
||||||
let _Symbol$asyncDispose;
|
var _events = require("./events");
|
||||||
|
var _fetch = require("./fetch");
|
||||||
|
var _frame = require("./frame");
|
||||||
|
var _waiter = require("./waiter");
|
||||||
|
var _worker = require("./worker");
|
||||||
|
var _assert = require("../utils/isomorphic/assert");
|
||||||
|
var _headers = require("../utils/isomorphic/headers");
|
||||||
|
var _urlMatch = require("../utils/isomorphic/urlMatch");
|
||||||
|
var _manualPromise = require("../utils/isomorphic/manualPromise");
|
||||||
|
var _multimap = require("../utils/isomorphic/multimap");
|
||||||
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
|
var _stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
|
var _mimeType = require("../utils/isomorphic/mimeType");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -33,7 +35,7 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
class Request extends _channelOwner.ChannelOwner {
|
class Request extends _channelOwner.ChannelOwner {
|
||||||
static from(request) {
|
static from(request) {
|
||||||
return request._object;
|
return request._object;
|
||||||
@@ -88,7 +90,7 @@ class Request extends _channelOwner.ChannelOwner {
|
|||||||
const contentType = this.headers()['content-type'];
|
const contentType = this.headers()['content-type'];
|
||||||
if (contentType !== null && contentType !== void 0 && contentType.includes('application/x-www-form-urlencoded')) {
|
if (contentType !== null && contentType !== void 0 && contentType.includes('application/x-www-form-urlencoded')) {
|
||||||
const entries = {};
|
const entries = {};
|
||||||
const parsed = new _url.URLSearchParams(postData);
|
const parsed = new URLSearchParams(postData);
|
||||||
for (const [k, v] of parsed.entries()) entries[k] = v;
|
for (const [k, v] of parsed.entries()) entries[k] = v;
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
@@ -134,7 +136,7 @@ class Request extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
frame() {
|
frame() {
|
||||||
if (!this._initializer.frame) {
|
if (!this._initializer.frame) {
|
||||||
(0, _utils.assert)(this.serviceWorker());
|
(0, _assert.assert)(this.serviceWorker());
|
||||||
throw new Error('Service Worker requests do not have an associated frame.');
|
throw new Error('Service Worker requests do not have an associated frame.');
|
||||||
}
|
}
|
||||||
const frame = _frame.Frame.from(this._initializer.frame);
|
const frame = _frame.Frame.from(this._initializer.frame);
|
||||||
@@ -184,7 +186,7 @@ class Request extends _channelOwner.ChannelOwner {
|
|||||||
if (overrides.url) this._fallbackOverrides.url = overrides.url;
|
if (overrides.url) this._fallbackOverrides.url = overrides.url;
|
||||||
if (overrides.method) this._fallbackOverrides.method = overrides.method;
|
if (overrides.method) this._fallbackOverrides.method = overrides.method;
|
||||||
if (overrides.headers) this._fallbackOverrides.headers = overrides.headers;
|
if (overrides.headers) this._fallbackOverrides.headers = overrides.headers;
|
||||||
if ((0, _utils.isString)(overrides.postData)) this._fallbackOverrides.postDataBuffer = Buffer.from(overrides.postData, 'utf-8');else if (overrides.postData instanceof Buffer) this._fallbackOverrides.postDataBuffer = overrides.postData;else if (overrides.postData) this._fallbackOverrides.postDataBuffer = Buffer.from(JSON.stringify(overrides.postData), 'utf-8');
|
if ((0, _rtti.isString)(overrides.postData)) this._fallbackOverrides.postDataBuffer = Buffer.from(overrides.postData, 'utf-8');else if (overrides.postData instanceof Buffer) this._fallbackOverrides.postDataBuffer = overrides.postData;else if (overrides.postData) this._fallbackOverrides.postDataBuffer = Buffer.from(JSON.stringify(overrides.postData), 'utf-8');
|
||||||
}
|
}
|
||||||
_fallbackOverridesForContinue() {
|
_fallbackOverridesForContinue() {
|
||||||
return this._fallbackOverrides;
|
return this._fallbackOverrides;
|
||||||
@@ -272,13 +274,12 @@ class Route extends _channelOwner.ChannelOwner {
|
|||||||
body
|
body
|
||||||
} = options;
|
} = options;
|
||||||
if (options.json !== undefined) {
|
if (options.json !== undefined) {
|
||||||
(0, _utils.assert)(options.body === undefined, 'Can specify either body or json parameters');
|
(0, _assert.assert)(options.body === undefined, 'Can specify either body or json parameters');
|
||||||
body = JSON.stringify(options.json);
|
body = JSON.stringify(options.json);
|
||||||
}
|
}
|
||||||
if (options.response instanceof _fetch.APIResponse) {
|
if (options.response instanceof _fetch.APIResponse) {
|
||||||
var _statusOption, _headersOption;
|
statusOption !== null && statusOption !== void 0 ? statusOption : statusOption = options.response.status();
|
||||||
(_statusOption = statusOption) !== null && _statusOption !== void 0 ? _statusOption : statusOption = options.response.status();
|
headersOption !== null && headersOption !== void 0 ? headersOption : headersOption = options.response.headers();
|
||||||
(_headersOption = headersOption) !== null && _headersOption !== void 0 ? _headersOption : headersOption = options.response.headers();
|
|
||||||
if (body === undefined && options.path === undefined) {
|
if (body === undefined && options.path === undefined) {
|
||||||
if (options.response._request._connection === this._connection) fetchResponseUid = options.response._fetchUid();else body = await options.response.body();
|
if (options.response._request._connection === this._connection) fetchResponseUid = options.response._fetchUid();else body = await options.response.body();
|
||||||
}
|
}
|
||||||
@@ -286,11 +287,11 @@ class Route extends _channelOwner.ChannelOwner {
|
|||||||
let isBase64 = false;
|
let isBase64 = false;
|
||||||
let length = 0;
|
let length = 0;
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
const buffer = await _fs.default.promises.readFile(options.path);
|
const buffer = await this._platform.fs().promises.readFile(options.path);
|
||||||
body = buffer.toString('base64');
|
body = buffer.toString('base64');
|
||||||
isBase64 = true;
|
isBase64 = true;
|
||||||
length = buffer.length;
|
length = buffer.length;
|
||||||
} else if ((0, _utils.isString)(body)) {
|
} else if ((0, _rtti.isString)(body)) {
|
||||||
isBase64 = false;
|
isBase64 = false;
|
||||||
length = Buffer.byteLength(body);
|
length = Buffer.byteLength(body);
|
||||||
} else if (body) {
|
} else if (body) {
|
||||||
@@ -300,11 +301,11 @@ class Route extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
const headers = {};
|
const headers = {};
|
||||||
for (const header of Object.keys(headersOption || {})) headers[header.toLowerCase()] = String(headersOption[header]);
|
for (const header of Object.keys(headersOption || {})) headers[header.toLowerCase()] = String(headersOption[header]);
|
||||||
if (options.contentType) headers['content-type'] = String(options.contentType);else if (options.json) headers['content-type'] = 'application/json';else if (options.path) headers['content-type'] = _utilsBundle.mime.getType(options.path) || 'application/octet-stream';
|
if (options.contentType) headers['content-type'] = String(options.contentType);else if (options.json) headers['content-type'] = 'application/json';else if (options.path) headers['content-type'] = (0, _mimeType.getMimeTypeForPath)(options.path) || 'application/octet-stream';
|
||||||
if (length && !('content-length' in headers)) headers['content-length'] = String(length);
|
if (length && !('content-length' in headers)) headers['content-length'] = String(length);
|
||||||
await this._raceWithTargetClose(this._channel.fulfill({
|
await this._raceWithTargetClose(this._channel.fulfill({
|
||||||
status: statusOption || 200,
|
status: statusOption || 200,
|
||||||
headers: (0, _utils.headersObjectToArray)(headers),
|
headers: (0, _headers.headersObjectToArray)(headers),
|
||||||
body,
|
body,
|
||||||
isBase64,
|
isBase64,
|
||||||
fetchResponseUid
|
fetchResponseUid
|
||||||
@@ -329,14 +330,13 @@ class Route extends _channelOwner.ChannelOwner {
|
|||||||
return await this._raceWithTargetClose(this._channel.continue({
|
return await this._raceWithTargetClose(this._channel.continue({
|
||||||
url: options.url,
|
url: options.url,
|
||||||
method: options.method,
|
method: options.method,
|
||||||
headers: options.headers ? (0, _utils.headersObjectToArray)(options.headers) : undefined,
|
headers: options.headers ? (0, _headers.headersObjectToArray)(options.headers) : undefined,
|
||||||
postData: options.postDataBuffer,
|
postData: options.postDataBuffer,
|
||||||
isFallback
|
isFallback
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Route = Route;
|
exports.Route = Route;
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class WebSocketRoute extends _channelOwner.ChannelOwner {
|
class WebSocketRoute extends _channelOwner.ChannelOwner {
|
||||||
static from(route) {
|
static from(route) {
|
||||||
return route._object;
|
return route._object;
|
||||||
@@ -370,7 +370,7 @@ class WebSocketRoute extends _channelOwner.ChannelOwner {
|
|||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
send: message => {
|
send: message => {
|
||||||
if ((0, _utils.isString)(message)) this._channel.sendToServer({
|
if ((0, _rtti.isString)(message)) this._channel.sendToServer({
|
||||||
message,
|
message,
|
||||||
isBase64: false
|
isBase64: false
|
||||||
}).catch(() => {});else this._channel.sendToServer({
|
}).catch(() => {});else this._channel.sendToServer({
|
||||||
@@ -439,7 +439,7 @@ class WebSocketRoute extends _channelOwner.ChannelOwner {
|
|||||||
return this._server;
|
return this._server;
|
||||||
}
|
}
|
||||||
send(message) {
|
send(message) {
|
||||||
if ((0, _utils.isString)(message)) this._channel.sendToPage({
|
if ((0, _rtti.isString)(message)) this._channel.sendToPage({
|
||||||
message,
|
message,
|
||||||
isBase64: false
|
isBase64: false
|
||||||
}).catch(() => {});else this._channel.sendToPage({
|
}).catch(() => {});else this._channel.sendToPage({
|
||||||
@@ -453,7 +453,7 @@ class WebSocketRoute extends _channelOwner.ChannelOwner {
|
|||||||
onClose(handler) {
|
onClose(handler) {
|
||||||
this._onPageClose = handler;
|
this._onPageClose = handler;
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async _afterHandle() {
|
async _afterHandle() {
|
||||||
@@ -476,9 +476,9 @@ class WebSocketRouteHandler {
|
|||||||
const patterns = [];
|
const patterns = [];
|
||||||
let all = false;
|
let all = false;
|
||||||
for (const handler of handlers) {
|
for (const handler of handlers) {
|
||||||
if ((0, _utils.isString)(handler.url)) patterns.push({
|
if ((0, _rtti.isString)(handler.url)) patterns.push({
|
||||||
glob: handler.url
|
glob: handler.url
|
||||||
});else if ((0, _utils.isRegExp)(handler.url)) patterns.push({
|
});else if ((0, _rtti.isRegExp)(handler.url)) patterns.push({
|
||||||
regexSource: handler.url.source,
|
regexSource: handler.url.source,
|
||||||
regexFlags: handler.url.flags
|
regexFlags: handler.url.flags
|
||||||
});else all = true;
|
});else all = true;
|
||||||
@@ -489,7 +489,7 @@ class WebSocketRouteHandler {
|
|||||||
return patterns;
|
return patterns;
|
||||||
}
|
}
|
||||||
matches(wsURL) {
|
matches(wsURL) {
|
||||||
return (0, _utils.urlMatches)(this._baseURL, wsURL, this.url);
|
return (0, _urlMatch.urlMatches)(this._baseURL, wsURL, this.url);
|
||||||
}
|
}
|
||||||
async handle(webSocketRoute) {
|
async handle(webSocketRoute) {
|
||||||
const handler = this.handler;
|
const handler = this.handler;
|
||||||
@@ -644,11 +644,11 @@ exports.WebSocket = WebSocket;
|
|||||||
function validateHeaders(headers) {
|
function validateHeaders(headers) {
|
||||||
for (const key of Object.keys(headers)) {
|
for (const key of Object.keys(headers)) {
|
||||||
const value = headers[key];
|
const value = headers[key];
|
||||||
if (!Object.is(value, undefined) && !(0, _utils.isString)(value)) throw new Error(`Expected value of header "${key}" to be String, but "${typeof value}" is found.`);
|
if (!Object.is(value, undefined) && !(0, _rtti.isString)(value)) throw new Error(`Expected value of header "${key}" to be String, but "${typeof value}" is found.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class RouteHandler {
|
class RouteHandler {
|
||||||
constructor(baseURL, url, handler, times = Number.MAX_SAFE_INTEGER) {
|
constructor(platform, baseURL, url, handler, times = Number.MAX_SAFE_INTEGER) {
|
||||||
this.handledCount = 0;
|
this.handledCount = 0;
|
||||||
this._baseURL = void 0;
|
this._baseURL = void 0;
|
||||||
this._times = void 0;
|
this._times = void 0;
|
||||||
@@ -656,20 +656,20 @@ class RouteHandler {
|
|||||||
this.handler = void 0;
|
this.handler = void 0;
|
||||||
this._ignoreException = false;
|
this._ignoreException = false;
|
||||||
this._activeInvocations = new Set();
|
this._activeInvocations = new Set();
|
||||||
this._svedZone = void 0;
|
this._savedZone = void 0;
|
||||||
this._baseURL = baseURL;
|
this._baseURL = baseURL;
|
||||||
this._times = times;
|
this._times = times;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this._svedZone = _utils.zones.current().without('apiZone');
|
this._savedZone = platform.zones.current().pop();
|
||||||
}
|
}
|
||||||
static prepareInterceptionPatterns(handlers) {
|
static prepareInterceptionPatterns(handlers) {
|
||||||
const patterns = [];
|
const patterns = [];
|
||||||
let all = false;
|
let all = false;
|
||||||
for (const handler of handlers) {
|
for (const handler of handlers) {
|
||||||
if ((0, _utils.isString)(handler.url)) patterns.push({
|
if ((0, _rtti.isString)(handler.url)) patterns.push({
|
||||||
glob: handler.url
|
glob: handler.url
|
||||||
});else if ((0, _utils.isRegExp)(handler.url)) patterns.push({
|
});else if ((0, _rtti.isRegExp)(handler.url)) patterns.push({
|
||||||
regexSource: handler.url.source,
|
regexSource: handler.url.source,
|
||||||
regexFlags: handler.url.flags
|
regexFlags: handler.url.flags
|
||||||
});else all = true;
|
});else all = true;
|
||||||
@@ -680,10 +680,10 @@ class RouteHandler {
|
|||||||
return patterns;
|
return patterns;
|
||||||
}
|
}
|
||||||
matches(requestURL) {
|
matches(requestURL) {
|
||||||
return (0, _utils.urlMatches)(this._baseURL, requestURL, this.url);
|
return (0, _urlMatch.urlMatches)(this._baseURL, requestURL, this.url);
|
||||||
}
|
}
|
||||||
async handle(route) {
|
async handle(route) {
|
||||||
return await this._svedZone.run(async () => this._handleImpl(route));
|
return await this._savedZone.run(async () => this._handleImpl(route));
|
||||||
}
|
}
|
||||||
async _handleImpl(route) {
|
async _handleImpl(route) {
|
||||||
const handlerInvocation = {
|
const handlerInvocation = {
|
||||||
@@ -699,7 +699,7 @@ class RouteHandler {
|
|||||||
if ((0, _errors.isTargetClosedError)(e)) {
|
if ((0, _errors.isTargetClosedError)(e)) {
|
||||||
// We are failing in the handler because the target close closed.
|
// We are failing in the handler because the target close closed.
|
||||||
// Give user a hint!
|
// Give user a hint!
|
||||||
(0, _utils.rewriteErrorMessage)(e, `"${e.message}" while running route callback.\nConsider awaiting \`await page.unrouteAll({ behavior: 'ignoreErrors' })\`\nbefore the end of the test to ignore remaining routes in flight.`);
|
(0, _stackTrace.rewriteErrorMessage)(e, `"${e.message}" while running route callback.\nConsider awaiting \`await page.unrouteAll({ behavior: 'ignoreErrors' })\`\nbefore the end of the test to ignore remaining routes in flight.`);
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -745,7 +745,7 @@ class RawHeaders {
|
|||||||
}
|
}
|
||||||
constructor(headers) {
|
constructor(headers) {
|
||||||
this._headersArray = void 0;
|
this._headersArray = void 0;
|
||||||
this._headersMap = new _utils.MultiMap();
|
this._headersMap = new _multimap.MultiMap();
|
||||||
this._headersArray = headers;
|
this._headersArray = headers;
|
||||||
for (const header of headers) this._headersMap.set(header.name.toLowerCase(), header.value);
|
for (const header of headers) this._headersMap.set(header.name.toLowerCase(), header.value);
|
||||||
}
|
}
|
||||||
|
|||||||
85
tvapp2/node_modules/playwright-core/lib/client/page.js
generated
vendored
@@ -4,11 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Page = exports.BindingCall = void 0;
|
exports.Page = exports.BindingCall = void 0;
|
||||||
var _fs = _interopRequireDefault(require("fs"));
|
|
||||||
var _path = _interopRequireDefault(require("path"));
|
|
||||||
var _errors = require("./errors");
|
|
||||||
var _timeoutSettings = require("../common/timeoutSettings");
|
|
||||||
var _utils = require("../utils");
|
|
||||||
var _accessibility = require("./accessibility");
|
var _accessibility = require("./accessibility");
|
||||||
var _artifact = require("./artifact");
|
var _artifact = require("./artifact");
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
@@ -16,17 +11,25 @@ var _clientHelper = require("./clientHelper");
|
|||||||
var _coverage = require("./coverage");
|
var _coverage = require("./coverage");
|
||||||
var _download = require("./download");
|
var _download = require("./download");
|
||||||
var _elementHandle = require("./elementHandle");
|
var _elementHandle = require("./elementHandle");
|
||||||
|
var _errors = require("./errors");
|
||||||
var _events = require("./events");
|
var _events = require("./events");
|
||||||
var _fileChooser = require("./fileChooser");
|
var _fileChooser = require("./fileChooser");
|
||||||
var _frame = require("./frame");
|
var _frame = require("./frame");
|
||||||
|
var _harRouter = require("./harRouter");
|
||||||
var _input = require("./input");
|
var _input = require("./input");
|
||||||
var _jsHandle = require("./jsHandle");
|
var _jsHandle = require("./jsHandle");
|
||||||
var _network = require("./network");
|
var _network = require("./network");
|
||||||
var _video = require("./video");
|
var _video = require("./video");
|
||||||
var _waiter = require("./waiter");
|
var _waiter = require("./waiter");
|
||||||
var _worker = require("./worker");
|
var _worker = require("./worker");
|
||||||
var _harRouter = require("./harRouter");
|
var _timeoutSettings = require("./timeoutSettings");
|
||||||
let _Symbol$asyncDispose;
|
var _assert = require("../utils/isomorphic/assert");
|
||||||
|
var _fileUtils = require("./fileUtils");
|
||||||
|
var _headers = require("../utils/isomorphic/headers");
|
||||||
|
var _stringUtils = require("../utils/isomorphic/stringUtils");
|
||||||
|
var _urlMatch = require("../utils/isomorphic/urlMatch");
|
||||||
|
var _manualPromise = require("../utils/isomorphic/manualPromise");
|
||||||
|
var _rtti = require("../utils/isomorphic/rtti");
|
||||||
/**
|
/**
|
||||||
* Copyright 2017 Google Inc. All rights reserved.
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
* Modifications copyright (c) Microsoft Corporation.
|
* Modifications copyright (c) Microsoft Corporation.
|
||||||
@@ -43,8 +46,7 @@ let _Symbol$asyncDispose;
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
||||||
_Symbol$asyncDispose = Symbol.asyncDispose;
|
|
||||||
class Page extends _channelOwner.ChannelOwner {
|
class Page extends _channelOwner.ChannelOwner {
|
||||||
static from(page) {
|
static from(page) {
|
||||||
return page._object;
|
return page._object;
|
||||||
@@ -60,7 +62,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
this._frames = new Set();
|
this._frames = new Set();
|
||||||
this._workers = new Set();
|
this._workers = new Set();
|
||||||
this._closed = false;
|
this._closed = false;
|
||||||
this._closedOrCrashedScope = new _utils.LongStandingScope();
|
this._closedOrCrashedScope = new _manualPromise.LongStandingScope();
|
||||||
this._viewportSize = void 0;
|
this._viewportSize = void 0;
|
||||||
this._routes = [];
|
this._routes = [];
|
||||||
this._webSocketRoutes = [];
|
this._webSocketRoutes = [];
|
||||||
@@ -80,7 +82,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
this._harRouters = [];
|
this._harRouters = [];
|
||||||
this._locatorHandlers = new Map();
|
this._locatorHandlers = new Map();
|
||||||
this._browserContext = parent;
|
this._browserContext = parent;
|
||||||
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(this._browserContext._timeoutSettings);
|
this._timeoutSettings = new _timeoutSettings.TimeoutSettings(this._platform, this._browserContext._timeoutSettings);
|
||||||
this.accessibility = new _accessibility.Accessibility(this._channel);
|
this.accessibility = new _accessibility.Accessibility(this._channel);
|
||||||
this.keyboard = new _input.Keyboard(this);
|
this.keyboard = new _input.Keyboard(this);
|
||||||
this.mouse = new _input.Mouse(this);
|
this.mouse = new _input.Mouse(this);
|
||||||
@@ -208,12 +210,12 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
return this._mainFrame;
|
return this._mainFrame;
|
||||||
}
|
}
|
||||||
frame(frameSelector) {
|
frame(frameSelector) {
|
||||||
const name = (0, _utils.isString)(frameSelector) ? frameSelector : frameSelector.name;
|
const name = (0, _rtti.isString)(frameSelector) ? frameSelector : frameSelector.name;
|
||||||
const url = (0, _utils.isObject)(frameSelector) ? frameSelector.url : undefined;
|
const url = (0, _rtti.isObject)(frameSelector) ? frameSelector.url : undefined;
|
||||||
(0, _utils.assert)(name || url, 'Either name or url matcher should be specified');
|
(0, _assert.assert)(name || url, 'Either name or url matcher should be specified');
|
||||||
return this.frames().find(f => {
|
return this.frames().find(f => {
|
||||||
if (name) return f.name() === name;
|
if (name) return f.name() === name;
|
||||||
return (0, _utils.urlMatches)(this._browserContext._options.baseURL, f.url(), url);
|
return (0, _urlMatch.urlMatches)(this._browserContext._options.baseURL, f.url(), url);
|
||||||
}) || null;
|
}) || null;
|
||||||
}
|
}
|
||||||
frames() {
|
frames() {
|
||||||
@@ -222,18 +224,18 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
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
|
||||||
}).catch(() => {});
|
});
|
||||||
}, true);
|
}, true).catch(() => {});
|
||||||
}
|
}
|
||||||
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
|
||||||
}).catch(() => {});
|
});
|
||||||
}, true);
|
}, true).catch(() => {});
|
||||||
}
|
}
|
||||||
_forceVideo() {
|
_forceVideo() {
|
||||||
if (!this._video) this._video = new _video.Video(this, this._connection);
|
if (!this._video) this._video = new _video.Video(this, this._connection);
|
||||||
@@ -293,7 +295,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
async setExtraHTTPHeaders(headers) {
|
async setExtraHTTPHeaders(headers) {
|
||||||
(0, _network.validateHeaders)(headers);
|
(0, _network.validateHeaders)(headers);
|
||||||
await this._channel.setExtraHTTPHeaders({
|
await this._channel.setExtraHTTPHeaders({
|
||||||
headers: (0, _utils.headersObjectToArray)(headers)
|
headers: (0, _headers.headersObjectToArray)(headers)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
url() {
|
url() {
|
||||||
@@ -368,7 +370,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async waitForRequest(urlOrPredicate, options = {}) {
|
async waitForRequest(urlOrPredicate, options = {}) {
|
||||||
const predicate = async request => {
|
const predicate = async request => {
|
||||||
if ((0, _utils.isString)(urlOrPredicate) || (0, _utils.isRegExp)(urlOrPredicate)) return (0, _utils.urlMatches)(this._browserContext._options.baseURL, request.url(), urlOrPredicate);
|
if ((0, _rtti.isString)(urlOrPredicate) || (0, _rtti.isRegExp)(urlOrPredicate)) return (0, _urlMatch.urlMatches)(this._browserContext._options.baseURL, request.url(), urlOrPredicate);
|
||||||
return await urlOrPredicate(request);
|
return await urlOrPredicate(request);
|
||||||
};
|
};
|
||||||
const trimmedUrl = trimUrl(urlOrPredicate);
|
const trimmedUrl = trimUrl(urlOrPredicate);
|
||||||
@@ -380,7 +382,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async waitForResponse(urlOrPredicate, options = {}) {
|
async waitForResponse(urlOrPredicate, options = {}) {
|
||||||
const predicate = async response => {
|
const predicate = async response => {
|
||||||
if ((0, _utils.isString)(urlOrPredicate) || (0, _utils.isRegExp)(urlOrPredicate)) return (0, _utils.urlMatches)(this._browserContext._options.baseURL, response.url(), urlOrPredicate);
|
if ((0, _rtti.isString)(urlOrPredicate) || (0, _rtti.isRegExp)(urlOrPredicate)) return (0, _urlMatch.urlMatches)(this._browserContext._options.baseURL, response.url(), urlOrPredicate);
|
||||||
return await urlOrPredicate(response);
|
return await urlOrPredicate(response);
|
||||||
};
|
};
|
||||||
const trimmedUrl = trimUrl(urlOrPredicate);
|
const trimmedUrl = trimUrl(urlOrPredicate);
|
||||||
@@ -432,7 +434,8 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
media: options.media === null ? 'no-override' : options.media,
|
media: options.media === null ? 'no-override' : options.media,
|
||||||
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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async setViewportSize(viewportSize) {
|
async setViewportSize(viewportSize) {
|
||||||
@@ -449,21 +452,23 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
return await this._mainFrame.evaluate(pageFunction, arg);
|
return await this._mainFrame.evaluate(pageFunction, arg);
|
||||||
}
|
}
|
||||||
async addInitScript(script, arg) {
|
async addInitScript(script, arg) {
|
||||||
const source = await (0, _clientHelper.evaluationScript)(script, arg);
|
const source = await (0, _clientHelper.evaluationScript)(this._platform, script, arg);
|
||||||
await this._channel.addInitScript({
|
await this._channel.addInitScript({
|
||||||
source
|
source
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async route(url, handler, options = {}) {
|
async route(url, handler, options = {}) {
|
||||||
this._routes.unshift(new _network.RouteHandler(this._browserContext._options.baseURL, url, handler, options.times));
|
this._routes.unshift(new _network.RouteHandler(this._platform, this._browserContext._options.baseURL, url, handler, options.times));
|
||||||
await this._updateInterceptionPatterns();
|
await this._updateInterceptionPatterns();
|
||||||
}
|
}
|
||||||
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._browserContext._recordIntoHAR(har, this, options);
|
await this._browserContext._recordIntoHAR(har, this, options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const harRouter = await _harRouter.HarRouter.create(this._connection.localUtils(), har, options.notFound || 'abort', {
|
const harRouter = await _harRouter.HarRouter.create(localUtils, har, options.notFound || 'abort', {
|
||||||
urlMatch: options.url
|
urlMatch: options.url
|
||||||
});
|
});
|
||||||
this._harRouters.push(harRouter);
|
this._harRouters.push(harRouter);
|
||||||
@@ -485,7 +490,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
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, _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');
|
||||||
}
|
}
|
||||||
@@ -509,21 +514,22 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async screenshot(options = {}) {
|
async screenshot(options = {}) {
|
||||||
|
const mask = options.mask;
|
||||||
const copy = {
|
const copy = {
|
||||||
...options,
|
...options,
|
||||||
mask: undefined
|
mask: undefined
|
||||||
};
|
};
|
||||||
if (!copy.type) copy.type = (0, _elementHandle.determineScreenshotType)(options);
|
if (!copy.type) copy.type = (0, _elementHandle.determineScreenshotType)(options);
|
||||||
if (options.mask) {
|
if (mask) {
|
||||||
copy.mask = options.mask.map(locator => ({
|
copy.mask = mask.map(locator => ({
|
||||||
frame: locator._frame._channel,
|
frame: locator._frame._channel,
|
||||||
selector: locator._selector
|
selector: locator._selector
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
const result = await this._channel.screenshot(copy);
|
const result = await this._channel.screenshot(copy);
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
await (0, _utils.mkdirIfNeeded)(options.path);
|
await (0, _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;
|
||||||
}
|
}
|
||||||
@@ -549,7 +555,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
async bringToFront() {
|
async bringToFront() {
|
||||||
await this._channel.bringToFront();
|
await this._channel.bringToFront();
|
||||||
}
|
}
|
||||||
async [_Symbol$asyncDispose]() {
|
async [Symbol.asyncDispose]() {
|
||||||
await this.close();
|
await this.close();
|
||||||
}
|
}
|
||||||
async close(options = {}) {
|
async close(options = {}) {
|
||||||
@@ -678,7 +684,7 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
async pause(_options) {
|
async pause(_options) {
|
||||||
var _this$_instrumentatio;
|
var _this$_instrumentatio;
|
||||||
if (require('inspector').url()) return;
|
if (this._platform.isJSDebuggerAttached()) return;
|
||||||
const defaultNavigationTimeout = this._browserContext._timeoutSettings.defaultNavigationTimeout();
|
const defaultNavigationTimeout = this._browserContext._timeoutSettings.defaultNavigationTimeout();
|
||||||
const defaultTimeout = this._browserContext._timeoutSettings.defaultTimeout();
|
const defaultTimeout = this._browserContext._timeoutSettings.defaultTimeout();
|
||||||
this._browserContext.setDefaultNavigationTimeout(0);
|
this._browserContext.setDefaultNavigationTimeout(0);
|
||||||
@@ -705,10 +711,11 @@ class Page extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
const result = await this._channel.pdf(transportOptions);
|
const result = await this._channel.pdf(transportOptions);
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
await _fs.default.promises.mkdir(_path.default.dirname(options.path), {
|
const platform = this._platform;
|
||||||
|
await platform.fs().promises.mkdir(platform.path().dirname(options.path), {
|
||||||
recursive: true
|
recursive: true
|
||||||
});
|
});
|
||||||
await _fs.default.promises.writeFile(options.path, result.pdf);
|
await platform.fs().promises.writeFile(options.path, result.pdf);
|
||||||
}
|
}
|
||||||
return result.pdf;
|
return result.pdf;
|
||||||
}
|
}
|
||||||
@@ -743,6 +750,6 @@ class BindingCall extends _channelOwner.ChannelOwner {
|
|||||||
}
|
}
|
||||||
exports.BindingCall = BindingCall;
|
exports.BindingCall = BindingCall;
|
||||||
function trimUrl(param) {
|
function trimUrl(param) {
|
||||||
if ((0, _utils.isRegExp)(param)) return `/${(0, _utils.trimStringWithEllipsis)(param.source, 50)}/${param.flags}`;
|
if ((0, _rtti.isRegExp)(param)) return `/${(0, _stringUtils.trimStringWithEllipsis)(param.source, 50)}/${param.flags}`;
|
||||||
if ((0, _utils.isString)(param)) return `"${(0, _utils.trimStringWithEllipsis)(param, 50)}"`;
|
if ((0, _rtti.isString)(param)) return `"${(0, _stringUtils.trimStringWithEllipsis)(param, 50)}"`;
|
||||||
}
|
}
|
||||||
22
tvapp2/node_modules/playwright-core/lib/client/playwright.js
generated
vendored
@@ -4,11 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Playwright = void 0;
|
exports.Playwright = void 0;
|
||||||
var _errors = require("./errors");
|
|
||||||
var _android = require("./android");
|
var _android = require("./android");
|
||||||
|
var _browser = require("./browser");
|
||||||
var _browserType = require("./browserType");
|
var _browserType = require("./browserType");
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _electron = require("./electron");
|
var _electron = require("./electron");
|
||||||
|
var _errors = require("./errors");
|
||||||
var _fetch = require("./fetch");
|
var _fetch = require("./fetch");
|
||||||
var _selectors = require("./selectors");
|
var _selectors = require("./selectors");
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +43,11 @@ class Playwright extends _channelOwner.ChannelOwner {
|
|||||||
this.selectors = void 0;
|
this.selectors = void 0;
|
||||||
this.request = void 0;
|
this.request = void 0;
|
||||||
this.errors = void 0;
|
this.errors = void 0;
|
||||||
|
// Instrumentation.
|
||||||
|
this._defaultLaunchOptions = void 0;
|
||||||
|
this._defaultContextOptions = void 0;
|
||||||
|
this._defaultContextTimeout = void 0;
|
||||||
|
this._defaultContextNavigationTimeout = void 0;
|
||||||
this.request = new _fetch.APIRequest(this);
|
this.request = new _fetch.APIRequest(this);
|
||||||
this.chromium = _browserType.BrowserType.from(initializer.chromium);
|
this.chromium = _browserType.BrowserType.from(initializer.chromium);
|
||||||
this.chromium._playwright = this;
|
this.chromium._playwright = this;
|
||||||
@@ -76,5 +82,19 @@ class Playwright extends _channelOwner.ChannelOwner {
|
|||||||
static from(channel) {
|
static from(channel) {
|
||||||
return channel._object;
|
return channel._object;
|
||||||
}
|
}
|
||||||
|
_browserTypes() {
|
||||||
|
return [this.chromium, this.firefox, this.webkit, this._bidiChromium, this._bidiFirefox];
|
||||||
|
}
|
||||||
|
_preLaunchedBrowser() {
|
||||||
|
const browser = _browser.Browser.from(this._initializer.preLaunchedBrowser);
|
||||||
|
browser._browserType = this[browser._name];
|
||||||
|
return browser;
|
||||||
|
}
|
||||||
|
_allContexts() {
|
||||||
|
return this._browserTypes().flatMap(type => [...type._contexts]);
|
||||||
|
}
|
||||||
|
_allPages() {
|
||||||
|
return this._allContexts().flatMap(context => context.pages());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.Playwright = Playwright;
|
exports.Playwright = Playwright;
|
||||||
10
tvapp2/node_modules/playwright-core/lib/client/selectors.js
generated
vendored
@@ -4,9 +4,11 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.SelectorsOwner = exports.Selectors = void 0;
|
exports.SelectorsOwner = exports.Selectors = void 0;
|
||||||
var _clientHelper = require("./clientHelper");
|
exports.setPlatformForSelectors = setPlatformForSelectors;
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
|
var _clientHelper = require("./clientHelper");
|
||||||
var _locator = require("./locator");
|
var _locator = require("./locator");
|
||||||
|
var _platform = require("./platform");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -23,13 +25,17 @@ var _locator = require("./locator");
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
let platform = _platform.emptyPlatform;
|
||||||
|
function setPlatformForSelectors(p) {
|
||||||
|
platform = p;
|
||||||
|
}
|
||||||
class Selectors {
|
class Selectors {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._channels = new Set();
|
this._channels = new Set();
|
||||||
this._registrations = [];
|
this._registrations = [];
|
||||||
}
|
}
|
||||||
async register(name, script, options = {}) {
|
async register(name, script, options = {}) {
|
||||||
const source = await (0, _clientHelper.evaluationScript)(script, undefined, false);
|
const source = await (0, _clientHelper.evaluationScript)(platform, script, undefined, false);
|
||||||
const params = {
|
const params = {
|
||||||
...options,
|
...options,
|
||||||
name,
|
name,
|
||||||
|
|||||||
23
tvapp2/node_modules/playwright-core/lib/client/stream.js
generated
vendored
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Stream = void 0;
|
exports.Stream = void 0;
|
||||||
var _stream = require("stream");
|
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
@@ -30,25 +29,7 @@ class Stream extends _channelOwner.ChannelOwner {
|
|||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
}
|
}
|
||||||
stream() {
|
stream() {
|
||||||
return new StreamImpl(this._channel);
|
return this._platform.streamReadable(this._channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Stream = Stream;
|
exports.Stream = Stream;
|
||||||
class StreamImpl extends _stream.Readable {
|
|
||||||
constructor(channel) {
|
|
||||||
super();
|
|
||||||
this._channel = void 0;
|
|
||||||
this._channel = channel;
|
|
||||||
}
|
|
||||||
async _read() {
|
|
||||||
const result = await this._channel.read({
|
|
||||||
size: 1024 * 1024
|
|
||||||
});
|
|
||||||
if (result.binary.byteLength) this.push(result.binary);else this.push(null);
|
|
||||||
}
|
|
||||||
_destroy(error, callback) {
|
|
||||||
// Stream might be destroyed after the connection was closed.
|
|
||||||
this._channel.close().catch(e => null);
|
|
||||||
super._destroy(error, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
tvapp2/node_modules/playwright-core/lib/client/tracing.js
generated
vendored
@@ -70,15 +70,16 @@ class Tracing extends _channelOwner.ChannelOwner {
|
|||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
async _startCollectingStacks(traceName) {
|
async _startCollectingStacks(traceName) {
|
||||||
|
var _this$_connection$loc;
|
||||||
if (!this._isTracing) {
|
if (!this._isTracing) {
|
||||||
this._isTracing = true;
|
this._isTracing = true;
|
||||||
this._connection.setIsTracing(true);
|
this._connection.setIsTracing(true);
|
||||||
}
|
}
|
||||||
const result = await this._connection.localUtils()._channel.tracingStarted({
|
const result = await ((_this$_connection$loc = this._connection.localUtils()) === null || _this$_connection$loc === void 0 ? void 0 : _this$_connection$loc.tracingStarted({
|
||||||
tracesDir: this._tracesDir,
|
tracesDir: this._tracesDir,
|
||||||
traceName
|
traceName
|
||||||
});
|
}));
|
||||||
this._stacksId = result.stacksId;
|
this._stacksId = result === null || result === void 0 ? void 0 : result.stacksId;
|
||||||
}
|
}
|
||||||
async stopChunk(options = {}) {
|
async stopChunk(options = {}) {
|
||||||
await this._doStopChunk(options.path);
|
await this._doStopChunk(options.path);
|
||||||
@@ -94,17 +95,19 @@ class Tracing extends _channelOwner.ChannelOwner {
|
|||||||
await this._channel.tracingStopChunk({
|
await this._channel.tracingStopChunk({
|
||||||
mode: 'discard'
|
mode: 'discard'
|
||||||
});
|
});
|
||||||
if (this._stacksId) await this._connection.localUtils()._channel.traceDiscarded({
|
if (this._stacksId) await this._connection.localUtils().traceDiscarded({
|
||||||
stacksId: this._stacksId
|
stacksId: this._stacksId
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const localUtils = this._connection.localUtils();
|
||||||
|
if (!localUtils) throw new Error('Cannot save trace in thin clients');
|
||||||
const isLocal = !this._connection.isRemote();
|
const isLocal = !this._connection.isRemote();
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
const result = await this._channel.tracingStopChunk({
|
const result = await this._channel.tracingStopChunk({
|
||||||
mode: 'entries'
|
mode: 'entries'
|
||||||
});
|
});
|
||||||
await this._connection.localUtils()._channel.zip({
|
await localUtils.zip({
|
||||||
zipFile: filePath,
|
zipFile: filePath,
|
||||||
entries: result.entries,
|
entries: result.entries,
|
||||||
mode: 'write',
|
mode: 'write',
|
||||||
@@ -119,7 +122,7 @@ class Tracing extends _channelOwner.ChannelOwner {
|
|||||||
|
|
||||||
// The artifact may be missing if the browser closed while stopping tracing.
|
// The artifact may be missing if the browser closed while stopping tracing.
|
||||||
if (!result.artifact) {
|
if (!result.artifact) {
|
||||||
if (this._stacksId) await this._connection.localUtils()._channel.traceDiscarded({
|
if (this._stacksId) await localUtils.traceDiscarded({
|
||||||
stacksId: this._stacksId
|
stacksId: this._stacksId
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -129,7 +132,7 @@ class Tracing extends _channelOwner.ChannelOwner {
|
|||||||
const artifact = _artifact.Artifact.from(result.artifact);
|
const artifact = _artifact.Artifact.from(result.artifact);
|
||||||
await artifact.saveAs(filePath);
|
await artifact.saveAs(filePath);
|
||||||
await artifact.delete();
|
await artifact.delete();
|
||||||
await this._connection.localUtils()._channel.zip({
|
await localUtils.zip({
|
||||||
zipFile: filePath,
|
zipFile: filePath,
|
||||||
entries: [],
|
entries: [],
|
||||||
mode: 'append',
|
mode: 'append',
|
||||||
|
|||||||
4
tvapp2/node_modules/playwright-core/lib/client/video.js
generated
vendored
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Video = void 0;
|
exports.Video = void 0;
|
||||||
var _utils = require("../utils");
|
var _manualPromise = require("../utils/isomorphic/manualPromise");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -24,7 +24,7 @@ var _utils = require("../utils");
|
|||||||
class Video {
|
class Video {
|
||||||
constructor(page, connection) {
|
constructor(page, connection) {
|
||||||
this._artifact = null;
|
this._artifact = null;
|
||||||
this._artifactReadyPromise = new _utils.ManualPromise();
|
this._artifactReadyPromise = new _manualPromise.ManualPromise();
|
||||||
this._isRemote = false;
|
this._isRemote = false;
|
||||||
this._isRemote = connection.isRemote();
|
this._isRemote = connection.isRemote();
|
||||||
this._artifact = page._closedOrCrashedScope.safeRace(this._artifactReadyPromise);
|
this._artifact = page._closedOrCrashedScope.safeRace(this._artifactReadyPromise);
|
||||||
|
|||||||
11
tvapp2/node_modules/playwright-core/lib/client/waiter.js
generated
vendored
@@ -4,9 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Waiter = void 0;
|
exports.Waiter = void 0;
|
||||||
var _stackTrace = require("../utils/stackTrace");
|
|
||||||
var _errors = require("./errors");
|
var _errors = require("./errors");
|
||||||
var _utils = require("../utils");
|
var _stackTrace = require("../utils/isomorphic/stackTrace");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -33,9 +32,9 @@ class Waiter {
|
|||||||
this._waitId = void 0;
|
this._waitId = void 0;
|
||||||
this._error = void 0;
|
this._error = void 0;
|
||||||
this._savedZone = void 0;
|
this._savedZone = void 0;
|
||||||
this._waitId = (0, _utils.createGuid)();
|
this._waitId = channelOwner._platform.createGuid();
|
||||||
this._channelOwner = channelOwner;
|
this._channelOwner = channelOwner;
|
||||||
this._savedZone = _utils.zones.current().without('apiZone');
|
this._savedZone = channelOwner._platform.zones.current().pop();
|
||||||
this._channelOwner._channel.waitForEventInfo({
|
this._channelOwner._channel.waitForEventInfo({
|
||||||
info: {
|
info: {
|
||||||
waitId: this._waitId,
|
waitId: this._waitId,
|
||||||
@@ -111,8 +110,8 @@ class Waiter {
|
|||||||
phase: 'log',
|
phase: 'log',
|
||||||
message: s
|
message: s
|
||||||
}
|
}
|
||||||
}).catch(() => {});
|
});
|
||||||
}, true);
|
}, true).catch(() => {});
|
||||||
}
|
}
|
||||||
_rejectOn(promise, dispose) {
|
_rejectOn(promise, dispose) {
|
||||||
this._failures.push(promise);
|
this._failures.push(promise);
|
||||||
|
|||||||
8
tvapp2/node_modules/playwright-core/lib/client/worker.js
generated
vendored
@@ -4,11 +4,11 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.Worker = void 0;
|
exports.Worker = void 0;
|
||||||
var _events = require("./events");
|
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
var _jsHandle = require("./jsHandle");
|
|
||||||
var _utils = require("../utils");
|
|
||||||
var _errors = require("./errors");
|
var _errors = require("./errors");
|
||||||
|
var _events = require("./events");
|
||||||
|
var _jsHandle = require("./jsHandle");
|
||||||
|
var _manualPromise = require("../utils/isomorphic/manualPromise");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
*
|
*
|
||||||
@@ -35,7 +35,7 @@ class Worker extends _channelOwner.ChannelOwner {
|
|||||||
// Set for web workers.
|
// Set for web workers.
|
||||||
this._context = void 0;
|
this._context = void 0;
|
||||||
// Set for service workers.
|
// Set for service workers.
|
||||||
this._closedScope = new _utils.LongStandingScope();
|
this._closedScope = new _manualPromise.LongStandingScope();
|
||||||
this._channel.on('close', () => {
|
this._channel.on('close', () => {
|
||||||
if (this._page) this._page._workers.delete(this);
|
if (this._page) this._page._workers.delete(this);
|
||||||
if (this._context) this._context._serviceWorkers.delete(this);
|
if (this._context) this._context._serviceWorkers.delete(this);
|
||||||
|
|||||||
23
tvapp2/node_modules/playwright-core/lib/client/writableStream.js
generated
vendored
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|||||||
value: true
|
value: true
|
||||||
});
|
});
|
||||||
exports.WritableStream = void 0;
|
exports.WritableStream = void 0;
|
||||||
var _stream = require("stream");
|
|
||||||
var _channelOwner = require("./channelOwner");
|
var _channelOwner = require("./channelOwner");
|
||||||
/**
|
/**
|
||||||
* Copyright (c) Microsoft Corporation.
|
* Copyright (c) Microsoft Corporation.
|
||||||
@@ -30,25 +29,7 @@ class WritableStream extends _channelOwner.ChannelOwner {
|
|||||||
super(parent, type, guid, initializer);
|
super(parent, type, guid, initializer);
|
||||||
}
|
}
|
||||||
stream() {
|
stream() {
|
||||||
return new WritableStreamImpl(this._channel);
|
return this._platform.streamWritable(this._channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.WritableStream = WritableStream;
|
exports.WritableStream = WritableStream;
|
||||||
class WritableStreamImpl extends _stream.Writable {
|
|
||||||
constructor(channel) {
|
|
||||||
super();
|
|
||||||
this._channel = void 0;
|
|
||||||
this._channel = channel;
|
|
||||||
}
|
|
||||||
async _write(chunk, encoding, callback) {
|
|
||||||
const error = await this._channel.write({
|
|
||||||
binary: typeof chunk === 'string' ? Buffer.from(chunk) : chunk
|
|
||||||
}).catch(e => e);
|
|
||||||
callback(error || null);
|
|
||||||
}
|
|
||||||
async _final(callback) {
|
|
||||||
// Stream might be destroyed after the connection was closed.
|
|
||||||
const error = await this._channel.close().catch(e => e);
|
|
||||||
callback(error || null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
569
tvapp2/node_modules/playwright-core/lib/common/socksProxy.js
generated
vendored
@@ -1,569 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.SocksProxyHandler = exports.SocksProxy = void 0;
|
|
||||||
exports.parsePattern = parsePattern;
|
|
||||||
var _events = _interopRequireDefault(require("events"));
|
|
||||||
var _net = _interopRequireDefault(require("net"));
|
|
||||||
var _debugLogger = require("../utils/debugLogger");
|
|
||||||
var _happyEyeballs = require("../utils/happy-eyeballs");
|
|
||||||
var _utils = require("../utils");
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
// https://tools.ietf.org/html/rfc1928
|
|
||||||
var SocksAuth = /*#__PURE__*/function (SocksAuth) {
|
|
||||||
SocksAuth[SocksAuth["NO_AUTHENTICATION_REQUIRED"] = 0] = "NO_AUTHENTICATION_REQUIRED";
|
|
||||||
SocksAuth[SocksAuth["GSSAPI"] = 1] = "GSSAPI";
|
|
||||||
SocksAuth[SocksAuth["USERNAME_PASSWORD"] = 2] = "USERNAME_PASSWORD";
|
|
||||||
SocksAuth[SocksAuth["NO_ACCEPTABLE_METHODS"] = 255] = "NO_ACCEPTABLE_METHODS";
|
|
||||||
return SocksAuth;
|
|
||||||
}(SocksAuth || {});
|
|
||||||
var SocksAddressType = /*#__PURE__*/function (SocksAddressType) {
|
|
||||||
SocksAddressType[SocksAddressType["IPv4"] = 1] = "IPv4";
|
|
||||||
SocksAddressType[SocksAddressType["FqName"] = 3] = "FqName";
|
|
||||||
SocksAddressType[SocksAddressType["IPv6"] = 4] = "IPv6";
|
|
||||||
return SocksAddressType;
|
|
||||||
}(SocksAddressType || {});
|
|
||||||
var SocksCommand = /*#__PURE__*/function (SocksCommand) {
|
|
||||||
SocksCommand[SocksCommand["CONNECT"] = 1] = "CONNECT";
|
|
||||||
SocksCommand[SocksCommand["BIND"] = 2] = "BIND";
|
|
||||||
SocksCommand[SocksCommand["UDP_ASSOCIATE"] = 3] = "UDP_ASSOCIATE";
|
|
||||||
return SocksCommand;
|
|
||||||
}(SocksCommand || {});
|
|
||||||
var SocksReply = /*#__PURE__*/function (SocksReply) {
|
|
||||||
SocksReply[SocksReply["Succeeded"] = 0] = "Succeeded";
|
|
||||||
SocksReply[SocksReply["GeneralServerFailure"] = 1] = "GeneralServerFailure";
|
|
||||||
SocksReply[SocksReply["NotAllowedByRuleSet"] = 2] = "NotAllowedByRuleSet";
|
|
||||||
SocksReply[SocksReply["NetworkUnreachable"] = 3] = "NetworkUnreachable";
|
|
||||||
SocksReply[SocksReply["HostUnreachable"] = 4] = "HostUnreachable";
|
|
||||||
SocksReply[SocksReply["ConnectionRefused"] = 5] = "ConnectionRefused";
|
|
||||||
SocksReply[SocksReply["TtlExpired"] = 6] = "TtlExpired";
|
|
||||||
SocksReply[SocksReply["CommandNotSupported"] = 7] = "CommandNotSupported";
|
|
||||||
SocksReply[SocksReply["AddressTypeNotSupported"] = 8] = "AddressTypeNotSupported";
|
|
||||||
return SocksReply;
|
|
||||||
}(SocksReply || {});
|
|
||||||
class SocksConnection {
|
|
||||||
constructor(uid, socket, client) {
|
|
||||||
this._buffer = Buffer.from([]);
|
|
||||||
this._offset = 0;
|
|
||||||
this._fence = 0;
|
|
||||||
this._fenceCallback = void 0;
|
|
||||||
this._socket = void 0;
|
|
||||||
this._boundOnData = void 0;
|
|
||||||
this._uid = void 0;
|
|
||||||
this._client = void 0;
|
|
||||||
this._uid = uid;
|
|
||||||
this._socket = socket;
|
|
||||||
this._client = client;
|
|
||||||
this._boundOnData = this._onData.bind(this);
|
|
||||||
socket.on('data', this._boundOnData);
|
|
||||||
socket.on('close', () => this._onClose());
|
|
||||||
socket.on('end', () => this._onClose());
|
|
||||||
socket.on('error', () => this._onClose());
|
|
||||||
this._run().catch(() => this._socket.end());
|
|
||||||
}
|
|
||||||
async _run() {
|
|
||||||
(0, _utils.assert)(await this._authenticate());
|
|
||||||
const {
|
|
||||||
command,
|
|
||||||
host,
|
|
||||||
port
|
|
||||||
} = await this._parseRequest();
|
|
||||||
if (command !== SocksCommand.CONNECT) {
|
|
||||||
this._writeBytes(Buffer.from([0x05, SocksReply.CommandNotSupported, 0x00,
|
|
||||||
// RSV
|
|
||||||
0x01,
|
|
||||||
// IPv4
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
// Address
|
|
||||||
0x00, 0x00 // Port
|
|
||||||
]));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._socket.off('data', this._boundOnData);
|
|
||||||
this._client.onSocketRequested({
|
|
||||||
uid: this._uid,
|
|
||||||
host,
|
|
||||||
port
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async _authenticate() {
|
|
||||||
// Request:
|
|
||||||
// +----+----------+----------+
|
|
||||||
// |VER | NMETHODS | METHODS |
|
|
||||||
// +----+----------+----------+
|
|
||||||
// | 1 | 1 | 1 to 255 |
|
|
||||||
// +----+----------+----------+
|
|
||||||
|
|
||||||
// Response:
|
|
||||||
// +----+--------+
|
|
||||||
// |VER | METHOD |
|
|
||||||
// +----+--------+
|
|
||||||
// | 1 | 1 |
|
|
||||||
// +----+--------+
|
|
||||||
|
|
||||||
const version = await this._readByte();
|
|
||||||
(0, _utils.assert)(version === 0x05, 'The VER field must be set to x05 for this version of the protocol, was ' + version);
|
|
||||||
const nMethods = await this._readByte();
|
|
||||||
(0, _utils.assert)(nMethods, 'No authentication methods specified');
|
|
||||||
const methods = await this._readBytes(nMethods);
|
|
||||||
for (const method of methods) {
|
|
||||||
if (method === 0) {
|
|
||||||
this._writeBytes(Buffer.from([version, method]));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._writeBytes(Buffer.from([version, SocksAuth.NO_ACCEPTABLE_METHODS]));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
async _parseRequest() {
|
|
||||||
// Request.
|
|
||||||
// +----+-----+-------+------+----------+----------+
|
|
||||||
// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
|
|
||||||
// +----+-----+-------+------+----------+----------+
|
|
||||||
// | 1 | 1 | X'00' | 1 | Variable | 2 |
|
|
||||||
// +----+-----+-------+------+----------+----------+
|
|
||||||
|
|
||||||
// Response.
|
|
||||||
// +----+-----+-------+------+----------+----------+
|
|
||||||
// |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
|
|
||||||
// +----+-----+-------+------+----------+----------+
|
|
||||||
// | 1 | 1 | X'00' | 1 | Variable | 2 |
|
|
||||||
// +----+-----+-------+------+----------+----------+
|
|
||||||
|
|
||||||
const version = await this._readByte();
|
|
||||||
(0, _utils.assert)(version === 0x05, 'The VER field must be set to x05 for this version of the protocol, was ' + version);
|
|
||||||
const command = await this._readByte();
|
|
||||||
await this._readByte(); // skip reserved.
|
|
||||||
const addressType = await this._readByte();
|
|
||||||
let host = '';
|
|
||||||
switch (addressType) {
|
|
||||||
case SocksAddressType.IPv4:
|
|
||||||
host = (await this._readBytes(4)).join('.');
|
|
||||||
break;
|
|
||||||
case SocksAddressType.FqName:
|
|
||||||
const length = await this._readByte();
|
|
||||||
host = (await this._readBytes(length)).toString();
|
|
||||||
break;
|
|
||||||
case SocksAddressType.IPv6:
|
|
||||||
const bytes = await this._readBytes(16);
|
|
||||||
const tokens = [];
|
|
||||||
for (let i = 0; i < 8; ++i) tokens.push(bytes.readUInt16BE(i * 2).toString(16));
|
|
||||||
host = tokens.join(':');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const port = (await this._readBytes(2)).readUInt16BE(0);
|
|
||||||
this._buffer = Buffer.from([]);
|
|
||||||
this._offset = 0;
|
|
||||||
this._fence = 0;
|
|
||||||
return {
|
|
||||||
command,
|
|
||||||
host,
|
|
||||||
port
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async _readByte() {
|
|
||||||
const buffer = await this._readBytes(1);
|
|
||||||
return buffer[0];
|
|
||||||
}
|
|
||||||
async _readBytes(length) {
|
|
||||||
this._fence = this._offset + length;
|
|
||||||
if (!this._buffer || this._buffer.length < this._fence) await new Promise(f => this._fenceCallback = f);
|
|
||||||
this._offset += length;
|
|
||||||
return this._buffer.slice(this._offset - length, this._offset);
|
|
||||||
}
|
|
||||||
_writeBytes(buffer) {
|
|
||||||
if (this._socket.writable) this._socket.write(buffer);
|
|
||||||
}
|
|
||||||
_onClose() {
|
|
||||||
this._client.onSocketClosed({
|
|
||||||
uid: this._uid
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_onData(buffer) {
|
|
||||||
this._buffer = Buffer.concat([this._buffer, buffer]);
|
|
||||||
if (this._fenceCallback && this._buffer.length >= this._fence) {
|
|
||||||
const callback = this._fenceCallback;
|
|
||||||
this._fenceCallback = undefined;
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
socketConnected(host, port) {
|
|
||||||
this._writeBytes(Buffer.from([0x05, SocksReply.Succeeded, 0x00,
|
|
||||||
// RSV
|
|
||||||
...ipToSocksAddress(host),
|
|
||||||
// ATYP, Address
|
|
||||||
port >> 8, port & 0xFF // Port
|
|
||||||
]));
|
|
||||||
this._socket.on('data', data => this._client.onSocketData({
|
|
||||||
uid: this._uid,
|
|
||||||
data
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
socketFailed(errorCode) {
|
|
||||||
const buffer = Buffer.from([0x05, 0, 0x00,
|
|
||||||
// RSV
|
|
||||||
...ipToSocksAddress('0.0.0.0'),
|
|
||||||
// ATYP, Address
|
|
||||||
0, 0 // Port
|
|
||||||
]);
|
|
||||||
switch (errorCode) {
|
|
||||||
case 'ENOENT':
|
|
||||||
case 'ENOTFOUND':
|
|
||||||
case 'ETIMEDOUT':
|
|
||||||
case 'EHOSTUNREACH':
|
|
||||||
buffer[1] = SocksReply.HostUnreachable;
|
|
||||||
break;
|
|
||||||
case 'ENETUNREACH':
|
|
||||||
buffer[1] = SocksReply.NetworkUnreachable;
|
|
||||||
break;
|
|
||||||
case 'ECONNREFUSED':
|
|
||||||
buffer[1] = SocksReply.ConnectionRefused;
|
|
||||||
break;
|
|
||||||
case 'ERULESET':
|
|
||||||
buffer[1] = SocksReply.NotAllowedByRuleSet;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this._writeBytes(buffer);
|
|
||||||
this._socket.end();
|
|
||||||
}
|
|
||||||
sendData(data) {
|
|
||||||
this._socket.write(data);
|
|
||||||
}
|
|
||||||
end() {
|
|
||||||
this._socket.end();
|
|
||||||
}
|
|
||||||
error(error) {
|
|
||||||
this._socket.destroy(new Error(error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function hexToNumber(hex) {
|
|
||||||
// Note: parseInt has a few issues including ignoring trailing characters and allowing leading 0x.
|
|
||||||
return [...hex].reduce((value, digit) => {
|
|
||||||
const code = digit.charCodeAt(0);
|
|
||||||
if (code >= 48 && code <= 57)
|
|
||||||
// 0..9
|
|
||||||
return value + code;
|
|
||||||
if (code >= 97 && code <= 102)
|
|
||||||
// a..f
|
|
||||||
return value + (code - 97) + 10;
|
|
||||||
if (code >= 65 && code <= 70)
|
|
||||||
// A..F
|
|
||||||
return value + (code - 65) + 10;
|
|
||||||
throw new Error('Invalid IPv6 token ' + hex);
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
function ipToSocksAddress(address) {
|
|
||||||
if (_net.default.isIPv4(address)) {
|
|
||||||
return [0x01,
|
|
||||||
// IPv4
|
|
||||||
...address.split('.', 4).map(t => +t & 0xFF) // Address
|
|
||||||
];
|
|
||||||
}
|
|
||||||
if (_net.default.isIPv6(address)) {
|
|
||||||
const result = [0x04]; // IPv6
|
|
||||||
const tokens = address.split(':', 8);
|
|
||||||
while (tokens.length < 8) tokens.unshift('');
|
|
||||||
for (const token of tokens) {
|
|
||||||
const value = hexToNumber(token);
|
|
||||||
result.push(value >> 8 & 0xFF, value & 0xFF); // Big-endian
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
throw new Error('Only IPv4 and IPv6 addresses are supported');
|
|
||||||
}
|
|
||||||
function starMatchToRegex(pattern) {
|
|
||||||
const source = pattern.split('*').map(s => {
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
|
||||||
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
||||||
}).join('.*');
|
|
||||||
return new RegExp('^' + source + '$');
|
|
||||||
}
|
|
||||||
|
|
||||||
// This follows "Proxy bypass rules" syntax without implicit and negative rules.
|
|
||||||
// https://source.chromium.org/chromium/chromium/src/+/main:net/docs/proxy.md;l=331
|
|
||||||
function parsePattern(pattern) {
|
|
||||||
if (!pattern) return () => false;
|
|
||||||
const matchers = pattern.split(',').map(token => {
|
|
||||||
const match = token.match(/^(.*?)(?::(\d+))?$/);
|
|
||||||
if (!match) throw new Error(`Unsupported token "${token}" in pattern "${pattern}"`);
|
|
||||||
const tokenPort = match[2] ? +match[2] : undefined;
|
|
||||||
const portMatches = port => tokenPort === undefined || tokenPort === port;
|
|
||||||
let tokenHost = match[1];
|
|
||||||
if (tokenHost === '<loopback>') {
|
|
||||||
return (host, port) => {
|
|
||||||
if (!portMatches(port)) return false;
|
|
||||||
return host === 'localhost' || host.endsWith('.localhost') || host === '127.0.0.1' || host === '[::1]';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (tokenHost === '*') return (host, port) => portMatches(port);
|
|
||||||
if (_net.default.isIPv4(tokenHost) || _net.default.isIPv6(tokenHost)) return (host, port) => host === tokenHost && portMatches(port);
|
|
||||||
if (tokenHost[0] === '.') tokenHost = '*' + tokenHost;
|
|
||||||
const tokenRegex = starMatchToRegex(tokenHost);
|
|
||||||
return (host, port) => {
|
|
||||||
if (!portMatches(port)) return false;
|
|
||||||
if (_net.default.isIPv4(host) || _net.default.isIPv6(host)) return false;
|
|
||||||
return !!host.match(tokenRegex);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return (host, port) => matchers.some(matcher => matcher(host, port));
|
|
||||||
}
|
|
||||||
class SocksProxy extends _events.default {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this._server = void 0;
|
|
||||||
this._connections = new Map();
|
|
||||||
this._sockets = new Set();
|
|
||||||
this._closed = false;
|
|
||||||
this._port = void 0;
|
|
||||||
this._patternMatcher = () => false;
|
|
||||||
this._directSockets = new Map();
|
|
||||||
this._server = new _net.default.Server(socket => {
|
|
||||||
const uid = (0, _utils.createGuid)();
|
|
||||||
const connection = new SocksConnection(uid, socket, this);
|
|
||||||
this._connections.set(uid, connection);
|
|
||||||
});
|
|
||||||
this._server.on('connection', socket => {
|
|
||||||
if (this._closed) {
|
|
||||||
socket.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._sockets.add(socket);
|
|
||||||
socket.once('close', () => this._sockets.delete(socket));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setPattern(pattern) {
|
|
||||||
try {
|
|
||||||
this._patternMatcher = parsePattern(pattern);
|
|
||||||
} catch (e) {
|
|
||||||
this._patternMatcher = () => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async _handleDirect(request) {
|
|
||||||
try {
|
|
||||||
var _this$_connections$ge4;
|
|
||||||
const socket = await (0, _happyEyeballs.createSocket)(request.host, request.port);
|
|
||||||
socket.on('data', data => {
|
|
||||||
var _this$_connections$ge;
|
|
||||||
return (_this$_connections$ge = this._connections.get(request.uid)) === null || _this$_connections$ge === void 0 ? void 0 : _this$_connections$ge.sendData(data);
|
|
||||||
});
|
|
||||||
socket.on('error', error => {
|
|
||||||
var _this$_connections$ge2;
|
|
||||||
(_this$_connections$ge2 = this._connections.get(request.uid)) === null || _this$_connections$ge2 === void 0 || _this$_connections$ge2.error(error.message);
|
|
||||||
this._directSockets.delete(request.uid);
|
|
||||||
});
|
|
||||||
socket.on('end', () => {
|
|
||||||
var _this$_connections$ge3;
|
|
||||||
(_this$_connections$ge3 = this._connections.get(request.uid)) === null || _this$_connections$ge3 === void 0 || _this$_connections$ge3.end();
|
|
||||||
this._directSockets.delete(request.uid);
|
|
||||||
});
|
|
||||||
const localAddress = socket.localAddress;
|
|
||||||
const localPort = socket.localPort;
|
|
||||||
this._directSockets.set(request.uid, socket);
|
|
||||||
(_this$_connections$ge4 = this._connections.get(request.uid)) === null || _this$_connections$ge4 === void 0 || _this$_connections$ge4.socketConnected(localAddress, localPort);
|
|
||||||
} catch (error) {
|
|
||||||
var _this$_connections$ge5;
|
|
||||||
(_this$_connections$ge5 = this._connections.get(request.uid)) === null || _this$_connections$ge5 === void 0 || _this$_connections$ge5.socketFailed(error.code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
port() {
|
|
||||||
return this._port;
|
|
||||||
}
|
|
||||||
async listen(port, hostname) {
|
|
||||||
return new Promise(f => {
|
|
||||||
this._server.listen(port, hostname, () => {
|
|
||||||
const port = this._server.address().port;
|
|
||||||
this._port = port;
|
|
||||||
f(port);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async close() {
|
|
||||||
if (this._closed) return;
|
|
||||||
this._closed = true;
|
|
||||||
for (const socket of this._sockets) socket.destroy();
|
|
||||||
this._sockets.clear();
|
|
||||||
await new Promise(f => this._server.close(f));
|
|
||||||
}
|
|
||||||
onSocketRequested(payload) {
|
|
||||||
if (!this._patternMatcher(payload.host, payload.port)) {
|
|
||||||
this._handleDirect(payload);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.emit(SocksProxy.Events.SocksRequested, payload);
|
|
||||||
}
|
|
||||||
onSocketData(payload) {
|
|
||||||
const direct = this._directSockets.get(payload.uid);
|
|
||||||
if (direct) {
|
|
||||||
direct.write(payload.data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.emit(SocksProxy.Events.SocksData, payload);
|
|
||||||
}
|
|
||||||
onSocketClosed(payload) {
|
|
||||||
const direct = this._directSockets.get(payload.uid);
|
|
||||||
if (direct) {
|
|
||||||
direct.destroy();
|
|
||||||
this._directSockets.delete(payload.uid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.emit(SocksProxy.Events.SocksClosed, payload);
|
|
||||||
}
|
|
||||||
socketConnected({
|
|
||||||
uid,
|
|
||||||
host,
|
|
||||||
port
|
|
||||||
}) {
|
|
||||||
var _this$_connections$ge6;
|
|
||||||
(_this$_connections$ge6 = this._connections.get(uid)) === null || _this$_connections$ge6 === void 0 || _this$_connections$ge6.socketConnected(host, port);
|
|
||||||
}
|
|
||||||
socketFailed({
|
|
||||||
uid,
|
|
||||||
errorCode
|
|
||||||
}) {
|
|
||||||
var _this$_connections$ge7;
|
|
||||||
(_this$_connections$ge7 = this._connections.get(uid)) === null || _this$_connections$ge7 === void 0 || _this$_connections$ge7.socketFailed(errorCode);
|
|
||||||
}
|
|
||||||
sendSocketData({
|
|
||||||
uid,
|
|
||||||
data
|
|
||||||
}) {
|
|
||||||
var _this$_connections$ge8;
|
|
||||||
(_this$_connections$ge8 = this._connections.get(uid)) === null || _this$_connections$ge8 === void 0 || _this$_connections$ge8.sendData(data);
|
|
||||||
}
|
|
||||||
sendSocketEnd({
|
|
||||||
uid
|
|
||||||
}) {
|
|
||||||
var _this$_connections$ge9;
|
|
||||||
(_this$_connections$ge9 = this._connections.get(uid)) === null || _this$_connections$ge9 === void 0 || _this$_connections$ge9.end();
|
|
||||||
}
|
|
||||||
sendSocketError({
|
|
||||||
uid,
|
|
||||||
error
|
|
||||||
}) {
|
|
||||||
var _this$_connections$ge10;
|
|
||||||
(_this$_connections$ge10 = this._connections.get(uid)) === null || _this$_connections$ge10 === void 0 || _this$_connections$ge10.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.SocksProxy = SocksProxy;
|
|
||||||
SocksProxy.Events = {
|
|
||||||
SocksRequested: 'socksRequested',
|
|
||||||
SocksData: 'socksData',
|
|
||||||
SocksClosed: 'socksClosed'
|
|
||||||
};
|
|
||||||
class SocksProxyHandler extends _events.default {
|
|
||||||
constructor(pattern, redirectPortForTest) {
|
|
||||||
super();
|
|
||||||
this._sockets = new Map();
|
|
||||||
this._patternMatcher = () => false;
|
|
||||||
this._redirectPortForTest = void 0;
|
|
||||||
this._patternMatcher = parsePattern(pattern);
|
|
||||||
this._redirectPortForTest = redirectPortForTest;
|
|
||||||
}
|
|
||||||
cleanup() {
|
|
||||||
for (const uid of this._sockets.keys()) this.socketClosed({
|
|
||||||
uid
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async socketRequested({
|
|
||||||
uid,
|
|
||||||
host,
|
|
||||||
port
|
|
||||||
}) {
|
|
||||||
_debugLogger.debugLogger.log('socks', `[${uid}] => request ${host}:${port}`);
|
|
||||||
if (!this._patternMatcher(host, port)) {
|
|
||||||
const payload = {
|
|
||||||
uid,
|
|
||||||
errorCode: 'ERULESET'
|
|
||||||
};
|
|
||||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= pattern error ${payload.errorCode}`);
|
|
||||||
this.emit(SocksProxyHandler.Events.SocksFailed, payload);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (host === 'local.playwright') host = 'localhost';
|
|
||||||
try {
|
|
||||||
if (this._redirectPortForTest) port = this._redirectPortForTest;
|
|
||||||
const socket = await (0, _happyEyeballs.createSocket)(host, port);
|
|
||||||
socket.on('data', data => {
|
|
||||||
const payload = {
|
|
||||||
uid,
|
|
||||||
data
|
|
||||||
};
|
|
||||||
this.emit(SocksProxyHandler.Events.SocksData, payload);
|
|
||||||
});
|
|
||||||
socket.on('error', error => {
|
|
||||||
const payload = {
|
|
||||||
uid,
|
|
||||||
error: error.message
|
|
||||||
};
|
|
||||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= network socket error ${payload.error}`);
|
|
||||||
this.emit(SocksProxyHandler.Events.SocksError, payload);
|
|
||||||
this._sockets.delete(uid);
|
|
||||||
});
|
|
||||||
socket.on('end', () => {
|
|
||||||
const payload = {
|
|
||||||
uid
|
|
||||||
};
|
|
||||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= network socket closed`);
|
|
||||||
this.emit(SocksProxyHandler.Events.SocksEnd, payload);
|
|
||||||
this._sockets.delete(uid);
|
|
||||||
});
|
|
||||||
const localAddress = socket.localAddress;
|
|
||||||
const localPort = socket.localPort;
|
|
||||||
this._sockets.set(uid, socket);
|
|
||||||
const payload = {
|
|
||||||
uid,
|
|
||||||
host: localAddress,
|
|
||||||
port: localPort
|
|
||||||
};
|
|
||||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= connected to network ${payload.host}:${payload.port}`);
|
|
||||||
this.emit(SocksProxyHandler.Events.SocksConnected, payload);
|
|
||||||
} catch (error) {
|
|
||||||
const payload = {
|
|
||||||
uid,
|
|
||||||
errorCode: error.code
|
|
||||||
};
|
|
||||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= connect error ${payload.errorCode}`);
|
|
||||||
this.emit(SocksProxyHandler.Events.SocksFailed, payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sendSocketData({
|
|
||||||
uid,
|
|
||||||
data
|
|
||||||
}) {
|
|
||||||
var _this$_sockets$get;
|
|
||||||
(_this$_sockets$get = this._sockets.get(uid)) === null || _this$_sockets$get === void 0 || _this$_sockets$get.write(data);
|
|
||||||
}
|
|
||||||
socketClosed({
|
|
||||||
uid
|
|
||||||
}) {
|
|
||||||
var _this$_sockets$get2;
|
|
||||||
_debugLogger.debugLogger.log('socks', `[${uid}] <= browser socket closed`);
|
|
||||||
(_this$_sockets$get2 = this._sockets.get(uid)) === null || _this$_sockets$get2 === void 0 || _this$_sockets$get2.destroy();
|
|
||||||
this._sockets.delete(uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.SocksProxyHandler = SocksProxyHandler;
|
|
||||||
SocksProxyHandler.Events = {
|
|
||||||
SocksConnected: 'socksConnected',
|
|
||||||
SocksData: 'socksData',
|
|
||||||
SocksError: 'socksError',
|
|
||||||
SocksFailed: 'socksFailed',
|
|
||||||
SocksEnd: 'socksEnd'
|
|
||||||
};
|
|
||||||
73
tvapp2/node_modules/playwright-core/lib/common/timeoutSettings.js
generated
vendored
@@ -1,73 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.TimeoutSettings = exports.DEFAULT_TIMEOUT = exports.DEFAULT_LAUNCH_TIMEOUT = void 0;
|
|
||||||
var _utils = require("../utils");
|
|
||||||
/**
|
|
||||||
* 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 DEFAULT_TIMEOUT = exports.DEFAULT_TIMEOUT = 30000;
|
|
||||||
const DEFAULT_LAUNCH_TIMEOUT = exports.DEFAULT_LAUNCH_TIMEOUT = 3 * 60 * 1000; // 3 minutes
|
|
||||||
|
|
||||||
class TimeoutSettings {
|
|
||||||
constructor(parent) {
|
|
||||||
this._parent = void 0;
|
|
||||||
this._defaultTimeout = void 0;
|
|
||||||
this._defaultNavigationTimeout = void 0;
|
|
||||||
this._parent = parent;
|
|
||||||
}
|
|
||||||
setDefaultTimeout(timeout) {
|
|
||||||
this._defaultTimeout = timeout;
|
|
||||||
}
|
|
||||||
setDefaultNavigationTimeout(timeout) {
|
|
||||||
this._defaultNavigationTimeout = timeout;
|
|
||||||
}
|
|
||||||
defaultNavigationTimeout() {
|
|
||||||
return this._defaultNavigationTimeout;
|
|
||||||
}
|
|
||||||
defaultTimeout() {
|
|
||||||
return this._defaultTimeout;
|
|
||||||
}
|
|
||||||
navigationTimeout(options) {
|
|
||||||
if (typeof options.timeout === 'number') return options.timeout;
|
|
||||||
if (this._defaultNavigationTimeout !== undefined) return this._defaultNavigationTimeout;
|
|
||||||
if ((0, _utils.debugMode)()) return 0;
|
|
||||||
if (this._defaultTimeout !== undefined) return this._defaultTimeout;
|
|
||||||
if (this._parent) return this._parent.navigationTimeout(options);
|
|
||||||
return DEFAULT_TIMEOUT;
|
|
||||||
}
|
|
||||||
timeout(options) {
|
|
||||||
if (typeof options.timeout === 'number') return options.timeout;
|
|
||||||
if ((0, _utils.debugMode)()) return 0;
|
|
||||||
if (this._defaultTimeout !== undefined) return this._defaultTimeout;
|
|
||||||
if (this._parent) return this._parent.timeout(options);
|
|
||||||
return DEFAULT_TIMEOUT;
|
|
||||||
}
|
|
||||||
static timeout(options) {
|
|
||||||
if (typeof options.timeout === 'number') return options.timeout;
|
|
||||||
if ((0, _utils.debugMode)()) return 0;
|
|
||||||
return DEFAULT_TIMEOUT;
|
|
||||||
}
|
|
||||||
static launchTimeout(options) {
|
|
||||||
if (typeof options.timeout === 'number') return options.timeout;
|
|
||||||
if ((0, _utils.debugMode)()) return 0;
|
|
||||||
return DEFAULT_LAUNCH_TIMEOUT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.TimeoutSettings = TimeoutSettings;
|
|
||||||
5
tvapp2/node_modules/playwright-core/lib/common/types.js
generated
vendored
@@ -1,5 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
2
tvapp2/node_modules/playwright-core/lib/generated/consoleApiSource.js
generated
vendored
2
tvapp2/node_modules/playwright-core/lib/generated/injectedScriptSource.js
generated
vendored
98
tvapp2/node_modules/playwright-core/lib/image_tools/colorUtils.js
generated
vendored
@@ -1,98 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.blendWithWhite = blendWithWhite;
|
|
||||||
exports.colorDeltaE94 = colorDeltaE94;
|
|
||||||
exports.rgb2gray = rgb2gray;
|
|
||||||
exports.srgb2xyz = srgb2xyz;
|
|
||||||
exports.xyz2lab = xyz2lab;
|
|
||||||
/**
|
|
||||||
* 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 blendWithWhite(c, a) {
|
|
||||||
return 255 + (c - 255) * a;
|
|
||||||
}
|
|
||||||
function rgb2gray(r, g, b) {
|
|
||||||
// NOTE: this is the exact integer formula from SSIM.js.
|
|
||||||
// See https://github.com/obartra/ssim/blob/ca8e3c6a6ff5f4f2e232239e0c3d91806f3c97d5/src/matlab/rgb2gray.ts#L56
|
|
||||||
return 77 * r + 150 * g + 29 * b + 128 >> 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perceived color difference defined by CIE94.
|
|
||||||
// See https://en.wikipedia.org/wiki/Color_difference#CIE94
|
|
||||||
//
|
|
||||||
// The result of 1.0 is a "just-noticeable difference".
|
|
||||||
//
|
|
||||||
// Other results interpretation (taken from http://zschuessler.github.io/DeltaE/learn/):
|
|
||||||
// < 1.0 Not perceptible by human eyes.
|
|
||||||
// 1-2 Perceptible through close observation.
|
|
||||||
// 2-10 Perceptible at a glance.
|
|
||||||
// 11-49 Colors are more similar than opposite
|
|
||||||
// 100 Colors are exact opposite
|
|
||||||
function colorDeltaE94(rgb1, rgb2) {
|
|
||||||
const [l1, a1, b1] = xyz2lab(srgb2xyz(rgb1));
|
|
||||||
const [l2, a2, b2] = xyz2lab(srgb2xyz(rgb2));
|
|
||||||
const deltaL = l1 - l2;
|
|
||||||
const deltaA = a1 - a2;
|
|
||||||
const deltaB = b1 - b2;
|
|
||||||
const c1 = Math.sqrt(a1 ** 2 + b1 ** 2);
|
|
||||||
const c2 = Math.sqrt(a2 ** 2 + b2 ** 2);
|
|
||||||
const deltaC = c1 - c2;
|
|
||||||
let deltaH = deltaA ** 2 + deltaB ** 2 - deltaC ** 2;
|
|
||||||
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
||||||
// The k1, k2, kL, kC, kH values for "graphic arts" applications.
|
|
||||||
// See https://en.wikipedia.org/wiki/Color_difference#CIE94
|
|
||||||
const k1 = 0.045;
|
|
||||||
const k2 = 0.015;
|
|
||||||
const kL = 1;
|
|
||||||
const kC = 1;
|
|
||||||
const kH = 1;
|
|
||||||
const sC = 1.0 + k1 * c1;
|
|
||||||
const sH = 1.0 + k2 * c1;
|
|
||||||
const sL = 1;
|
|
||||||
return Math.sqrt((deltaL / sL / kL) ** 2 + (deltaC / sC / kC) ** 2 + (deltaH / sH / kH) ** 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sRGB -> 1-normalized XYZ (i.e. Y ∈ [0, 1]) with D65 illuminant
|
|
||||||
// See https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ
|
|
||||||
function srgb2xyz(rgb) {
|
|
||||||
let r = rgb[0] / 255;
|
|
||||||
let g = rgb[1] / 255;
|
|
||||||
let b = rgb[2] / 255;
|
|
||||||
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
||||||
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
||||||
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
||||||
return [r * 0.4124 + g * 0.3576 + b * 0.1805, r * 0.2126 + g * 0.7152 + b * 0.0722, r * 0.0193 + g * 0.1192 + b * 0.9505];
|
|
||||||
}
|
|
||||||
const sigma_pow2 = 6 * 6 / 29 / 29;
|
|
||||||
const sigma_pow3 = 6 * 6 * 6 / 29 / 29 / 29;
|
|
||||||
|
|
||||||
// 1-normalized CIE XYZ with D65 to L*a*b*
|
|
||||||
// See https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB
|
|
||||||
function xyz2lab(xyz) {
|
|
||||||
const x = xyz[0] / 0.950489;
|
|
||||||
const y = xyz[1];
|
|
||||||
const z = xyz[2] / 1.088840;
|
|
||||||
const fx = x > sigma_pow3 ? x ** (1 / 3) : x / 3 / sigma_pow2 + 4 / 29;
|
|
||||||
const fy = y > sigma_pow3 ? y ** (1 / 3) : y / 3 / sigma_pow2 + 4 / 29;
|
|
||||||
const fz = z > sigma_pow3 ? z ** (1 / 3) : z / 3 / sigma_pow2 + 4 / 29;
|
|
||||||
const l = 116 * fy - 16;
|
|
||||||
const a = 500 * (fx - fy);
|
|
||||||
const b = 200 * (fy - fz);
|
|
||||||
return [l, a, b];
|
|
||||||
}
|
|
||||||
108
tvapp2/node_modules/playwright-core/lib/image_tools/compare.js
generated
vendored
@@ -1,108 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.compare = compare;
|
|
||||||
var _colorUtils = require("./colorUtils");
|
|
||||||
var _imageChannel = require("./imageChannel");
|
|
||||||
var _stats = require("./stats");
|
|
||||||
/**
|
|
||||||
* 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 SSIM_WINDOW_RADIUS = 15;
|
|
||||||
const VARIANCE_WINDOW_RADIUS = 1;
|
|
||||||
function drawPixel(width, data, x, y, r, g, b) {
|
|
||||||
const idx = (y * width + x) * 4;
|
|
||||||
data[idx + 0] = r;
|
|
||||||
data[idx + 1] = g;
|
|
||||||
data[idx + 2] = b;
|
|
||||||
data[idx + 3] = 255;
|
|
||||||
}
|
|
||||||
function compare(actual, expected, diff, width, height, options = {}) {
|
|
||||||
const {
|
|
||||||
maxColorDeltaE94 = 1.0
|
|
||||||
} = options;
|
|
||||||
const paddingSize = Math.max(VARIANCE_WINDOW_RADIUS, SSIM_WINDOW_RADIUS);
|
|
||||||
const paddingColorEven = [255, 0, 255];
|
|
||||||
const paddingColorOdd = [0, 255, 0];
|
|
||||||
const [r1, g1, b1] = _imageChannel.ImageChannel.intoRGB(width, height, expected, {
|
|
||||||
paddingSize,
|
|
||||||
paddingColorEven,
|
|
||||||
paddingColorOdd
|
|
||||||
});
|
|
||||||
const [r2, g2, b2] = _imageChannel.ImageChannel.intoRGB(width, height, actual, {
|
|
||||||
paddingSize,
|
|
||||||
paddingColorEven,
|
|
||||||
paddingColorOdd
|
|
||||||
});
|
|
||||||
const noop = (x, y) => {};
|
|
||||||
const drawRedPixel = diff ? (x, y) => drawPixel(width, diff, x - paddingSize, y - paddingSize, 255, 0, 0) : noop;
|
|
||||||
const drawYellowPixel = diff ? (x, y) => drawPixel(width, diff, x - paddingSize, y - paddingSize, 255, 255, 0) : noop;
|
|
||||||
const drawGrayPixel = diff ? (x, y) => {
|
|
||||||
const gray = (0, _colorUtils.rgb2gray)(r1.get(x, y), g1.get(x, y), b1.get(x, y));
|
|
||||||
const value = (0, _colorUtils.blendWithWhite)(gray, 0.1);
|
|
||||||
drawPixel(width, diff, x - paddingSize, y - paddingSize, value, value, value);
|
|
||||||
} : noop;
|
|
||||||
let fastR, fastG, fastB;
|
|
||||||
let diffCount = 0;
|
|
||||||
for (let y = paddingSize; y < r1.height - paddingSize; ++y) {
|
|
||||||
for (let x = paddingSize; x < r1.width - paddingSize; ++x) {
|
|
||||||
// Fast-path: equal pixels.
|
|
||||||
if (r1.get(x, y) === r2.get(x, y) && g1.get(x, y) === g2.get(x, y) && b1.get(x, y) === b2.get(x, y)) {
|
|
||||||
drawGrayPixel(x, y);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare pixel colors using the dE94 color difference formulae.
|
|
||||||
// The dE94 is normalized so that the value of 1.0 is the "just-noticeable-difference".
|
|
||||||
// Color difference below 1.0 is not noticeable to a human eye, so we can disregard it.
|
|
||||||
// See https://en.wikipedia.org/wiki/Color_difference
|
|
||||||
const delta = (0, _colorUtils.colorDeltaE94)([r1.get(x, y), g1.get(x, y), b1.get(x, y)], [r2.get(x, y), g2.get(x, y), b2.get(x, y)]);
|
|
||||||
if (delta <= maxColorDeltaE94) {
|
|
||||||
drawGrayPixel(x, y);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!fastR || !fastG || !fastB) {
|
|
||||||
fastR = new _stats.FastStats(r1, r2);
|
|
||||||
fastG = new _stats.FastStats(g1, g2);
|
|
||||||
fastB = new _stats.FastStats(b1, b2);
|
|
||||||
}
|
|
||||||
const [varX1, varY1] = r1.boundXY(x - VARIANCE_WINDOW_RADIUS, y - VARIANCE_WINDOW_RADIUS);
|
|
||||||
const [varX2, varY2] = r1.boundXY(x + VARIANCE_WINDOW_RADIUS, y + VARIANCE_WINDOW_RADIUS);
|
|
||||||
const var1 = fastR.varianceC1(varX1, varY1, varX2, varY2) + fastG.varianceC1(varX1, varY1, varX2, varY2) + fastB.varianceC1(varX1, varY1, varX2, varY2);
|
|
||||||
const var2 = fastR.varianceC2(varX1, varY1, varX2, varY2) + fastG.varianceC2(varX1, varY1, varX2, varY2) + fastB.varianceC2(varX1, varY1, varX2, varY2);
|
|
||||||
// if this pixel is a part of a flood fill of a 3x3 square of either of the images, then it cannot be
|
|
||||||
// anti-aliasing pixel so it must be a pixel difference.
|
|
||||||
if (var1 === 0 || var2 === 0) {
|
|
||||||
drawRedPixel(x, y);
|
|
||||||
++diffCount;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const [ssimX1, ssimY1] = r1.boundXY(x - SSIM_WINDOW_RADIUS, y - SSIM_WINDOW_RADIUS);
|
|
||||||
const [ssimX2, ssimY2] = r1.boundXY(x + SSIM_WINDOW_RADIUS, y + SSIM_WINDOW_RADIUS);
|
|
||||||
const ssimRGB = ((0, _stats.ssim)(fastR, ssimX1, ssimY1, ssimX2, ssimY2) + (0, _stats.ssim)(fastG, ssimX1, ssimY1, ssimX2, ssimY2) + (0, _stats.ssim)(fastB, ssimX1, ssimY1, ssimX2, ssimY2)) / 3.0;
|
|
||||||
const isAntialiased = ssimRGB >= 0.99;
|
|
||||||
if (isAntialiased) {
|
|
||||||
drawYellowPixel(x, y);
|
|
||||||
} else {
|
|
||||||
drawRedPixel(x, y);
|
|
||||||
++diffCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diffCount;
|
|
||||||
}
|
|
||||||
70
tvapp2/node_modules/playwright-core/lib/image_tools/imageChannel.js
generated
vendored
@@ -1,70 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.ImageChannel = void 0;
|
|
||||||
var _colorUtils = require("./colorUtils");
|
|
||||||
/**
|
|
||||||
* 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 ImageChannel {
|
|
||||||
static intoRGB(width, height, data, options = {}) {
|
|
||||||
const {
|
|
||||||
paddingSize = 0,
|
|
||||||
paddingColorOdd = [255, 0, 255],
|
|
||||||
paddingColorEven = [0, 255, 0]
|
|
||||||
} = options;
|
|
||||||
const newWidth = width + 2 * paddingSize;
|
|
||||||
const newHeight = height + 2 * paddingSize;
|
|
||||||
const r = new Uint8Array(newWidth * newHeight);
|
|
||||||
const g = new Uint8Array(newWidth * newHeight);
|
|
||||||
const b = new Uint8Array(newWidth * newHeight);
|
|
||||||
for (let y = 0; y < newHeight; ++y) {
|
|
||||||
for (let x = 0; x < newWidth; ++x) {
|
|
||||||
const index = y * newWidth + x;
|
|
||||||
if (y >= paddingSize && y < newHeight - paddingSize && x >= paddingSize && x < newWidth - paddingSize) {
|
|
||||||
const offset = ((y - paddingSize) * width + (x - paddingSize)) * 4;
|
|
||||||
const alpha = data[offset + 3] === 255 ? 1 : data[offset + 3] / 255;
|
|
||||||
r[index] = (0, _colorUtils.blendWithWhite)(data[offset], alpha);
|
|
||||||
g[index] = (0, _colorUtils.blendWithWhite)(data[offset + 1], alpha);
|
|
||||||
b[index] = (0, _colorUtils.blendWithWhite)(data[offset + 2], alpha);
|
|
||||||
} else {
|
|
||||||
const color = (y + x) % 2 === 0 ? paddingColorEven : paddingColorOdd;
|
|
||||||
r[index] = color[0];
|
|
||||||
g[index] = color[1];
|
|
||||||
b[index] = color[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [new ImageChannel(newWidth, newHeight, r), new ImageChannel(newWidth, newHeight, g), new ImageChannel(newWidth, newHeight, b)];
|
|
||||||
}
|
|
||||||
constructor(width, height, data) {
|
|
||||||
this.data = void 0;
|
|
||||||
this.width = void 0;
|
|
||||||
this.height = void 0;
|
|
||||||
this.data = data;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
}
|
|
||||||
get(x, y) {
|
|
||||||
return this.data[y * this.width + x];
|
|
||||||
}
|
|
||||||
boundXY(x, y) {
|
|
||||||
return [Math.min(Math.max(x, 0), this.width - 1), Math.min(Math.max(y, 0), this.height - 1)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.ImageChannel = ImageChannel;
|
|
||||||
102
tvapp2/node_modules/playwright-core/lib/image_tools/stats.js
generated
vendored
@@ -1,102 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", {
|
|
||||||
value: true
|
|
||||||
});
|
|
||||||
exports.FastStats = void 0;
|
|
||||||
exports.ssim = ssim;
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Image channel has a 8-bit depth.
|
|
||||||
const DYNAMIC_RANGE = 2 ** 8 - 1;
|
|
||||||
function ssim(stats, x1, y1, x2, y2) {
|
|
||||||
const mean1 = stats.meanC1(x1, y1, x2, y2);
|
|
||||||
const mean2 = stats.meanC2(x1, y1, x2, y2);
|
|
||||||
const var1 = stats.varianceC1(x1, y1, x2, y2);
|
|
||||||
const var2 = stats.varianceC2(x1, y1, x2, y2);
|
|
||||||
const cov = stats.covariance(x1, y1, x2, y2);
|
|
||||||
const c1 = (0.01 * DYNAMIC_RANGE) ** 2;
|
|
||||||
const c2 = (0.03 * DYNAMIC_RANGE) ** 2;
|
|
||||||
return (2 * mean1 * mean2 + c1) * (2 * cov + c2) / (mean1 ** 2 + mean2 ** 2 + c1) / (var1 + var2 + c2);
|
|
||||||
}
|
|
||||||
class FastStats {
|
|
||||||
constructor(c1, c2) {
|
|
||||||
this.c1 = void 0;
|
|
||||||
this.c2 = void 0;
|
|
||||||
this._partialSumC1 = void 0;
|
|
||||||
this._partialSumC2 = void 0;
|
|
||||||
this._partialSumMult = void 0;
|
|
||||||
this._partialSumSq1 = void 0;
|
|
||||||
this._partialSumSq2 = void 0;
|
|
||||||
this.c1 = c1;
|
|
||||||
this.c2 = c2;
|
|
||||||
const {
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
} = c1;
|
|
||||||
this._partialSumC1 = new Array(width * height);
|
|
||||||
this._partialSumC2 = new Array(width * height);
|
|
||||||
this._partialSumSq1 = new Array(width * height);
|
|
||||||
this._partialSumSq2 = new Array(width * height);
|
|
||||||
this._partialSumMult = new Array(width * height);
|
|
||||||
const recalc = (mx, idx, initial, x, y) => {
|
|
||||||
mx[idx] = initial;
|
|
||||||
if (y > 0) mx[idx] += mx[(y - 1) * width + x];
|
|
||||||
if (x > 0) mx[idx] += mx[y * width + x - 1];
|
|
||||||
if (x > 0 && y > 0) mx[idx] -= mx[(y - 1) * width + x - 1];
|
|
||||||
};
|
|
||||||
for (let y = 0; y < height; ++y) {
|
|
||||||
for (let x = 0; x < width; ++x) {
|
|
||||||
const idx = y * width + x;
|
|
||||||
recalc(this._partialSumC1, idx, this.c1.data[idx], x, y);
|
|
||||||
recalc(this._partialSumC2, idx, this.c2.data[idx], x, y);
|
|
||||||
recalc(this._partialSumSq1, idx, this.c1.data[idx] * this.c1.data[idx], x, y);
|
|
||||||
recalc(this._partialSumSq2, idx, this.c2.data[idx] * this.c2.data[idx], x, y);
|
|
||||||
recalc(this._partialSumMult, idx, this.c1.data[idx] * this.c2.data[idx], x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_sum(partialSum, x1, y1, x2, y2) {
|
|
||||||
const width = this.c1.width;
|
|
||||||
let result = partialSum[y2 * width + x2];
|
|
||||||
if (y1 > 0) result -= partialSum[(y1 - 1) * width + x2];
|
|
||||||
if (x1 > 0) result -= partialSum[y2 * width + x1 - 1];
|
|
||||||
if (x1 > 0 && y1 > 0) result += partialSum[(y1 - 1) * width + x1 - 1];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
meanC1(x1, y1, x2, y2) {
|
|
||||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
|
||||||
return this._sum(this._partialSumC1, x1, y1, x2, y2) / N;
|
|
||||||
}
|
|
||||||
meanC2(x1, y1, x2, y2) {
|
|
||||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
|
||||||
return this._sum(this._partialSumC2, x1, y1, x2, y2) / N;
|
|
||||||
}
|
|
||||||
varianceC1(x1, y1, x2, y2) {
|
|
||||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
|
||||||
return (this._sum(this._partialSumSq1, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) ** 2 / N) / N;
|
|
||||||
}
|
|
||||||
varianceC2(x1, y1, x2, y2) {
|
|
||||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
|
||||||
return (this._sum(this._partialSumSq2, x1, y1, x2, y2) - this._sum(this._partialSumC2, x1, y1, x2, y2) ** 2 / N) / N;
|
|
||||||
}
|
|
||||||
covariance(x1, y1, x2, y2) {
|
|
||||||
const N = (y2 - y1 + 1) * (x2 - x1 + 1);
|
|
||||||
return (this._sum(this._partialSumMult, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) * this._sum(this._partialSumC2, x1, y1, x2, y2) / N) / N;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.FastStats = FastStats;
|
|
||||||