Compare commits

...

23 Commits

Author SHA1 Message Date
Andrea Giammarchi
83c2afeaf1 Updated Polyscript to its latest (#2036) 2024-04-24 16:56:47 +02:00
Andrea Giammarchi
643b76479f HTML class in MicroPython (#2033) 2024-04-22 12:43:17 +02:00
Andrea Giammarchi
cf92996071 Avoid PyWeb as part of stdlib on MicroPython (#2030)
* Avoid PyWeb as part of stdlib on MicroPython

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-04-17 17:10:23 +02:00
Andrea Giammarchi
c653296821 Added @xterm/addon-web-links to the terminal (#2027)
* Added @xterm/addon-web-links to the terminal

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-04-12 16:25:12 +02:00
Andrea Giammarchi
44cd6273ba PyTerminal .process(code) utility (#2026)
* PyTerminal .process(code) utility

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-04-12 15:44:20 +02:00
pre-commit-ci[bot]
d7d2dfb383 [pre-commit.ci] pre-commit autoupdate (#2012)
updates:
- [github.com/psf/black: 24.1.1 → 24.3.0](https://github.com/psf/black/compare/24.1.1...24.3.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Andrea Giammarchi <andrea.giammarchi@gmail.com>
2024-04-10 16:22:15 +02:00
Andrea Giammarchi
2d5cf096e0 Fix MicroPython badly handling unicode chars (#2018)
## Changes

  * fixed an issue with the **py-editor** related to the new `linebuffer` directive
  * provide in worker hook scope a simple callback that pre-buffers unicode sequences [accordingly to the standard](https://encoding.spec.whatwg.org/#utf-8-bytes-needed) so that the buffer is sent to the terminal only once those sequences are fulfilled
  * test with both `µ` and way more convoluted sequences such as 👩‍❤️‍👨 that the output, if either requested as input or already evaluated from the page works ... in latter case `test = "👩‍❤️‍👨"` completely messes up the program and the resulting string is empty
2024-04-09 14:51:10 +02:00
Andrea Giammarchi
6ee8217593 Updated dev-dependencies w/ ESLint 9 (#2021) 2024-04-09 14:27:06 +02:00
dependabot[bot]
6d45728787 Bump dorny/test-reporter from 1.8.0 to 1.9.0 in the github-actions group (#2019)
Bumps the github-actions group with 1 update: [dorny/test-reporter](https://github.com/dorny/test-reporter).


Updates `dorny/test-reporter` from 1.8.0 to 1.9.0
- [Release notes](https://github.com/dorny/test-reporter/releases)
- [Changelog](https://github.com/dorny/test-reporter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dorny/test-reporter/compare/v1.8.0...v1.9.0)

---
updated-dependencies:
- dependency-name: dorny/test-reporter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 10:40:53 +02:00
Andrea Giammarchi
65954a627e Allow MicroPython input("...") to work beside the code.interact() (#2017) 2024-04-04 18:13:00 +02:00
Andrea Giammarchi
2f1b764251 Provide input("") and sync output to MicroPython (#2016)
Provide input("") and sync output to MicroPython
2024-04-04 17:34:12 +02:00
Andrea Giammarchi
1fb6cddd70 Forgot to update current npm version (#2015) 2024-04-04 15:53:52 +02:00
Andrea Giammarchi
239add4e20 Better MicroPython Terminal (#2014)
* Better MicroPython Terminal + fixed Pyodide astty value
2024-04-04 15:33:41 +02:00
Andrea Giammarchi
4e4ac56729 Fix #1998 - Allow lazy terminal bootstrap + MicroPython terminal
* Fix #1998 - Allow lazy PyTerminal bootstrap

* Fix #1998 - Allow lazy terminal bootstrap / runtime

* Implemented mpy terminal in both main and worker

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-04-03 15:50:20 +02:00
Andrea Giammarchi
1447cb3094 Fix #1997 - Bring pyscript stdlib to the PyEditor (#2010)
* Fix #1997 - Bring pyscript stdlib to the PyEditor
2024-03-28 10:43:26 +01:00
dependabot[bot]
2f3659b676 Bump the github-actions group with 6 updates (#1995)
Bumps the github-actions group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/setup-node](https://github.com/actions/setup-node) | `3` | `4` |
| [actions/cache](https://github.com/actions/cache) | `3` | `4` |
| [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `1` | `2` |
| [conda-incubator/setup-miniconda](https://github.com/conda-incubator/setup-miniconda) | `2` | `3` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `3` | `4` |
| [dorny/test-reporter](https://github.com/dorny/test-reporter) | `1.6.0` | `1.8.0` |


Updates `actions/setup-node` from 3 to 4
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

Updates `actions/cache` from 3 to 4
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

Updates `softprops/action-gh-release` from 1 to 2
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

Updates `conda-incubator/setup-miniconda` from 2 to 3
- [Release notes](https://github.com/conda-incubator/setup-miniconda/releases)
- [Changelog](https://github.com/conda-incubator/setup-miniconda/blob/main/CHANGELOG.md)
- [Commits](https://github.com/conda-incubator/setup-miniconda/compare/v2...v3)

Updates `actions/upload-artifact` from 3 to 4
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

Updates `dorny/test-reporter` from 1.6.0 to 1.8.0
- [Release notes](https://github.com/dorny/test-reporter/releases)
- [Changelog](https://github.com/dorny/test-reporter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dorny/test-reporter/compare/v1.6.0...v1.8.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: conda-incubator/setup-miniconda
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: dorny/test-reporter
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 11:00:29 +01:00
Andrea Giammarchi
910c666319 pyscript.ffi - expose most essential utilities (#2005)
pyscript.ffi - expose most essential utilities
2024-03-22 17:41:06 +01:00
Andrea Giammarchi
eee2f64c1d Update Polyscript with its latest untar.gz and unzip abilities (#2004) 2024-03-22 10:42:01 +01:00
Andrea Giammarchi
d080246a0f Update MicroPython to its latest (#2003) 2024-03-21 11:47:47 +01:00
Andrea Giammarchi
98c0f5e50d Fix #2000 - Allow advanced users to deal themselves with responses (#2001)
* Fix #2000 - Allow advanced users to deal themselves with responses

* rolled back the direct utility idea

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Updated to latest MicroPython and latest way to have direct access with fetch

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-03-20 16:40:24 +01:00
Andrea Giammarchi
a1268f1aa2 Fix #1993 - Expose a handy fetch API (#1994) 2024-03-14 19:36:23 +01:00
Christian Clauss
69b8884045 Keep GitHub Actions up to date with GitHub's Dependabot (#1992)
* Keep GitHub Actions up to date with GitHub's Dependabot

Fix the warning like at the bottom right of
https://github.com/pyscript/pyscript/actions/runs/8263920642

# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-03-14 15:36:18 +01:00
Andrea Giammarchi
df1d699fe6 [feature] py-editor setup (#1989) 2024-03-13 12:25:30 +01:00
33 changed files with 988 additions and 516 deletions

13
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# Keep GitHub Actions up to date with GitHub's Dependabot...
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
version: 2
updates:
- package-ecosystem: github-actions
directory: /
groups:
github-actions:
patterns:
- "*" # Group all Actions updates into a single larger pull request
schedule:
interval: weekly

View File

@@ -17,12 +17,12 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 18.x node-version: 18.x
- name: Cache node modules - name: Cache node modules
uses: actions/cache@v3 uses: actions/cache@v4
env: env:
cache-name: cache-node-modules cache-name: cache-node-modules
with: with:
@@ -48,7 +48,7 @@ jobs:
run: zip -r -q ./build.zip ./dist run: zip -r -q ./build.zip ./dist
- name: Prepare Release - name: Prepare Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v2
with: with:
draft: true draft: true
prerelease: true prerelease: true

View File

@@ -19,12 +19,12 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 18.x node-version: 18.x
- name: Cache node modules - name: Cache node modules
uses: actions/cache@v3 uses: actions/cache@v4
env: env:
cache-name: cache-node-modules cache-name: cache-node-modules
with: with:

View File

@@ -23,12 +23,12 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 18.x node-version: 18.x
- name: Cache node modules - name: Cache node modules
uses: actions/cache@v3 uses: actions/cache@v4
env: env:
cache-name: cache-node-modules cache-name: cache-node-modules
with: with:

View File

@@ -24,12 +24,12 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 18.x node-version: 18.x
- name: Cache node modules - name: Cache node modules
uses: actions/cache@v3 uses: actions/cache@v4
env: env:
cache-name: cache-node-modules cache-name: cache-node-modules
with: with:

View File

@@ -37,12 +37,12 @@ jobs:
run: git log --graph -3 run: git log --graph -3
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v4
with: with:
node-version: 20.x node-version: 20.x
- name: Cache node modules - name: Cache node modules
uses: actions/cache@v3 uses: actions/cache@v4
env: env:
cache-name: cache-node-modules cache-name: cache-node-modules
with: with:
@@ -55,7 +55,7 @@ jobs:
${{ runner.os }}- ${{ runner.os }}-
- name: setup Miniconda - name: setup Miniconda
uses: conda-incubator/setup-miniconda@v2 uses: conda-incubator/setup-miniconda@v3
- name: Create and activate virtual environment - name: Create and activate virtual environment
run: | run: |
@@ -76,7 +76,7 @@ jobs:
run: | run: |
make test-integration make test-integration
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: pyscript name: pyscript
path: | path: |
@@ -84,7 +84,7 @@ jobs:
if-no-files-found: error if-no-files-found: error
retention-days: 7 retention-days: 7
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
if: success() || failure() if: success() || failure()
with: with:
name: test_results name: test_results

View File

@@ -8,7 +8,7 @@ jobs:
report: report:
runs-on: ubuntu-latest-8core runs-on: ubuntu-latest-8core
steps: steps:
- uses: dorny/test-reporter@v1.6.0 - uses: dorny/test-reporter@v1.9.0
with: with:
artifact: test_results artifact: test_results
name: Test reports name: Test reports

View File

@@ -25,7 +25,7 @@ repos:
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 24.1.1 rev: 24.3.0
hooks: hooks:
- id: black - id: black
exclude: pyscript\.core/src/stdlib/pyscript/__init__\.py exclude: pyscript\.core/src/stdlib/pyscript/__init__\.py

View File

@@ -1,41 +1,42 @@
{ {
"name": "@pyscript/core", "name": "@pyscript/core",
"version": "0.4.5", "version": "0.4.22",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@pyscript/core", "name": "@pyscript/core",
"version": "0.4.5", "version": "0.4.22",
"license": "APACHE-2.0", "license": "APACHE-2.0",
"dependencies": { "dependencies": {
"@ungap/with-resolvers": "^0.1.0", "@ungap/with-resolvers": "^0.1.0",
"basic-devtools": "^0.1.6", "basic-devtools": "^0.1.6",
"polyscript": "^0.9.0", "polyscript": "^0.12.6",
"sticky-module": "^0.1.1", "sticky-module": "^0.1.1",
"to-json-callback": "^0.1.1", "to-json-callback": "^0.1.1",
"type-checked-collections": "^0.1.7" "type-checked-collections": "^0.1.7"
}, },
"devDependencies": { "devDependencies": {
"@codemirror/commands": "^6.3.3", "@codemirror/commands": "^6.5.0",
"@codemirror/lang-python": "^6.1.4", "@codemirror/lang-python": "^6.1.5",
"@codemirror/language": "^6.10.1", "@codemirror/language": "^6.10.1",
"@codemirror/state": "^6.4.0", "@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.24.0", "@codemirror/view": "^6.26.3",
"@playwright/test": "^1.41.2", "@playwright/test": "^1.43.1",
"@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@webreflection/toml-j0.4": "^1.1.3", "@webreflection/toml-j0.4": "^1.1.3",
"@xterm/addon-fit": "^0.9.0-beta.1", "@xterm/addon-fit": "^0.10.0",
"@xterm/addon-web-links": "^0.11.0",
"chokidar": "^3.6.0", "chokidar": "^3.6.0",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"eslint": "^8.56.0", "eslint": "^9.1.1",
"rollup": "^4.11.0", "rollup": "^4.16.4",
"rollup-plugin-postcss": "^4.0.2", "rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-string": "^3.0.0", "rollup-plugin-string": "^3.0.0",
"static-handler": "^0.4.3", "static-handler": "^0.4.3",
"typescript": "^5.3.3", "typescript": "^5.4.5",
"xterm": "^5.3.0", "xterm": "^5.3.0",
"xterm-readline": "^1.1.1" "xterm-readline": "^1.1.1"
} }
@@ -68,9 +69,9 @@
} }
}, },
"node_modules/@codemirror/commands": { "node_modules/@codemirror/commands": {
"version": "6.3.3", "version": "6.5.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz", "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz",
"integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==", "integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0", "@codemirror/language": "^6.0.0",
@@ -80,9 +81,9 @@
} }
}, },
"node_modules/@codemirror/lang-python": { "node_modules/@codemirror/lang-python": {
"version": "6.1.4", "version": "6.1.5",
"resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.4.tgz", "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.5.tgz",
"integrity": "sha512-b6d1TDqrkCjFNvMO01SWldFiDoZ39yl3tDMC1Y5f8glA2eZpynPxJhwYVTlGFr0stizcJgrp6ojLEGH2myoZAw==", "integrity": "sha512-hCm+8X6wrnXJCGf+QhmFu1AXkdTVG7dHy0Ly6SI1N3SRPptaMvwX6oNQonOXOMPvmcjiB0xq342KAxX3BYpijw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.3.2", "@codemirror/autocomplete": "^6.3.2",
@@ -129,15 +130,15 @@
} }
}, },
"node_modules/@codemirror/state": { "node_modules/@codemirror/state": {
"version": "6.4.0", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
"integrity": "sha512-hm8XshYj5Fo30Bb922QX9hXB/bxOAVH+qaqHBzw5TKa72vOeslyGwd4X8M0c1dJ9JqxlaMceOQ8RsL9tC7gU0A==", "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==",
"dev": true "dev": true
}, },
"node_modules/@codemirror/view": { "node_modules/@codemirror/view": {
"version": "6.24.0", "version": "6.26.3",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.24.0.tgz", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz",
"integrity": "sha512-zK6m5pNkdhdJl8idPP1gA4N8JKTiSsOz8U/Iw+C1ChMwyLG7+MLiNXnH/wFuAk6KeGEe33/adOiAh5jMqee03w==", "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@codemirror/state": "^6.4.0", "@codemirror/state": "^6.4.0",
@@ -170,15 +171,15 @@
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "2.1.4", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz",
"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ajv": "^6.12.4", "ajv": "^6.12.4",
"debug": "^4.3.2", "debug": "^4.3.2",
"espree": "^9.6.0", "espree": "^10.0.1",
"globals": "^13.19.0", "globals": "^14.0.0",
"ignore": "^5.2.0", "ignore": "^5.2.0",
"import-fresh": "^3.2.1", "import-fresh": "^3.2.1",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
@@ -186,28 +187,28 @@
"strip-json-comments": "^3.1.1" "strip-json-comments": "^3.1.1"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "8.56.0", "version": "9.1.1",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.1.1.tgz",
"integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "integrity": "sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.11.14", "version": "0.13.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
"integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@humanwhocodes/object-schema": "^2.0.2", "@humanwhocodes/object-schema": "^2.0.3",
"debug": "^4.3.1", "debug": "^4.3.1",
"minimatch": "^3.0.5" "minimatch": "^3.0.5"
}, },
@@ -229,11 +230,24 @@
} }
}, },
"node_modules/@humanwhocodes/object-schema": { "node_modules/@humanwhocodes/object-schema": {
"version": "2.0.2", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
"integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"dev": true "dev": true
}, },
"node_modules/@humanwhocodes/retry": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.2.3.tgz",
"integrity": "sha512-X38nUbachlb01YMlvPFojKoiXq+LzZvuSce70KPMPdeM1Rj03k4dR7lDslhbqXn3Ang4EU3+EAmwEAsbrjHW3g==",
"dev": true,
"engines": {
"node": ">=18.18"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3", "version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
@@ -363,12 +377,12 @@
} }
}, },
"node_modules/@playwright/test": { "node_modules/@playwright/test": {
"version": "1.41.2", "version": "1.43.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz",
"integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==", "integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"playwright": "1.41.2" "playwright": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@@ -472,9 +486,9 @@
} }
}, },
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.4.tgz",
"integrity": "sha512-BV+u2QSfK3i1o6FucqJh5IK9cjAU6icjFFhvknzFgu472jzl0bBojfDAkJLBEsHFMo+YZg6rthBvBBt8z12IBQ==", "integrity": "sha512-GkhjAaQ8oUTOKE4g4gsZ0u8K/IHU1+2WQSgS1TwTcYvL+sjbaQjNHFXbOJ6kgqGHIO1DfUhI/Sphi9GkRT9K+Q==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -485,9 +499,9 @@
] ]
}, },
"node_modules/@rollup/rollup-android-arm64": { "node_modules/@rollup/rollup-android-arm64": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.4.tgz",
"integrity": "sha512-0ij3iw7sT5jbcdXofWO2NqDNjSVVsf6itcAkV2I6Xsq4+6wjW1A8rViVB67TfBEan7PV2kbLzT8rhOVWLI2YXw==", "integrity": "sha512-Bvm6D+NPbGMQOcxvS1zUl8H7DWlywSXsphAeOnVeiZLQ+0J6Is8T7SrjGTH29KtYkiY9vld8ZnpV3G2EPbom+w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -498,9 +512,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-arm64": { "node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.4.tgz",
"integrity": "sha512-yPLs6RbbBMupArf6qv1UDk6dzZvlH66z6NLYEwqTU0VHtss1wkI4UYeeMS7TVj5QRVvaNAWYKP0TD/MOeZ76Zg==", "integrity": "sha512-i5d64MlnYBO9EkCOGe5vPR/EeDwjnKOGGdd7zKFhU5y8haKhQZTN2DgVtpODDMxUr4t2K90wTUJg7ilgND6bXw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -511,9 +525,9 @@
] ]
}, },
"node_modules/@rollup/rollup-darwin-x64": { "node_modules/@rollup/rollup-darwin-x64": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.4.tgz",
"integrity": "sha512-OvqIgwaGAwnASzXaZEeoJY3RltOFg+WUbdkdfoluh2iqatd090UeOG3A/h0wNZmE93dDew9tAtXgm3/+U/B6bw==", "integrity": "sha512-WZupV1+CdUYehaZqjaFTClJI72fjJEgTXdf4NbW69I9XyvdmztUExBtcI2yIIU6hJtYvtwS6pkTkHJz+k08mAQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -524,9 +538,22 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm-gnueabihf": { "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.4.tgz",
"integrity": "sha512-X17s4hZK3QbRmdAuLd2EE+qwwxL8JxyVupEqAkxKPa/IgX49ZO+vf0ka69gIKsaYeo6c1CuwY3k8trfDtZ9dFg==", "integrity": "sha512-ADm/xt86JUnmAfA9mBqFcRp//RVRt1ohGOYF6yL+IFCYqOBNwy5lbEK05xTsEoJq+/tJzg8ICUtS82WinJRuIw==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.4.tgz",
"integrity": "sha512-tJfJaXPiFAG+Jn3cutp7mCs1ePltuAgRqdDZrzb1aeE3TktWWJ+g7xK9SNlaSUFw6IU4QgOxAY4rA+wZUT5Wfg==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -537,9 +564,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-gnu": { "node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.4.tgz",
"integrity": "sha512-673Lu9EJwxVB9NfYeA4AdNu0FOHz7g9t6N1DmT7bZPn1u6bTF+oZjj+fuxUcrfxWXE0r2jxl5QYMa9cUOj9NFg==", "integrity": "sha512-7dy1BzQkgYlUTapDTvK997cgi0Orh5Iu7JlZVBy1MBURk7/HSbHkzRnXZa19ozy+wwD8/SlpJnOOckuNZtJR9w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -550,9 +577,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-arm64-musl": { "node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.4.tgz",
"integrity": "sha512-yFW2msTAQNpPJaMmh2NpRalr1KXI7ZUjlN6dY/FhWlOclMrZezm5GIhy3cP4Ts2rIAC+IPLAjNibjp1BsxCVGg==", "integrity": "sha512-zsFwdUw5XLD1gQe0aoU2HVceI6NEW7q7m05wA46eUAyrkeNYExObfRFQcvA6zw8lfRc5BHtan3tBpo+kqEOxmg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -562,10 +589,23 @@
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.4.tgz",
"integrity": "sha512-p8C3NnxXooRdNrdv6dBmRTddEapfESEUflpICDNKXpHvTjRRq1J82CbU5G3XfebIZyI3B0s074JHMWD36qOW6w==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": { "node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.4.tgz",
"integrity": "sha512-kKT9XIuhbvYgiA3cPAGntvrBgzhWkGpBMzuk1V12Xuoqg7CI41chye4HU0vLJnGf9MiZzfNh4I7StPeOzOWJfA==", "integrity": "sha512-Lh/8ckoar4s4Id2foY7jNgitTOUQczwMWNYi+Mjt0eQ9LKhr6sK477REqQkmy8YHY3Ca3A2JJVdXnfb3Rrwkng==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -575,10 +615,23 @@
"linux" "linux"
] ]
}, },
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.4.tgz",
"integrity": "sha512-1xwwn9ZCQYuqGmulGsTZoKrrn0z2fAur2ujE60QgyDpHmBbXbxLaQiEvzJWDrscRq43c8DnuHx3QorhMTZgisQ==",
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": { "node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.4.tgz",
"integrity": "sha512-6q4ESWlyTO+erp1PSCmASac+ixaDv11dBk1fqyIuvIUc/CmRAX2Zk+2qK1FGo5q7kyDcjHCFVwgGFCGIZGVwCA==", "integrity": "sha512-LuOGGKAJ7dfRtxVnO1i3qWc6N9sh0Em/8aZ3CezixSTM+E9Oq3OvTsvC4sm6wWjzpsIlOCnZjdluINKESflJLA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -589,9 +642,9 @@
] ]
}, },
"node_modules/@rollup/rollup-linux-x64-musl": { "node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.4.tgz",
"integrity": "sha512-vIAQUmXeMLmaDN78HSE4Kh6xqof2e3TJUKr+LPqXWU4NYNON0MDN9h2+t4KHrPAQNmU3w1GxBQ/n01PaWFwa5w==", "integrity": "sha512-ch86i7KkJKkLybDP2AtySFTRi5fM3KXp0PnHocHuJMdZwu7BuyIKi35BE9guMlmTpwwBTB3ljHj9IQXnTCD0vA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -602,9 +655,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-arm64-msvc": { "node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.4.tgz",
"integrity": "sha512-LVXo9dDTGPr0nezMdqa1hK4JeoMZ02nstUxGYY/sMIDtTYlli1ZxTXBYAz3vzuuvKO4X6NBETciIh7N9+abT1g==", "integrity": "sha512-Ma4PwyLfOWZWayfEsNQzTDBVW8PZ6TUUN1uFTBQbF2Chv/+sjenE86lpiEwj2FiviSmSZ4Ap4MaAfl1ciF4aSA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -615,9 +668,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-ia32-msvc": { "node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.4.tgz",
"integrity": "sha512-xZVt6K70Gr3I7nUhug2dN6VRR1ibot3rXqXS3wo+8JP64t7djc3lBFyqO4GiVrhNaAIhUCJtwQ/20dr0h0thmQ==", "integrity": "sha512-9m/ZDrQsdo/c06uOlP3W9G2ENRVzgzbSXmXHT4hwVaDQhYcRpi9bgBT0FTG9OhESxwK0WjQxYOSfv40cU+T69w==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -628,9 +681,9 @@
] ]
}, },
"node_modules/@rollup/rollup-win32-x64-msvc": { "node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.11.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.4.tgz",
"integrity": "sha512-f3I7h9oTg79UitEco9/2bzwdciYkWr8pITs3meSDSlr1TdvQ7IxkQaaYN2YqZXX5uZhiYL+VuYDmHwNzhx+HOg==", "integrity": "sha512-YunpoOAyGLDseanENHmbFvQSfVL5BxW3k7hhy0eN4rb3gS/ct75dVD0EXOWIqFT/nE8XYW6LP6vz6ctKRi0k9A==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -672,9 +725,9 @@
"integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw==" "integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw=="
}, },
"node_modules/@webreflection/fetch": { "node_modules/@webreflection/fetch": {
"version": "0.1.4", "version": "0.1.5",
"resolved": "https://registry.npmjs.org/@webreflection/fetch/-/fetch-0.1.4.tgz", "resolved": "https://registry.npmjs.org/@webreflection/fetch/-/fetch-0.1.5.tgz",
"integrity": "sha512-oKjhwcg0Phu4e9UcAEnpwHFhnywZfcPQfP6erP4T4EGSquAX8ub8+b7lYaQ80yLG3YAV51a0Bu5hsypti6oK8w==" "integrity": "sha512-zCcqCJoNLvdeF41asAK71XPlwSPieeRDsE09albBunJEksuYPYNillKNQjf8p5BqSoTKTuKrW3lUm3MNodUC4g=="
}, },
"node_modules/@webreflection/toml-j0.4": { "node_modules/@webreflection/toml-j0.4": {
"version": "1.1.3", "version": "1.1.3",
@@ -683,14 +736,30 @@
"dev": true "dev": true
}, },
"node_modules/@xterm/addon-fit": { "node_modules/@xterm/addon-fit": {
"version": "0.9.0-beta.1", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.9.0-beta.1.tgz", "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
"integrity": "sha512-HmGRUMMamUpQYuQBF2VP1LJ0xzqF85LMFfpaNu84t1Tsrl1lPKJWtqX9FDZ22Rf5q6bnKdbj44TRVAUHgDRbLA==", "integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==",
"dev": true, "dev": true,
"peerDependencies": { "peerDependencies": {
"xterm": "^5.0.0" "@xterm/xterm": "^5.0.0"
} }
}, },
"node_modules/@xterm/addon-web-links": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.11.0.tgz",
"integrity": "sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==",
"dev": true,
"peerDependencies": {
"@xterm/xterm": "^5.0.0"
}
},
"node_modules/@xterm/xterm": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.4.0.tgz",
"integrity": "sha512-GlyzcZZ7LJjhFevthHtikhiDIl8lnTSgol6eTM4aoSNLcuXu3OEhnbqdCVIjtIil3jjabf3gDtb1S8FGahsuEw==",
"dev": true,
"peer": true
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.11.3", "version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@@ -974,14 +1043,14 @@
} }
}, },
"node_modules/coincident": { "node_modules/coincident": {
"version": "1.2.2", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.2.tgz", "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.3.tgz",
"integrity": "sha512-6gL6Rk6NFsRDb8IniRrx43srnoybZzbIfC6jAzPipNAOOZkOZcf+2CYofNq1gypp0zalauGw0dIyqrkTrU1j8A==", "integrity": "sha512-Uxz3BMTWIslzeWjuQnizGWVg0j6khbvHUQ8+5BdM7WuJEm4ALXwq3wluYoB+uF68uPBz/oUOeJnYURKyfjexlA==",
"dependencies": { "dependencies": {
"@ungap/structured-clone": "^1.2.0", "@ungap/structured-clone": "^1.2.0",
"@ungap/with-resolvers": "^0.1.0", "@ungap/with-resolvers": "^0.1.0",
"gc-hook": "^0.3.1", "gc-hook": "^0.3.1",
"proxy-target": "^3.0.1" "proxy-target": "^3.0.2"
}, },
"optionalDependencies": { "optionalDependencies": {
"ws": "^8.16.0" "ws": "^8.16.0"
@@ -1246,18 +1315,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
"dependencies": {
"esutils": "^2.0.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/dom-serializer": { "node_modules/dom-serializer": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
@@ -1356,41 +1413,37 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.56.0", "version": "9.1.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.1.1.tgz",
"integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "integrity": "sha512-b4cRQ0BeZcSEzPpY2PjFY70VbO32K7BStTGtBsnIGdTSEEQzBi8hPBcGQmTG2zUvFr9uLe0TK42bw8YszuHEqg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.4", "@eslint/eslintrc": "^3.0.2",
"@eslint/js": "8.56.0", "@eslint/js": "9.1.1",
"@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/config-array": "^0.13.0",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.2.3",
"@nodelib/fs.walk": "^1.2.8", "@nodelib/fs.walk": "^1.2.8",
"@ungap/structured-clone": "^1.2.0",
"ajv": "^6.12.4", "ajv": "^6.12.4",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"cross-spawn": "^7.0.2", "cross-spawn": "^7.0.2",
"debug": "^4.3.2", "debug": "^4.3.2",
"doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
"eslint-scope": "^7.2.2", "eslint-scope": "^8.0.1",
"eslint-visitor-keys": "^3.4.3", "eslint-visitor-keys": "^4.0.0",
"espree": "^9.6.1", "espree": "^10.0.1",
"esquery": "^1.4.2", "esquery": "^1.4.2",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"file-entry-cache": "^6.0.1", "file-entry-cache": "^8.0.0",
"find-up": "^5.0.0", "find-up": "^5.0.0",
"glob-parent": "^6.0.2", "glob-parent": "^6.0.2",
"globals": "^13.19.0",
"graphemer": "^1.4.0",
"ignore": "^5.2.0", "ignore": "^5.2.0",
"imurmurhash": "^0.1.4", "imurmurhash": "^0.1.4",
"is-glob": "^4.0.0", "is-glob": "^4.0.0",
"is-path-inside": "^3.0.3", "is-path-inside": "^3.0.3",
"js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1", "json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1", "levn": "^0.4.1",
"lodash.merge": "^4.6.2", "lodash.merge": "^4.6.2",
@@ -1404,23 +1457,23 @@
"eslint": "bin/eslint.js" "eslint": "bin/eslint.js"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/eslint-scope": { "node_modules/eslint-scope": {
"version": "7.2.2", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz",
"integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"esrecurse": "^4.3.0", "esrecurse": "^4.3.0",
"estraverse": "^5.2.0" "estraverse": "^5.2.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
@@ -1438,6 +1491,18 @@
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
} }
}, },
"node_modules/eslint/node_modules/eslint-visitor-keys": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
"integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint/node_modules/glob-parent": { "node_modules/eslint/node_modules/glob-parent": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -1451,17 +1516,29 @@
} }
}, },
"node_modules/espree": { "node_modules/espree": {
"version": "9.6.1", "version": "10.0.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz",
"integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"acorn": "^8.9.0", "acorn": "^8.11.3",
"acorn-jsx": "^5.3.2", "acorn-jsx": "^5.3.2",
"eslint-visitor-keys": "^3.4.1" "eslint-visitor-keys": "^4.0.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/espree/node_modules/eslint-visitor-keys": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
"integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/eslint" "url": "https://opencollective.com/eslint"
@@ -1549,15 +1626,15 @@
} }
}, },
"node_modules/file-entry-cache": { "node_modules/file-entry-cache": {
"version": "6.0.1", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"flat-cache": "^3.0.4" "flat-cache": "^4.0.0"
}, },
"engines": { "engines": {
"node": "^10.12.0 || >=12.0.0" "node": ">=16.0.0"
} }
}, },
"node_modules/fill-range": { "node_modules/fill-range": {
@@ -1589,23 +1666,22 @@
} }
}, },
"node_modules/flat-cache": { "node_modules/flat-cache": {
"version": "3.2.0", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"flatted": "^3.2.9", "flatted": "^3.2.9",
"keyv": "^4.5.3", "keyv": "^4.5.4"
"rimraf": "^3.0.2"
}, },
"engines": { "engines": {
"node": "^10.12.0 || >=12.0.0" "node": ">=16"
} }
}, },
"node_modules/flatted": { "node_modules/flatted": {
"version": "3.2.9", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
"dev": true "dev": true
}, },
"node_modules/fs.realpath": { "node_modules/fs.realpath": {
@@ -1704,26 +1780,17 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "13.24.0", "version": "14.0.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true, "dev": true,
"dependencies": {
"type-fest": "^0.20.2"
},
"engines": { "engines": {
"node": ">=8" "node": ">=18"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true
},
"node_modules/has-flag": { "node_modules/has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -2303,15 +2370,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-key": { "node_modules/path-key": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -2363,12 +2421,12 @@
"integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==" "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA=="
}, },
"node_modules/playwright": { "node_modules/playwright": {
"version": "1.41.2", "version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz",
"integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"playwright-core": "1.41.2" "playwright-core": "1.43.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@@ -2381,9 +2439,9 @@
} }
}, },
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.41.2", "version": "1.43.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz",
"integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==",
"dev": true, "dev": true,
"bin": { "bin": {
"playwright-core": "cli.js" "playwright-core": "cli.js"
@@ -2407,19 +2465,19 @@
} }
}, },
"node_modules/polyscript": { "node_modules/polyscript": {
"version": "0.9.0", "version": "0.12.6",
"resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.9.0.tgz", "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.6.tgz",
"integrity": "sha512-oyLH0jjuwZTln9v+43IJ04QR9AFTUL+n8EfEfkdbavbcMcUd9b25Evai+ZEESFnm/YU1P5ZhCglHRLTJMY4z8w==", "integrity": "sha512-tvVuPp+ygyDSqtLiNbbGZRUHvBz594xAao0bq0fg6JYcnidmuhZhgFiwwMC3tw/eJKKlBPKKc60UnYr6lvNH4A==",
"dependencies": { "dependencies": {
"@ungap/structured-clone": "^1.2.0", "@ungap/structured-clone": "^1.2.0",
"@ungap/with-resolvers": "^0.1.0", "@ungap/with-resolvers": "^0.1.0",
"@webreflection/fetch": "^0.1.4", "@webreflection/fetch": "^0.1.5",
"basic-devtools": "^0.1.6", "basic-devtools": "^0.1.6",
"codedent": "^0.1.2", "codedent": "^0.1.2",
"coincident": "^1.2.2", "coincident": "^1.2.3",
"gc-hook": "^0.3.1", "gc-hook": "^0.3.1",
"html-escaper": "^3.0.3", "html-escaper": "^3.0.3",
"proxy-target": "^3.0.1", "proxy-target": "^3.0.2",
"sticky-module": "^0.1.1", "sticky-module": "^0.1.1",
"to-json-callback": "^0.1.1" "to-json-callback": "^0.1.1"
} }
@@ -3003,9 +3061,9 @@
} }
}, },
"node_modules/proxy-target": { "node_modules/proxy-target": {
"version": "3.0.1", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/proxy-target/-/proxy-target-3.0.1.tgz", "resolved": "https://registry.npmjs.org/proxy-target/-/proxy-target-3.0.2.tgz",
"integrity": "sha512-EGskR5UV9bsY3eFXBFJqq/rsDUXw/WAjeuW5YuyYaxd+0F2zgMpuZ/l5NQtju4FBHKIJnBXNGEptGqyisUgdcg==" "integrity": "sha512-FFE1XNwXX/FNC3/P8HiKaJSy/Qk68RitG/QEcLy/bVnTAPlgTAWPZKh0pARLAnpfXQPKyalBhk009NRTgsk8vQ=="
}, },
"node_modules/punycode": { "node_modules/punycode": {
"version": "2.3.1", "version": "2.3.1",
@@ -3093,45 +3151,10 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rollup": { "node_modules/rollup": {
"version": "4.11.0", "version": "4.16.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.11.0.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.4.tgz",
"integrity": "sha512-2xIbaXDXjf3u2tajvA5xROpib7eegJ9Y/uPlSFhXLNpK9ampCczXAhLEb5yLzJyG3LAdI1NWtNjDXiLyniNdjQ==", "integrity": "sha512-kuaTJSUbz+Wsb2ATGvEknkI12XV40vIiHmLuFlejoo7HtDok/O5eDDD0UpCVY5bBX5U5RYo8wWP83H7ZsqVEnA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@types/estree": "1.0.5" "@types/estree": "1.0.5"
@@ -3144,19 +3167,22 @@
"npm": ">=8.0.0" "npm": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.11.0", "@rollup/rollup-android-arm-eabi": "4.16.4",
"@rollup/rollup-android-arm64": "4.11.0", "@rollup/rollup-android-arm64": "4.16.4",
"@rollup/rollup-darwin-arm64": "4.11.0", "@rollup/rollup-darwin-arm64": "4.16.4",
"@rollup/rollup-darwin-x64": "4.11.0", "@rollup/rollup-darwin-x64": "4.16.4",
"@rollup/rollup-linux-arm-gnueabihf": "4.11.0", "@rollup/rollup-linux-arm-gnueabihf": "4.16.4",
"@rollup/rollup-linux-arm64-gnu": "4.11.0", "@rollup/rollup-linux-arm-musleabihf": "4.16.4",
"@rollup/rollup-linux-arm64-musl": "4.11.0", "@rollup/rollup-linux-arm64-gnu": "4.16.4",
"@rollup/rollup-linux-riscv64-gnu": "4.11.0", "@rollup/rollup-linux-arm64-musl": "4.16.4",
"@rollup/rollup-linux-x64-gnu": "4.11.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.16.4",
"@rollup/rollup-linux-x64-musl": "4.11.0", "@rollup/rollup-linux-riscv64-gnu": "4.16.4",
"@rollup/rollup-win32-arm64-msvc": "4.11.0", "@rollup/rollup-linux-s390x-gnu": "4.16.4",
"@rollup/rollup-win32-ia32-msvc": "4.11.0", "@rollup/rollup-linux-x64-gnu": "4.16.4",
"@rollup/rollup-win32-x64-msvc": "4.11.0", "@rollup/rollup-linux-x64-musl": "4.16.4",
"@rollup/rollup-win32-arm64-msvc": "4.16.4",
"@rollup/rollup-win32-ia32-msvc": "4.16.4",
"@rollup/rollup-win32-x64-msvc": "4.16.4",
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
}, },
@@ -3533,22 +3559,10 @@
"resolved": "https://registry.npmjs.org/type-checked-collections/-/type-checked-collections-0.1.7.tgz", "resolved": "https://registry.npmjs.org/type-checked-collections/-/type-checked-collections-0.1.7.tgz",
"integrity": "sha512-fLIydlJy7IG9XL4wjRwEcKhxx/ekLXiWiMvcGo01cOMF+TN+5ZqajM1mRNRz2bNNi1bzou2yofhjZEQi7kgl9A==" "integrity": "sha512-fLIydlJy7IG9XL4wjRwEcKhxx/ekLXiWiMvcGo01cOMF+TN+5ZqajM1mRNRz2bNNi1bzou2yofhjZEQi7kgl9A=="
}, },
"node_modules/type-fest": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.3.3", "version": "5.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@@ -3655,6 +3669,7 @@
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz", "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz",
"integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==", "integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==",
"deprecated": "This package is now deprecated. Move to @xterm/xterm instead.",
"dev": true "dev": true
}, },
"node_modules/xterm-readline": { "node_modules/xterm-readline": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@pyscript/core", "name": "@pyscript/core",
"version": "0.4.5", "version": "0.4.22",
"type": "module", "type": "module",
"description": "PyScript", "description": "PyScript",
"module": "./index.js", "module": "./index.js",
@@ -20,7 +20,7 @@
}, },
"scripts": { "scripts": {
"server": "npx static-handler --coi .", "server": "npx static-handler --coi .",
"build": "npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && eslint src/ && npm run ts && npm run test:mpy", "build": "export ESLINT_USE_FLAT_CONFIG=false; npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && eslint src/ && npm run ts && npm run test:mpy",
"build:core": "rm -rf dist && rollup --config rollup/core.config.js && cp src/3rd-party/*.css dist/", "build:core": "rm -rf dist && rollup --config rollup/core.config.js && cp src/3rd-party/*.css dist/",
"build:plugins": "node rollup/plugins.cjs", "build:plugins": "node rollup/plugins.cjs",
"build:stdlib": "node rollup/stdlib.cjs", "build:stdlib": "node rollup/stdlib.cjs",
@@ -42,31 +42,32 @@
"dependencies": { "dependencies": {
"@ungap/with-resolvers": "^0.1.0", "@ungap/with-resolvers": "^0.1.0",
"basic-devtools": "^0.1.6", "basic-devtools": "^0.1.6",
"polyscript": "^0.9.0", "polyscript": "^0.12.6",
"sticky-module": "^0.1.1", "sticky-module": "^0.1.1",
"to-json-callback": "^0.1.1", "to-json-callback": "^0.1.1",
"type-checked-collections": "^0.1.7" "type-checked-collections": "^0.1.7"
}, },
"devDependencies": { "devDependencies": {
"@codemirror/commands": "^6.3.3", "@codemirror/commands": "^6.5.0",
"@codemirror/lang-python": "^6.1.4", "@codemirror/lang-python": "^6.1.5",
"@codemirror/language": "^6.10.1", "@codemirror/language": "^6.10.1",
"@codemirror/state": "^6.4.0", "@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.24.0", "@codemirror/view": "^6.26.3",
"@playwright/test": "^1.41.2", "@playwright/test": "^1.43.1",
"@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@webreflection/toml-j0.4": "^1.1.3", "@webreflection/toml-j0.4": "^1.1.3",
"@xterm/addon-fit": "^0.9.0-beta.1", "@xterm/addon-fit": "^0.10.0",
"@xterm/addon-web-links": "^0.11.0",
"chokidar": "^3.6.0", "chokidar": "^3.6.0",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"eslint": "^8.56.0", "eslint": "^9.1.1",
"rollup": "^4.11.0", "rollup": "^4.16.4",
"rollup-plugin-postcss": "^4.0.2", "rollup-plugin-postcss": "^4.0.2",
"rollup-plugin-string": "^3.0.0", "rollup-plugin-string": "^3.0.0",
"static-handler": "^0.4.3", "static-handler": "^0.4.3",
"typescript": "^5.3.3", "typescript": "^5.4.5",
"xterm": "^5.3.0", "xterm": "^5.3.0",
"xterm-readline": "^1.1.1" "xterm-readline": "^1.1.1"
}, },

View File

@@ -51,6 +51,9 @@ const modules = {
"xterm_addon-fit.js": fetch(`${CDN}/@xterm/addon-fit/+esm`).then((b) => "xterm_addon-fit.js": fetch(`${CDN}/@xterm/addon-fit/+esm`).then((b) =>
b.text(), b.text(),
), ),
"xterm_addon-web-links.js": fetch(
`${CDN}/@xterm/addon-web-links/+esm`,
).then((b) => b.text()),
"xterm.css": fetch(`${CDN}/xterm@${v("xterm")}/css/xterm.min.css`).then( "xterm.css": fetch(`${CDN}/xterm@${v("xterm")}/css/xterm.min.css`).then(
(b) => b.text(), (b) => b.text(),
), ),

View File

@@ -26,6 +26,9 @@ import { ErrorCode } from "./exceptions.js";
import { robustFetch as fetch, getText } from "./fetch.js"; import { robustFetch as fetch, getText } from "./fetch.js";
import { hooks, main, worker, codeFor, createFunction } from "./hooks.js"; import { hooks, main, worker, codeFor, createFunction } from "./hooks.js";
import { stdlib, optional } from "./stdlib.js";
export { stdlib, optional };
// generic helper to disambiguate between custom element and script // generic helper to disambiguate between custom element and script
const isScript = ({ tagName }) => tagName === "SCRIPT"; const isScript = ({ tagName }) => tagName === "SCRIPT";
@@ -165,7 +168,7 @@ for (const [TYPE, interpreter] of TYPES) {
// specific main and worker hooks // specific main and worker hooks
const hooks = { const hooks = {
main: { main: {
...codeFor(main), ...codeFor(main, TYPE),
async onReady(wrap, element) { async onReady(wrap, element) {
registerModule(wrap); registerModule(wrap);
@@ -262,7 +265,7 @@ for (const [TYPE, interpreter] of TYPES) {
}, },
}, },
worker: { worker: {
...codeFor(worker), ...codeFor(worker, TYPE),
// these are lazy getters that returns a composition // these are lazy getters that returns a composition
// of the current hooks or undefined, if no hook is present // of the current hooks or undefined, if no hook is present
get onReady() { get onReady() {

View File

@@ -2,7 +2,7 @@ import { typedSet } from "type-checked-collections";
import { dedent } from "polyscript/exports"; import { dedent } from "polyscript/exports";
import toJSONCallback from "to-json-callback"; import toJSONCallback from "to-json-callback";
import stdlib from "./stdlib.js"; import { stdlib, optional } from "./stdlib.js";
export const main = (name) => hooks.main[name]; export const main = (name) => hooks.main[name];
export const worker = (name) => hooks.worker[name]; export const worker = (name) => hooks.worker[name];
@@ -15,10 +15,11 @@ const code = (hooks, branch, key, lib) => {
}; };
}; };
export const codeFor = (branch) => { export const codeFor = (branch, type) => {
const pylib = type === "mpy" ? stdlib.replace(optional, "") : stdlib;
const hooks = {}; const hooks = {};
code(hooks, branch, `codeBeforeRun`, stdlib); code(hooks, branch, `codeBeforeRun`, pylib);
code(hooks, branch, `codeBeforeRunAsync`, stdlib); code(hooks, branch, `codeBeforeRunAsync`, pylib);
code(hooks, branch, `codeAfterRun`); code(hooks, branch, `codeAfterRun`);
code(hooks, branch, `codeAfterRunAsync`); code(hooks, branch, `codeAfterRunAsync`);
return hooks; return hooks;

View File

@@ -1,6 +1,6 @@
// PyScript py-editor plugin // PyScript py-editor plugin
import { Hook, XWorker, dedent } from "polyscript/exports"; import { Hook, XWorker, dedent } from "polyscript/exports";
import { TYPES } from "../core.js"; import { TYPES, stdlib } from "../core.js";
const RUN_BUTTON = `<svg style="height:20px;width:20px;vertical-align:-.125em;transform-origin:center;overflow:visible;color:green" viewBox="0 0 384 512" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg"><g transform="translate(192 256)" transform-origin="96 0"><g transform="translate(0,0) scale(1,1)"><path d="M361 215C375.3 223.8 384 239.3 384 256C384 272.7 375.3 288.2 361 296.1L73.03 472.1C58.21 482 39.66 482.4 24.52 473.9C9.377 465.4 0 449.4 0 432V80C0 62.64 9.377 46.63 24.52 38.13C39.66 29.64 58.21 29.99 73.03 39.04L361 215z" fill="currentColor" transform="translate(-192 -256)"></path></g></g></svg>`; const RUN_BUTTON = `<svg style="height:20px;width:20px;vertical-align:-.125em;transform-origin:center;overflow:visible;color:green" viewBox="0 0 384 512" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg"><g transform="translate(192 256)" transform-origin="96 0"><g transform="translate(0,0) scale(1,1)"><path d="M361 215C375.3 223.8 384 239.3 384 256C384 272.7 375.3 288.2 361 296.1L73.03 472.1C58.21 482 39.66 482.4 24.52 473.9C9.377 465.4 0 449.4 0 432V80C0 62.64 9.377 46.63 24.52 38.13C39.66 29.64 58.21 29.99 73.03 39.04L361 215z" fill="currentColor" transform="translate(-192 -256)"></path></g></g></svg>`;
@@ -8,13 +8,15 @@ let id = 0;
const getID = (type) => `${type}-editor-${id++}`; const getID = (type) => `${type}-editor-${id++}`;
const envs = new Map(); const envs = new Map();
const configs = new Map();
const hooks = { const hooks = {
worker: { worker: {
codeBeforeRun: () => stdlib,
// works on both Pyodide and MicroPython // works on both Pyodide and MicroPython
onReady: ({ runAsync, io }, { sync }) => { onReady: ({ runAsync, io }, { sync }) => {
io.stdout = (line) => sync.write(line); io.stdout = io.buffered(sync.write);
io.stderr = (line) => sync.writeErr(line); io.stderr = io.buffered(sync.writeErr);
sync.revoke(); sync.revoke();
sync.runAsync = runAsync; sync.runAsync = runAsync;
}, },
@@ -23,15 +25,26 @@ const hooks = {
async function execute({ currentTarget }) { async function execute({ currentTarget }) {
const { env, pySrc, outDiv } = this; const { env, pySrc, outDiv } = this;
const hasRunButton = !!currentTarget;
if (hasRunButton) {
currentTarget.disabled = true; currentTarget.disabled = true;
outDiv.innerHTML = ""; outDiv.innerHTML = "";
}
if (!envs.has(env)) { if (!envs.has(env)) {
const srcLink = URL.createObjectURL(new Blob([""])); const srcLink = URL.createObjectURL(new Blob([""]));
const xworker = XWorker.call(new Hook(null, hooks), srcLink, { const details = { type: this.interpreter };
type: this.interpreter, const { config } = this;
}); if (config) {
details.configURL = config;
const { parse } = config.endsWith(".toml")
? await import(/* webpackIgnore: true */ "../3rd-party/toml.js")
: JSON;
details.config = parse(await fetch(config).then((r) => r.text()));
}
const xworker = XWorker.call(new Hook(null, hooks), srcLink, details);
const { sync } = xworker; const { sync } = xworker;
const { promise, resolve } = Promise.withResolvers(); const { promise, resolve } = Promise.withResolvers();
@@ -46,21 +59,25 @@ async function execute({ currentTarget }) {
// before executing the current code // before executing the current code
envs.get(env).then((xworker) => { envs.get(env).then((xworker) => {
xworker.onerror = ({ error }) => { xworker.onerror = ({ error }) => {
if (hasRunButton) {
outDiv.innerHTML += `<span style='color:red'>${ outDiv.innerHTML += `<span style='color:red'>${
error.message || error error.message || error
}</span>\n`; }</span>\n`;
}
console.error(error); console.error(error);
}; };
const enable = () => { const enable = () => {
currentTarget.disabled = false; if (hasRunButton) currentTarget.disabled = false;
}; };
const { sync } = xworker; const { sync } = xworker;
sync.write = (str) => { sync.write = (str) => {
outDiv.innerText += `${str}\n`; if (hasRunButton) outDiv.innerText += `${str}\n`;
}; };
sync.writeErr = (str) => { sync.writeErr = (str) => {
if (hasRunButton) {
outDiv.innerHTML += `<span style='color:red'>${str}</span>\n`; outDiv.innerHTML += `<span style='color:red'>${str}</span>\n`;
}
}; };
sync.runAsync(pySrc).then(enable, enable); sync.runAsync(pySrc).then(enable, enable);
}); });
@@ -120,7 +137,6 @@ const init = async (script, type, interpreter) => {
{ keymap }, { keymap },
{ defaultKeymap }, { defaultKeymap },
] = await Promise.all([ ] = await Promise.all([
// TODO: find a way to actually produce these bundles locally
import(/* webpackIgnore: true */ "../3rd-party/codemirror.js"), import(/* webpackIgnore: true */ "../3rd-party/codemirror.js"),
import(/* webpackIgnore: true */ "../3rd-party/codemirror_state.js"), import(/* webpackIgnore: true */ "../3rd-party/codemirror_state.js"),
import( import(
@@ -131,6 +147,42 @@ const init = async (script, type, interpreter) => {
import(/* webpackIgnore: true */ "../3rd-party/codemirror_commands.js"), import(/* webpackIgnore: true */ "../3rd-party/codemirror_commands.js"),
]); ]);
const isSetup = script.hasAttribute("setup");
const hasConfig = script.hasAttribute("config");
const env = `${interpreter}-${script.getAttribute("env") || getID(type)}`;
if (hasConfig && configs.has(env)) {
throw new SyntaxError(
configs.get(env)
? `duplicated config for env: ${env}`
: `unable to add a config to the env: ${env}`,
);
}
configs.set(env, hasConfig);
const source = script.src
? await fetch(script.src).then((b) => b.text())
: script.textContent;
const context = {
interpreter,
env,
config:
hasConfig &&
new URL(script.getAttribute("config"), location.href).href,
get pySrc() {
return isSetup ? source : editor.state.doc.toString();
},
get outDiv() {
return isSetup ? null : outDiv;
},
};
if (isSetup) {
execute.call(context, { currentTarget: null });
return;
}
const selector = script.getAttribute("target"); const selector = script.getAttribute("target");
let target; let target;
@@ -149,18 +201,6 @@ const init = async (script, type, interpreter) => {
if (!target.hasAttribute("exec-id")) target.setAttribute("exec-id", 0); if (!target.hasAttribute("exec-id")) target.setAttribute("exec-id", 0);
if (!target.hasAttribute("root")) target.setAttribute("root", target.id); if (!target.hasAttribute("root")) target.setAttribute("root", target.id);
const env = `${interpreter}-${script.getAttribute("env") || getID(type)}`;
const context = {
interpreter,
env,
get pySrc() {
return editor.state.doc.toString();
},
get outDiv() {
return outDiv;
},
};
// @see https://github.com/JeffersGlass/mkdocs-pyscript/blob/main/mkdocs_pyscript/js/makeblocks.js // @see https://github.com/JeffersGlass/mkdocs-pyscript/blob/main/mkdocs_pyscript/js/makeblocks.js
const listener = execute.bind(context); const listener = execute.bind(context);
const [boxDiv, outDiv] = makeBoxDiv(listener, type); const [boxDiv, outDiv] = makeBoxDiv(listener, type);
@@ -210,7 +250,7 @@ const resetTimeout = () => {
}; };
// triggered both ASAP on the living DOM and via MutationObserver later // triggered both ASAP on the living DOM and via MutationObserver later
const pyEditor = async () => { const pyEditor = () => {
if (timeout) return; if (timeout) return;
timeout = setTimeout(resetTimeout, 250); timeout = setTimeout(resetTimeout, 250);
for (const [type, interpreter] of TYPES) { for (const [type, interpreter] of TYPES) {

View File

@@ -1,11 +1,10 @@
// PyScript py-terminal plugin // PyScript py-terminal plugin
import { TYPES, hooks } from "../core.js"; import { TYPES, hooks } from "../core.js";
import { notify } from "./error.js"; import { notify } from "./error.js";
import { defineProperty } from "polyscript/exports"; import { customObserver, defineProperties } from "polyscript/exports";
const SELECTOR = [...TYPES.keys()] // will contain all valid selectors
.map((type) => `script[type="${type}"][terminal],${type}-script[terminal]`) const SELECTORS = [];
.join(",");
// show the error on main and // show the error on main and
// stops the module from keep executing // stops the module from keep executing
@@ -14,8 +13,6 @@ const notifyAndThrow = (message) => {
throw new Error(message); throw new Error(message);
}; };
const notParsedYet = (script) => !bootstrapped.has(script);
const onceOnMain = ({ attributes: { worker } }) => !worker; const onceOnMain = ({ attributes: { worker } }) => !worker;
const bootstrapped = new WeakSet(); const bootstrapped = new WeakSet();
@@ -25,75 +22,128 @@ let addStyle = true;
// this callback will be serialized as string and it never needs // this callback will be serialized as string and it never needs
// to be invoked multiple times. Each xworker here is bootstrapped // to be invoked multiple times. Each xworker here is bootstrapped
// only once thanks to the `sync.is_pyterminal()` check. // only once thanks to the `sync.is_pyterminal()` check.
const workerReady = ({ interpreter, io, run }, { sync }) => { const workerReady = ({ interpreter, io, run, type }, { sync }) => {
if (!sync.is_pyterminal()) return; if (!sync.is_pyterminal()) return;
// in workers it's always safe to grab the polyscript currentScript // in workers it's always safe to grab the polyscript currentScript
run("from polyscript.currentScript import terminal as __terminal__"); // the ugly `_` dance is due MicroPython not able to import via:
// `from polyscript.currentScript import terminal as __terminal__`
run(
"from polyscript import currentScript as _; __terminal__ = _.terminal; del _",
);
// This part is inevitably duplicated as external scope
// can't be reached by workers out of the box.
// The detail is that here we use sync though, not readline.
const decoder = new TextDecoder();
let data = ""; let data = "";
const { pyterminal_read, pyterminal_write } = sync;
const decoder = new TextDecoder();
const generic = { const generic = {
isatty: true, isatty: false,
write(buffer) { write(buffer) {
data = decoder.decode(buffer); data = decoder.decode(buffer);
sync.pyterminal_write(data); pyterminal_write(data);
return buffer.length; return buffer.length;
}, },
}; };
// This part works already in both Pyodide and MicroPython
io.stderr = (error) => {
pyterminal_write(String(error.message || error));
};
// MicroPython has no code or code.interact()
// This part patches it in a way that simulates
// the code.interact() module in Pyodide.
if (type === "mpy") {
// monkey patch global input otherwise broken in MicroPython
interpreter.registerJsModule("_pyscript_input", {
input: pyterminal_read,
});
run("from _pyscript_input import input");
// this is needed to avoid truncated unicode in MicroPython
// the reason is that `linebuffer` false just send one byte
// per time and readline here doesn't like it much.
// MicroPython also has issues with code-points and
// replProcessChar(byte) but that function accepts only
// one byte per time so ... we have an issue!
// @see https://github.com/pyscript/pyscript/pull/2018
// @see https://github.com/WebReflection/buffer-points
const bufferPoints = (stdio) => {
const bytes = [];
let needed = 0;
return (buffer) => {
let written = 0;
for (const byte of buffer) {
bytes.push(byte);
// @see https://encoding.spec.whatwg.org/#utf-8-bytes-needed
if (needed) needed--;
else if (0xc2 <= byte && byte <= 0xdf) needed = 1;
else if (0xe0 <= byte && byte <= 0xef) needed = 2;
else if (0xf0 <= byte && byte <= 0xf4) needed = 3;
if (!needed) {
written += bytes.length;
stdio(new Uint8Array(bytes.splice(0)));
}
}
return written;
};
};
io.stdout = bufferPoints(generic.write);
// tiny shim of the code module with only interact
// to bootstrap a REPL like environment
interpreter.registerJsModule("code", {
interact() {
let input = "";
let length = 1;
const encoder = new TextEncoder();
const acc = [];
const handlePoints = bufferPoints((buffer) => {
acc.push(...buffer);
pyterminal_write(decoder.decode(buffer));
});
// avoid duplicating the output produced by the input
io.stdout = (buffer) =>
length++ > input.length ? handlePoints(buffer) : 0;
interpreter.replInit();
// loop forever waiting for user inputs
(function repl() {
const out = decoder.decode(new Uint8Array(acc.splice(0)));
// print in current line only the last line produced by the REPL
const data = `${pyterminal_read(out.split("\n").at(-1))}\r`;
length = 0;
input = encoder.encode(data);
for (const c of input) interpreter.replProcessChar(c);
repl();
})();
},
});
} else {
interpreter.setStdout(generic); interpreter.setStdout(generic);
interpreter.setStderr(generic); interpreter.setStderr(generic);
interpreter.setStdin({ interpreter.setStdin({
isatty: true, isatty: false,
stdin: () => sync.pyterminal_read(data), stdin: () => pyterminal_read(data),
}); });
io.stderr = (error) => {
sync.pyterminal_write(`${error.message || error}\n`);
};
};
const pyTerminal = async () => {
const terminals = document.querySelectorAll(SELECTOR);
const unknown = [].filter.call(terminals, notParsedYet);
// no results will look further for runtime nodes
if (!unknown.length) return;
// early flag elements as known to avoid concurrent
// MutationObserver invokes of this async handler
else unknown.forEach(bootstrapped.add, bootstrapped);
// we currently support only one terminal as in "classic"
if ([].filter.call(terminals, onceOnMain).length > 1)
notifyAndThrow("You can use at most 1 main terminal");
// import styles lazily
if (addStyle) {
addStyle = false;
document.head.append(
Object.assign(document.createElement("link"), {
rel: "stylesheet",
href: new URL("./xterm.css", import.meta.url),
}),
);
} }
};
const pyTerminal = async (element) => {
// lazy load these only when a valid terminal is found // lazy load these only when a valid terminal is found
const [{ Terminal }, { Readline }, { FitAddon }] = await Promise.all([ const [{ Terminal }, { Readline }, { FitAddon }, { WebLinksAddon }] =
await Promise.all([
import(/* webpackIgnore: true */ "../3rd-party/xterm.js"), import(/* webpackIgnore: true */ "../3rd-party/xterm.js"),
import(/* webpackIgnore: true */ "../3rd-party/xterm-readline.js"), import(/* webpackIgnore: true */ "../3rd-party/xterm-readline.js"),
import(/* webpackIgnore: true */ "../3rd-party/xterm_addon-fit.js"), import(/* webpackIgnore: true */ "../3rd-party/xterm_addon-fit.js"),
import(
/* webpackIgnore: true */ "../3rd-party/xterm_addon-web-links.js"
),
]); ]);
for (const element of unknown) {
// hopefully to be removed in the near future!
if (element.matches('script[type="mpy"],mpy-script'))
notifyAndThrow("Unsupported terminal.");
const readline = new Readline(); const readline = new Readline();
// common main thread initialization for both worker // common main thread initialization for both worker
@@ -121,10 +171,29 @@ const pyTerminal = async () => {
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon); terminal.loadAddon(fitAddon);
terminal.loadAddon(readline); terminal.loadAddon(readline);
terminal.loadAddon(new WebLinksAddon());
terminal.open(target); terminal.open(target);
fitAddon.fit(); fitAddon.fit();
terminal.focus(); terminal.focus();
defineProperty(element, "terminal", { value: terminal }); defineProperties(element, {
terminal: { value: terminal },
process: {
value: async (code) => {
// this loop is the only way I could find to actually simulate
// the user input char after char in a way that works in both
// MicroPython and Pyodide
for (const line of code.split(/(?:\r|\n|\r\n)/)) {
terminal.paste(`${line}\n`);
do {
await new Promise((resolve) =>
setTimeout(resolve, 0),
);
} while (!readline.activeRead?.resolve);
readline.activeRead.resolve(line);
}
},
},
});
return terminal; return terminal;
}; };
@@ -158,7 +227,7 @@ const pyTerminal = async () => {
} else { } else {
// in the main case, just bootstrap XTerm without // in the main case, just bootstrap XTerm without
// allowing any input as that's not possible / awkward // allowing any input as that's not possible / awkward
hooks.main.onReady.add(function main({ interpreter, io, run }) { hooks.main.onReady.add(function main({ interpreter, io, run, type }) {
console.warn("py-terminal is read only on main thread"); console.warn("py-terminal is read only on main thread");
hooks.main.onReady.delete(main); hooks.main.onReady.delete(main);
@@ -171,13 +240,22 @@ const pyTerminal = async () => {
run("from js import __py_terminal__ as __terminal__"); run("from js import __py_terminal__ as __terminal__");
delete globalThis.__py_terminal__; delete globalThis.__py_terminal__;
// This part is inevitably duplicated as external scope io.stderr = (error) => {
// can't be reached by workers out of the box. readline.write(String(error.message || error));
// The detail is that here we use readline here, not sync. };
const decoder = new TextDecoder();
if (type === "mpy") {
interpreter.setStdin = Object; // as no-op
interpreter.setStderr = Object; // as no-op
interpreter.setStdout = ({ write }) => {
io.stdout = write;
};
}
let data = ""; let data = "";
const decoder = new TextDecoder();
const generic = { const generic = {
isatty: true, isatty: false,
write(buffer) { write(buffer) {
data = decoder.decode(buffer); data = decoder.decode(buffer);
readline.write(data); readline.write(data);
@@ -187,20 +265,33 @@ const pyTerminal = async () => {
interpreter.setStdout(generic); interpreter.setStdout(generic);
interpreter.setStderr(generic); interpreter.setStderr(generic);
interpreter.setStdin({ interpreter.setStdin({
isatty: true, isatty: false,
stdin: () => readline.read(data), stdin: () => readline.read(data),
}); });
io.stderr = (error) => {
readline.write(`${error.message || error}\n`);
};
}); });
} }
}
}; };
const mo = new MutationObserver(pyTerminal); for (const key of TYPES.keys()) {
mo.observe(document, { childList: true, subtree: true }); const selector = `script[type="${key}"][terminal],${key}-script[terminal]`;
SELECTORS.push(selector);
customObserver.set(selector, async (element) => {
// we currently support only one terminal on main as in "classic"
const terminals = document.querySelectorAll(SELECTORS.join(","));
if ([].filter.call(terminals, onceOnMain).length > 1)
notifyAndThrow("You can use at most 1 main terminal");
// try to check the current document ASAP // import styles lazily
export default pyTerminal(); if (addStyle) {
addStyle = false;
document.head.append(
Object.assign(document.createElement("link"), {
rel: "stylesheet",
href: new URL("./xterm.css", import.meta.url),
}),
);
}
await pyTerminal(element);
});
}

View File

@@ -8,6 +8,27 @@
import pyscript from "./stdlib/pyscript.js"; import pyscript from "./stdlib/pyscript.js";
class Ignore extends Array {
#add = false;
#paths;
#array;
constructor(array, ...paths) {
super();
this.#array = array;
this.#paths = paths;
}
push(...values) {
if (this.#add) super.push(...values);
return this.#array.push(...values);
}
path(path) {
for (const _path of this.#paths) {
// bails out at the first `true` value
if ((this.#add = path.startsWith(_path))) break;
}
}
}
const { entries } = Object; const { entries } = Object;
const python = [ const python = [
@@ -16,16 +37,19 @@ const python = [
"_path = None", "_path = None",
]; ];
const ignore = new Ignore(python, "./pyweb");
const write = (base, literal) => { const write = (base, literal) => {
for (const [key, value] of entries(literal)) { for (const [key, value] of entries(literal)) {
python.push(`_path = _Path("${base}/${key}")`); ignore.path(`${base}/${key}`);
ignore.push(`_path = _Path("${base}/${key}")`);
if (typeof value === "string") { if (typeof value === "string") {
const code = JSON.stringify(value); const code = JSON.stringify(value);
python.push(`_path.write_text(${code},encoding="utf-8")`); ignore.push(`_path.write_text(${code},encoding="utf-8")`);
} else { } else {
// @see https://github.com/pyscript/pyscript/pull/1813#issuecomment-1781502909 // @see https://github.com/pyscript/pyscript/pull/1813#issuecomment-1781502909
python.push(`if not _os.path.exists("${base}/${key}"):`); ignore.push(`if not _os.path.exists("${base}/${key}"):`);
python.push(" _path.mkdir(parents=True, exist_ok=True)"); ignore.push(" _path.mkdir(parents=True, exist_ok=True)");
write(`${base}/${key}`, value); write(`${base}/${key}`, value);
} }
} }
@@ -42,4 +66,5 @@ python.push(
); );
python.push("\n"); python.push("\n");
export default python.join("\n"); export const stdlib = python.join("\n");
export const optional = ignore.join("\n");

View File

@@ -30,6 +30,7 @@
# as it works transparently in both the main thread and worker cases. # as it works transparently in both the main thread and worker cases.
from pyscript.display import HTML, display from pyscript.display import HTML, display
from pyscript.fetch import fetch
from pyscript.magic_js import ( from pyscript.magic_js import (
RUNNING_IN_WORKER, RUNNING_IN_WORKER,
PyWorker, PyWorker,

View File

@@ -6,17 +6,17 @@ import re
from pyscript.magic_js import current_target, document, window from pyscript.magic_js import current_target, document, window
_MIME_METHODS = { _MIME_METHODS = {
"__repr__": "text/plain",
"_repr_html_": "text/html",
"_repr_markdown_": "text/markdown",
"_repr_svg_": "image/svg+xml",
"_repr_pdf_": "application/pdf",
"_repr_jpeg_": "image/jpeg",
"_repr_png_": "image/png",
"_repr_latex": "text/latex",
"_repr_json_": "application/json",
"_repr_javascript_": "application/javascript",
"savefig": "image/png", "savefig": "image/png",
"_repr_javascript_": "application/javascript",
"_repr_json_": "application/json",
"_repr_latex": "text/latex",
"_repr_png_": "image/png",
"_repr_jpeg_": "image/jpeg",
"_repr_pdf_": "application/pdf",
"_repr_svg_": "image/svg+xml",
"_repr_markdown_": "text/markdown",
"_repr_html_": "text/html",
"__repr__": "text/plain",
} }
@@ -99,7 +99,7 @@ def _format_mime(obj):
format_dict = mimebundle format_dict = mimebundle
output, not_available = None, [] output, not_available = None, []
for method, mime_type in reversed(_MIME_METHODS.items()): for method, mime_type in _MIME_METHODS.items():
if mime_type in format_dict: if mime_type in format_dict:
output = format_dict[mime_type] output = format_dict[mime_type]
else: else:

View File

@@ -0,0 +1,94 @@
import json
import js
### wrap the response to grant Pythonic results
class _Response:
def __init__(self, response):
self._response = response
# grant access to response.ok and other fields
def __getattr__(self, attr):
return getattr(self._response, attr)
def _as_bytearray(self, buffer):
ui8a = js.Uint8Array.new(buffer)
size = ui8a.length
ba = bytearray(size)
for i in range(0, size):
ba[i] = ui8a[i]
return ba
# exposed methods with Pythonic results
async def arrayBuffer(self):
buffer = await self._response.arrayBuffer()
# works in Pyodide
if hasattr(buffer, "to_py"):
return buffer.to_py()
# shims in MicroPython
return memoryview(self._as_bytearray(buffer))
async def blob(self):
return await self._response.blob()
async def bytearray(self):
buffer = await self._response.arrayBuffer()
return self._as_bytearray(buffer)
async def json(self):
return json.loads(await self.text())
async def text(self):
return await self._response.text()
### allow direct await to _Response methods
class _DirectResponse:
@staticmethod
def setup(promise, response):
promise._response = _Response(response)
return promise._response
def __init__(self, promise):
self._promise = promise
promise._response = None
promise.arrayBuffer = self.arrayBuffer
promise.blob = self.blob
promise.bytearray = self.bytearray
promise.json = self.json
promise.text = self.text
async def _response(self):
if not self._promise._response:
await self._promise
return self._promise._response
async def arrayBuffer(self):
response = await self._response()
return await response.arrayBuffer()
async def blob(self):
response = await self._response()
return await response.blob()
async def bytearray(self):
response = await self._response()
return await response.bytearray()
async def json(self):
response = await self._response()
return await response.json()
async def text(self):
response = await self._response()
return await response.text()
def fetch(url, **kw):
# workaround Pyodide / MicroPython dict <-> js conversion
options = js.JSON.parse(json.dumps(kw))
awaited = lambda response, *args: _DirectResponse.setup(promise, response)
promise = js.fetch(url, options).then(awaited)
_DirectResponse(promise)
return promise

View File

@@ -0,0 +1,18 @@
try:
import js
from pyodide.ffi import create_proxy as _cp
from pyodide.ffi import to_js as _py_tjs
from_entries = js.Object.fromEntries
def _tjs(value, **kw):
if not hasattr(kw, "dict_converter"):
kw["dict_converter"] = from_entries
return _py_tjs(value, **kw)
except:
from jsffi import create_proxy as _cp
from jsffi import to_js as _tjs
create_proxy = _cp
to_js = _tjs

View File

@@ -0,0 +1,95 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="../dist/core.css">
</head>
<body>
<script type="module">
import fetch from 'https://esm.run/@webreflection/fetch';
globalThis.fetch_text = await fetch("config.json").text();
globalThis.fetch_json = JSON.stringify(await fetch("config.json").json());
globalThis.fetch_buffer = new Uint8Array((await fetch("config.json").arrayBuffer())).length;
document.head.appendChild(
Object.assign(
document.createElement('script'),
{
type: 'module',
src: '../dist/core.js'
}
)
);
</script>
<script type="mpy" async>
import js, json
from pyscript import document, fetch
fetch_text = await (await fetch("config.json")).text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_text = await fetch("config.json").text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_json = await (await fetch("config.json")).json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_json = await fetch("config.json").json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_buffer = await (await fetch("config.json")).arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
fetch_buffer = await fetch("config.json").arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
print(await (await fetch("config.json")).bytearray())
print(await (await fetch("config.json")).blob())
if (await fetch("shenanigans.nope")).ok == False:
document.documentElement.classList.add('mpy')
</script>
<script type="py" async>
import js, json
from pyscript import document, fetch
fetch_text = await (await fetch("config.json")).text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_text = await fetch("config.json").text()
if (fetch_text != js.fetch_text):
raise Exception("fetch_text")
fetch_json = await (await fetch("config.json")).json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_json = await fetch("config.json").json()
if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json):
raise Exception("fetch_json")
fetch_buffer = await (await fetch("config.json")).arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
fetch_buffer = await fetch("config.json").arrayBuffer()
if (len(fetch_buffer) != js.fetch_buffer):
raise Exception("fetch_buffer")
print(await (await fetch("config.json")).bytearray())
print(await (await fetch("config.json")).blob())
if (await fetch("shenanigans.nope")).ok == False:
document.documentElement.classList.add('py')
</script>
</body>
</html>

View File

@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PyScript FFI</title>
<link rel="stylesheet" href="../dist/core.css">
<script type="module" src="../dist/core.js"></script>
</head>
<body>
<script type="mpy">
from pyscript import document
from pyscript.ffi import to_js
document.documentElement.classList.add(
to_js({"ok": "mpy"}).ok
)
</script>
<script type="py">
from pyscript import document
from pyscript.ffi import to_js
document.documentElement.classList.add(
to_js({"ok": "py"}).ok
)
</script>
</body>
</html>

View File

@@ -78,3 +78,13 @@ test('Pyodide + multiple terminals via Worker', async ({ page }) => {
await page.goto('http://localhost:8080/test/py-terminals.html'); await page.goto('http://localhost:8080/test/py-terminals.html');
await page.waitForSelector('html.first.second'); await page.waitForSelector('html.first.second');
}); });
test('MicroPython + Pyodide fetch', async ({ page }) => {
await page.goto('http://localhost:8080/test/fetch.html');
await page.waitForSelector('html.mpy.py');
});
test('MicroPython + Pyodide ffi', async ({ page }) => {
await page.goto('http://localhost:8080/test/ffi.html');
await page.waitForSelector('html.mpy.py');
});

View File

@@ -0,0 +1,2 @@
[js_modules.worker]
"https://cdn.jsdelivr.net/npm/html-escaper/+esm" = "html_escaper"

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../../dist/core.css">
<script type="module" src="../../dist/core.js"></script>
</head>
<body>
<!-- a setup node with a config for an env -->
<script type="mpy-editor" src="task1.py" config="./config.toml" env="task1" setup></script>
<script type="mpy-editor" env="task1">
from pyscript.js_modules.html_escaper import escape, unescape
print(unescape(escape("<OK>")))
a = 1
</script>
<!-- a share-nothing micropython editor -->
<script type="mpy-editor" config="./config.toml">
from pyscript.js_modules.html_escaper import escape, unescape
print(unescape(escape("<OK>")))
b = 2
try:
print(a)
except:
print("all good")
</script>
<!-- a config once micropython env -->
<script type="mpy-editor" env="task2" config="./config.toml">
from pyscript.js_modules.html_escaper import escape, unescape
print(unescape(escape("<OK>")))
c = 3
try:
print(b)
except:
print("all good")
</script>
<script type="mpy-editor" env="task2">
print(c)
</script>
</body>
</html>

View File

@@ -0,0 +1,5 @@
from pyscript import window
window.console.log("OK")
a = 1

View File

@@ -9,24 +9,10 @@
<style>.xterm { padding: .5rem; }</style> <style>.xterm { padding: .5rem; }</style>
</head> </head>
<body> <body>
<script type="py"> <script type="mpy" worker terminal>
def greetings(event): print("µpython")
print('hello world') import code
code.interact()
</script> </script>
<py-script worker terminal>
# works on both worker and main scripts
print("__terminal__", __terminal__)
import sys
from pyscript import display, document
display("Hello", "PyScript Next - PyTerminal", append=False)
print("this should go to the terminal")
print("another line")
# this works as expected
print("this goes to stderr", file=sys.stderr)
document.addEventListener('click', lambda event: print(event.type));
</py-script>
<button id="my-button" py-click="greetings">Click me</button>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,4 @@
declare var r: any;
declare var n: any;
declare var t: {};
export { r as WebLinksAddon, n as __esModule, t as default };

View File

@@ -1,3 +1,5 @@
import { stdlib } from "./stdlib.js";
import { optional } from "./stdlib.js";
import TYPES from "./types.js"; import TYPES from "./types.js";
/** /**
* A `Worker` facade able to bootstrap on the worker thread only a PyScript module. * A `Worker` facade able to bootstrap on the worker thread only a PyScript module.
@@ -38,11 +40,7 @@ declare const exportedHooks: {
}; };
worker: { worker: {
onReady: Set<Function>; onReady: Set<Function>;
onBeforeRun: Set<Function>; /** onBeforeRun: Set<Function>;
* Given a generic DOM Element, tries to fetch the 'src' attribute, if present.
* It either throws an error if the 'src' can't be fetched or it returns a fallback
* content as source.
*/
onBeforeRunAsync: Set<Function>; onBeforeRunAsync: Set<Function>;
onAfterRun: Set<Function>; onAfterRun: Set<Function>;
onAfterRunAsync: Set<Function>; onAfterRunAsync: Set<Function>;
@@ -54,5 +52,4 @@ declare const exportedHooks: {
}; };
declare const exportedConfig: {}; declare const exportedConfig: {};
declare const exportedWhenDefined: (type: string) => Promise<any>; declare const exportedWhenDefined: (type: string) => Promise<any>;
import sync from "./sync.js"; export { stdlib, optional, TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined };
export { TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined };

View File

@@ -1,6 +1,6 @@
export function main(name: any): any; export function main(name: any): any;
export function worker(name: any): any; export function worker(name: any): any;
export function codeFor(branch: any): {}; export function codeFor(branch: any, type: any): {};
export function createFunction(self: any, name: any): any; export function createFunction(self: any, name: any): any;
export namespace hooks { export namespace hooks {
namespace main { namespace main {

View File

@@ -1,2 +1 @@
declare const _default: Promise<void>; export {};
export default _default;

View File

@@ -1,2 +1,2 @@
declare const _default: string; export const stdlib: string;
export default _default; export const optional: string;

View File

@@ -3,6 +3,8 @@ declare namespace _default {
"__init__.py": string; "__init__.py": string;
"display.py": string; "display.py": string;
"event_handling.py": string; "event_handling.py": string;
"fetch.py": string;
"ffi.py": string;
"magic_js.py": string; "magic_js.py": string;
"util.py": string; "util.py": string;
}; };