diff --git a/.gitignore b/.gitignore
index b73e485..86b0437 100644
--- a/.gitignore
+++ b/.gitignore
@@ -118,8 +118,9 @@ venv.bak/
# Rope project settings
.ropeproject
-# VS Code Files
+# IDE Files
.vscode/
+.idea/
# mkdocs documentation
/site
diff --git a/pyscriptjs/.eslintrc.js b/pyscriptjs/.eslintrc.js
new file mode 100644
index 0000000..6853e5c
--- /dev/null
+++ b/pyscriptjs/.eslintrc.js
@@ -0,0 +1,46 @@
+module.exports = {
+ parser: '@typescript-eslint/parser',
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:@typescript-eslint/recommended-requiring-type-checking',
+ ],
+ parserOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module',
+ tsconfigRootDir: __dirname,
+ project: ['./tsconfig.json'],
+ extraFileExtensions: ['.svelte'],
+ },
+ env: {
+ es6: true,
+ browser: true,
+ },
+ overrides: [
+ {
+ files: ['*.svelte'],
+ processor: 'svelte3/svelte3',
+ },
+ ],
+ settings: {
+ 'svelte3/typescript': require('typescript'),
+ // ignore style tags in Svelte because of Tailwind CSS
+ // See https://github.com/sveltejs/eslint-plugin-svelte3/issues/70
+ 'svelte3/ignore-styles': () => true,
+ },
+ plugins: ['svelte3', '@typescript-eslint'],
+ ignorePatterns: ['node_modules'],
+ rules: {
+ 'no-prototype-builtins': 'warn',
+ '@typescript-eslint/no-unused-vars': 'warn',
+ '@typescript-eslint/no-explicit-any': 'warn',
+ '@typescript-eslint/no-unsafe-assignment': 'warn',
+ '@typescript-eslint/no-unsafe-argument': 'warn',
+ '@typescript-eslint/no-unsafe-member-access': 'warn',
+ '@typescript-eslint/no-unsafe-call': 'warn',
+ '@typescript-eslint/no-unsafe-return': 'warn',
+ '@typescript-eslint/no-floating-promises': 'warn',
+ '@typescript-eslint/restrict-plus-operands': 'warn',
+ '@typescript-eslint/no-empty-function': 'warn',
+ },
+};
\ No newline at end of file
diff --git a/pyscriptjs/.prettierignore b/pyscriptjs/.prettierignore
new file mode 100644
index 0000000..55ec36d
--- /dev/null
+++ b/pyscriptjs/.prettierignore
@@ -0,0 +1,6 @@
+build
+node_modules
+
+
+# Ignore all HTML files
+*.html
\ No newline at end of file
diff --git a/pyscriptjs/.prettierrc.js b/pyscriptjs/.prettierrc.js
new file mode 100644
index 0000000..bafc660
--- /dev/null
+++ b/pyscriptjs/.prettierrc.js
@@ -0,0 +1,13 @@
+module.exports = {
+ arrowParens: 'avoid',
+ bracketSameLine: true,
+ singleQuote: true,
+ printWidth: 120,
+ plugins: ['prettier-plugin-svelte'],
+ semi: true,
+ svelteSortOrder: 'options-styles-scripts-markup',
+ svelteStrictMode: false,
+ svelteIndentScriptAndStyle: true,
+ tabWidth: 4,
+ trailingComma: 'all',
+}
\ No newline at end of file
diff --git a/pyscriptjs/package-lock.json b/pyscriptjs/package-lock.json
index 30e4ade..018b045 100644
--- a/pyscriptjs/package-lock.json
+++ b/pyscriptjs/package-lock.json
@@ -275,6 +275,23 @@
"w3c-keyname": "^2.2.4"
}
},
+ "@eslint/eslintrc": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz",
+ "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.3.1",
+ "globals": "^13.9.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.0.4",
+ "strip-json-comments": "^3.1.1"
+ }
+ },
"@fortawesome/fontawesome-common-types": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.1.tgz",
@@ -288,6 +305,23 @@
"@fortawesome/fontawesome-common-types": "6.1.1"
}
},
+ "@humanwhocodes/config-array": {
+ "version": "0.9.5",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
+ "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
"@lezer/common": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.12.tgz",
@@ -410,6 +444,12 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
+ "@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
"@types/node": {
"version": "17.0.23",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
@@ -446,12 +486,131 @@
"@types/node": "*"
}
},
+ "@typescript-eslint/eslint-plugin": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.20.0.tgz",
+ "integrity": "sha512-fapGzoxilCn3sBtC6NtXZX6+P/Hef7VDbyfGqTTpzYydwhlkevB+0vE0EnmHPVTVSy68GUncyJ/2PcrFBeCo5Q==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.20.0",
+ "@typescript-eslint/type-utils": "5.20.0",
+ "@typescript-eslint/utils": "5.20.0",
+ "debug": "^4.3.2",
+ "functional-red-black-tree": "^1.0.1",
+ "ignore": "^5.1.8",
+ "regexpp": "^3.2.0",
+ "semver": "^7.3.5",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.20.0.tgz",
+ "integrity": "sha512-UWKibrCZQCYvobmu3/N8TWbEeo/EPQbS41Ux1F9XqPzGuV7pfg6n50ZrFo6hryynD8qOTTfLHtHjjdQtxJ0h/w==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.20.0",
+ "@typescript-eslint/types": "5.20.0",
+ "@typescript-eslint/typescript-estree": "5.20.0",
+ "debug": "^4.3.2"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.20.0.tgz",
+ "integrity": "sha512-h9KtuPZ4D/JuX7rpp1iKg3zOH0WNEa+ZIXwpW/KWmEFDxlA/HSfCMhiyF1HS/drTICjIbpA6OqkAhrP/zkCStg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.20.0",
+ "@typescript-eslint/visitor-keys": "5.20.0"
+ }
+ },
+ "@typescript-eslint/type-utils": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.20.0.tgz",
+ "integrity": "sha512-WxNrCwYB3N/m8ceyoGCgbLmuZwupvzN0rE8NBuwnl7APgjv24ZJIjkNzoFBXPRCGzLNkoU/WfanW0exvp/+3Iw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/utils": "5.20.0",
+ "debug": "^4.3.2",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.20.0.tgz",
+ "integrity": "sha512-+d8wprF9GyvPwtoB4CxBAR/s0rpP25XKgnOvMf/gMXYDvlUC3rPFHupdTQ/ow9vn7UDe5rX02ovGYQbv/IUCbg==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.20.0.tgz",
+ "integrity": "sha512-36xLjP/+bXusLMrT9fMMYy1KJAGgHhlER2TqpUVDYUQg4w0q/NW/sg4UGAgVwAqb8V4zYg43KMUpM8vV2lve6w==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.20.0",
+ "@typescript-eslint/visitor-keys": "5.20.0",
+ "debug": "^4.3.2",
+ "globby": "^11.0.4",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.5",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.20.0.tgz",
+ "integrity": "sha512-lHONGJL1LIO12Ujyx8L8xKbwWSkoUKFSO+0wDAqGXiudWB2EO7WEUT+YZLtVbmOmSllAjLb9tpoIPwpRe5Tn6w==",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.9",
+ "@typescript-eslint/scope-manager": "5.20.0",
+ "@typescript-eslint/types": "5.20.0",
+ "@typescript-eslint/typescript-estree": "5.20.0",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^3.0.0"
+ },
+ "dependencies": {
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ }
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.20.0.tgz",
+ "integrity": "sha512-1flRpNF+0CAQkMNlTJ6L/Z5jiODG/e5+7mk6XwtPOUS3UrTz3UOiAg9jG2VtKsWI6rZQfy4C6a232QNRZTRGlg==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.20.0",
+ "eslint-visitor-keys": "^3.0.0"
+ }
+ },
"acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
"dev": true
},
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true
+ },
"acorn-node": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
@@ -469,6 +628,24 @@
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
"dev": true
},
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@@ -499,6 +676,12 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
"autoprefixer": {
"version": "10.4.4",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz",
@@ -732,6 +915,17 @@
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz",
"integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA=="
},
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
"css-color-names": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
@@ -750,6 +944,21 @@
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true
},
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
@@ -785,12 +994,30 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
"dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"dev": true
},
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
"electron-to-chromium": {
"version": "1.4.103",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.103.tgz",
@@ -824,12 +1051,215 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
+ "eslint": {
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz",
+ "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==",
+ "dev": true,
+ "requires": {
+ "@eslint/eslintrc": "^1.2.2",
+ "@humanwhocodes/config-array": "^0.9.2",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.3.1",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^6.0.1",
+ "globals": "^13.6.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "eslint-plugin-svelte3": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-3.4.1.tgz",
+ "integrity": "sha512-7p59WG8qV8L6wLdl4d/c3mdjkgVglQCdv5XOTk/iNPBKXuuV+Q0eFP5Wa6iJd/G2M1qR3BkLPEzaANOqKAZczw==",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true
+ },
+ "espree": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
+ "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
+ "dev": true,
+ "requires": {
+ "acorn": "^8.7.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
+ "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
+ "dev": true
+ }
+ }
+ },
+ "esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ },
"estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
"fast-glob": {
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
@@ -843,6 +1273,18 @@
"micromatch": "^4.0.4"
}
},
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
"fastq": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
@@ -852,6 +1294,15 @@
"reusify": "^1.0.4"
}
},
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -861,6 +1312,33 @@
"to-regex-range": "^5.0.1"
}
},
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "dependencies": {
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
+ }
+ },
+ "flatted": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
+ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
+ "dev": true
+ },
"fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -897,6 +1375,12 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
"get-port": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz",
@@ -925,6 +1409,29 @@
"is-glob": "^4.0.1"
}
},
+ "globals": {
+ "version": "13.13.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
+ "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
"graceful-fs": {
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
@@ -970,6 +1477,12 @@
"integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==",
"dev": true
},
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true
+ },
"import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -980,6 +1493,12 @@
"resolve-from": "^4.0.0"
}
},
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -1070,6 +1589,12 @@
"@types/estree": "*"
}
},
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
"jest-worker": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
@@ -1118,6 +1643,18 @@
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"dev": true
},
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
@@ -1133,6 +1670,16 @@
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="
},
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
"lilconfig": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
@@ -1174,12 +1721,27 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
"lodash.topath": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz",
"integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=",
"dev": true
},
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
"magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
@@ -1263,12 +1825,24 @@
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz",
"integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ=="
},
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
"nanoid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.2.tgz",
"integrity": "sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==",
"dev": true
},
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
"node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@@ -1317,6 +1891,20 @@
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
"dev": true
},
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
"opts": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz",
@@ -1350,6 +1938,12 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
"path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
@@ -1438,12 +2032,36 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "prettier": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz",
+ "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==",
+ "dev": true
+ },
+ "prettier-plugin-svelte": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-2.7.0.tgz",
+ "integrity": "sha512-fQhhZICprZot2IqEyoiUYLTRdumULGRvw0o4dzl5jt0jfzVWdGqeYW27QTWAeXhoupEZJULmNoH3ueJwUWFLIA==",
+ "dev": true
+ },
"pretty-hrtime": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
"dev": true
},
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
"purgecss": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.1.3.tgz",
@@ -1504,6 +2122,12 @@
}
}
},
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
"require-relative": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
@@ -1682,6 +2306,15 @@
"resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz",
"integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg=="
},
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
"serialize-javascript": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
@@ -1691,6 +2324,21 @@
"randombytes": "^2.1.0"
}
},
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
@@ -1733,6 +2381,12 @@
"tinydate": "^1.0.0"
}
},
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
"sorcery": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
@@ -1781,6 +2435,15 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
"strip-indent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
@@ -1790,6 +2453,12 @@
"min-indent": "^1.0.0"
}
},
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
"style-mod": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
@@ -2036,6 +2705,12 @@
}
}
},
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
"tinydate": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz",
@@ -2081,6 +2756,38 @@
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
"dev": true
},
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ }
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "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
+ },
"typescript": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
@@ -2093,17 +2800,47 @@
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
},
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
"w3c-keyname": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz",
"integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw=="
},
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -2121,6 +2858,12 @@
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"dev": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
}
}
}
diff --git a/pyscriptjs/package.json b/pyscriptjs/package.json
index ec97fbd..d1f39de 100644
--- a/pyscriptjs/package.json
+++ b/pyscriptjs/package.json
@@ -5,15 +5,26 @@
"build": "NODE_ENV=production rollup -c",
"dev": "rollup -c -w",
"start": "sirv public --no-clear --port 8080",
- "validate": "svelte-check"
+ "validate": "svelte-check",
+ "format:check": "prettier --check './src/**/*.{js,svelte,html,ts}'",
+ "format": "prettier --write './src/**/*.{js,svelte,html,ts}'",
+ "lint": "eslint './src/**/*.{js,svelte,html,ts}'",
+ "lint:fix": "eslint --fix './src/**/*.{js,svelte,html,ts}'",
+ "xprelint": "npm run format"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-typescript": "^8.1.0",
"@tsconfig/svelte": "^1.0.0",
+ "@typescript-eslint/eslint-plugin": "^5.20.0",
+ "@typescript-eslint/parser": "^5.20.0",
"autoprefixer": "^10.2.3",
+ "eslint": "^8.14.0",
+ "eslint-plugin-svelte3": "^3.4.1",
"postcss": "^8.2.4",
+ "prettier": "^2.6.2",
+ "prettier-plugin-svelte": "^2.7.0",
"rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
diff --git a/pyscriptjs/src/App.svelte b/pyscriptjs/src/App.svelte
index 7122ca7..781adc7 100644
--- a/pyscriptjs/src/App.svelte
+++ b/pyscriptjs/src/App.svelte
@@ -1,81 +1,84 @@
-
-
+
+
-
+
diff --git a/pyscriptjs/src/Tailwind.svelte b/pyscriptjs/src/Tailwind.svelte
index aedc87d..b7fa654 100644
--- a/pyscriptjs/src/Tailwind.svelte
+++ b/pyscriptjs/src/Tailwind.svelte
@@ -2,4 +2,4 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
-
\ No newline at end of file
+
diff --git a/pyscriptjs/src/components/base.ts b/pyscriptjs/src/components/base.ts
index 877745d..113beaa 100644
--- a/pyscriptjs/src/components/base.ts
+++ b/pyscriptjs/src/components/base.ts
@@ -1,4 +1,4 @@
-import { pyodideLoaded, loadedEnvironments, componentDetailsNavOpen, mode } from '../stores';
+import { componentDetailsNavOpen, loadedEnvironments, mode, pyodideLoaded } from '../stores';
import { guidGenerator } from '../utils';
// Premise used to connect to the first available pyodide interpreter
let pyodideReadyPromise;
@@ -7,7 +7,7 @@ let currentMode;
let Element;
pyodideLoaded.subscribe(value => {
- pyodideReadyPromise = value;
+ pyodideReadyPromise = value;
});
loadedEnvironments.subscribe(value => {
environments = value;
@@ -15,17 +15,17 @@ loadedEnvironments.subscribe(value => {
let propertiesNavOpen;
componentDetailsNavOpen.subscribe(value => {
- propertiesNavOpen = value;
+ propertiesNavOpen = value;
});
mode.subscribe(value => {
- currentMode = value;
+ currentMode = value;
});
// TODO: use type declaractions
type PyodideInterface = {
- registerJsModule(name: string, module: object): void
-}
+ registerJsModule(name: string, module: object): void;
+};
export class BaseEvalElement extends HTMLElement {
shadow: ShadowRoot;
@@ -37,142 +37,136 @@ export class BaseEvalElement extends HTMLElement {
outputElement: HTMLElement;
errorElement: HTMLElement;
theme: string;
-
+
constructor() {
super();
-
+
// attach shadow so we can preserve the element original innerHtml content
- this.shadow = this.attachShadow({ mode: 'open'});
+ this.shadow = this.attachShadow({ mode: 'open' });
this.wrapper = document.createElement('slot');
this.shadow.appendChild(this.wrapper);
}
addToOutput(s: string) {
- this.outputElement.innerHTML += "
"+s+"
";
+ this.outputElement.innerHTML += '' + s + '
';
this.outputElement.hidden = false;
- }
-
- postEvaluate(){
-
}
- checkId(){
- if (!this.id)
- this.id = this.constructor.name+"-"+guidGenerator();
+ postEvaluate() {}
+
+ checkId() {
+ if (!this.id) this.id = this.constructor.name + '-' + guidGenerator();
}
- getSourceFromElement(): string{
- return "";
+ getSourceFromElement(): string {
+ return '';
}
- async getSourceFromFile(s: string): Promise{
- let pyodide = await pyodideReadyPromise;
- let response = await fetch(s);
+ async getSourceFromFile(s: string): Promise {
+ const pyodide = await pyodideReadyPromise;
+ const response = await fetch(s);
this.code = await response.text();
return this.code;
- }
+ }
protected async _register_esm(pyodide: PyodideInterface): Promise {
- const imports: {[key: string]: unknown} = {}
-
+ const imports: { [key: string]: unknown } = {};
+
for (const node of document.querySelectorAll("script[type='importmap']")) {
- const importmap = (() => {
- try {
- return JSON.parse(node.textContent)
- } catch {
- return null
+ const importmap = (() => {
+ try {
+ return JSON.parse(node.textContent);
+ } catch {
+ return null;
+ }
+ })();
+
+ if (importmap?.imports == null) continue;
+
+ for (const [name, url] of Object.entries(importmap.imports)) {
+ if (typeof name != 'string' || typeof url != 'string') continue;
+
+ try {
+ // XXX: pyodide doesn't like Module(), failing with
+ // "can't read 'name' of undefined" at import time
+ imports[name] = { ...(await import(url)) };
+ } catch {
+ console.error(`failed to fetch '${url}' for '${name}'`);
+ }
}
- })()
-
- if (importmap?.imports == null)
- continue
-
- for (const [name, url] of Object.entries(importmap.imports)) {
- if (typeof name != "string" || typeof url != "string")
- continue
-
- try {
- // XXX: pyodide doesn't like Module(), failing with
- // "can't read 'name' of undefined" at import time
- imports[name] = {...await import(url)}
- } catch {
- console.error(`failed to fetch '${url}' for '${name}'`)
- }
- }
}
-
- pyodide.registerJsModule("esm", imports)
+
+ pyodide.registerJsModule('esm', imports);
}
async evaluate(): Promise {
console.log('evaluate');
- let pyodide = await pyodideReadyPromise;
+ const pyodide = await pyodideReadyPromise;
let source: string;
let output;
try {
- // @ts-ignore
- if (this.source){
+ if (this.source) {
source = await this.getSourceFromFile(this.source);
- }else{
+ } else {
source = this.getSourceFromElement();
}
await this._register_esm(pyodide);
- if (source.includes("asyncio")){
- await pyodide.runPythonAsync(`output_manager.change("`+this.outputElement.id+`", "`+this.errorElement.id+`")`);
+ if (source.includes('asyncio')) {
+ await pyodide.runPythonAsync(
+ `output_manager.change("` + this.outputElement.id + `", "` + this.errorElement.id + `")`,
+ );
output = await pyodide.runPythonAsync(source);
- await pyodide.runPythonAsync(`output_manager.revert()`)
- }else{
- output = pyodide.runPython(`output_manager.change("`+this.outputElement.id+`", "`+this.errorElement.id+`")`);
+ await pyodide.runPythonAsync(`output_manager.revert()`);
+ } else {
+ output = pyodide.runPython(
+ `output_manager.change("` + this.outputElement.id + `", "` + this.errorElement.id + `")`,
+ );
output = pyodide.runPython(source);
- pyodide.runPython(`output_manager.revert()`)
+ pyodide.runPython(`output_manager.revert()`);
}
- if (output !== undefined){
- if (Element === undefined){
+ if (output !== undefined) {
+ if (Element === undefined) {
Element = pyodide.globals.get('Element');
}
const out = Element(this.outputElement.id);
- // @ts-ignore
- out.write.callKwargs(output, { append : true});
+ out.write.callKwargs(output, { append: true });
- this.outputElement.hidden = false;
+ this.outputElement.hidden = false;
this.outputElement.style.display = 'block';
}
- this.postEvaluate()
-
+ this.postEvaluate();
} catch (err) {
- if (Element === undefined){
+ if (Element === undefined) {
Element = pyodide.globals.get('Element');
}
const out = Element(this.errorElement.id);
- // @ts-ignore
- out.write.callKwargs(err, { append : true});
+ out.write.callKwargs(err, { append: true });
this.errorElement.hidden = false;
this.errorElement.style.display = 'block';
- }
- } // end evaluate
+ }
+ } // end evaluate
- async eval(source: string): Promise {
+ async eval(source: string): Promise {
let output;
- let pyodide = await pyodideReadyPromise;
-
- try{
+ const pyodide = await pyodideReadyPromise;
+
+ try {
output = await pyodide.runPythonAsync(source);
- if (output !== undefined){ console.log(output); }
+ if (output !== undefined) {
+ console.log(output);
+ }
} catch (err) {
console.log(err);
}
} // end eval
- }
+}
-
-
- function createWidget(name: string, code: string, klass: string){
-
- class CustomWidget extends HTMLElement{
+function createWidget(name: string, code: string, klass: string) {
+ class CustomWidget extends HTMLElement {
shadow: ShadowRoot;
wrapper: HTMLElement;
@@ -183,13 +177,13 @@ export class BaseEvalElement extends HTMLElement {
proxyClass: any;
constructor() {
- super();
-
- // attach shadow so we can preserve the element original innerHtml content
- this.shadow = this.attachShadow({ mode: 'open'});
-
- this.wrapper = document.createElement('slot');
- this.shadow.appendChild(this.wrapper);
+ super();
+
+ // attach shadow so we can preserve the element original innerHtml content
+ this.shadow = this.attachShadow({ mode: 'open' });
+
+ this.wrapper = document.createElement('slot');
+ this.shadow.appendChild(this.wrapper);
}
connectedCallback() {
@@ -207,19 +201,19 @@ export class BaseEvalElement extends HTMLElement {
}, 2000);
}
- async registerWidget(){
- let pyodide = await pyodideReadyPromise;
+ async registerWidget() {
+ const pyodide = await pyodideReadyPromise;
console.log('new widget registered:', this.name);
pyodide.globals.set(this.id, this.proxy);
}
async eval(source: string): Promise {
let output;
- let pyodide = await pyodideReadyPromise;
- try{
+ const pyodide = await pyodideReadyPromise;
+ try {
output = await pyodide.runPythonAsync(source);
this.proxyClass = pyodide.globals.get(this.klass);
- if (output !== undefined){
+ if (output !== undefined) {
console.log(output);
}
} catch (err) {
@@ -227,10 +221,10 @@ export class BaseEvalElement extends HTMLElement {
}
}
}
- let xPyWidget = customElements.define(name, CustomWidget);
- }
+ const xPyWidget = customElements.define(name, CustomWidget);
+}
- export class PyWidget extends HTMLElement {
+export class PyWidget extends HTMLElement {
shadow: ShadowRoot;
name: string;
klass: string;
@@ -240,43 +234,45 @@ export class BaseEvalElement extends HTMLElement {
theme: string;
source: string;
code: string;
-
+
constructor() {
super();
-
+
// attach shadow so we can preserve the element original innerHtml content
- this.shadow = this.attachShadow({ mode: 'open'});
-
+ this.shadow = this.attachShadow({ mode: 'open' });
+
this.wrapper = document.createElement('slot');
this.shadow.appendChild(this.wrapper);
if (this.hasAttribute('src')) {
- this.source = this.getAttribute('src');
+ this.source = this.getAttribute('src');
}
if (this.hasAttribute('name')) {
- this.name = this.getAttribute('name');
+ this.name = this.getAttribute('name');
}
if (this.hasAttribute('klass')) {
- this.klass = this.getAttribute('klass');
+ this.klass = this.getAttribute('klass');
}
- }
+ }
connectedCallback() {
- if (this.id === undefined){
- throw new ReferenceError(`No id specified for component. Components must have an explicit id. Please use id="" to specify your component id.`)
- return;
- }
+ if (this.id === undefined) {
+ throw new ReferenceError(
+ `No id specified for component. Components must have an explicit id. Please use id="" to specify your component id.`,
+ );
+ return;
+ }
- let mainDiv = document.createElement('div');
- mainDiv.id = this.id + '-main';
- this.appendChild(mainDiv);
- console.log('reading source')
- this.getSourceFromFile(this.source).then((code:string) => {
- this.code = code;
- createWidget(this.name, code, this.klass);
- });
+ const mainDiv = document.createElement('div');
+ mainDiv.id = this.id + '-main';
+ this.appendChild(mainDiv);
+ console.log('reading source');
+ this.getSourceFromFile(this.source).then((code: string) => {
+ this.code = code;
+ createWidget(this.name, code, this.klass);
+ });
}
initOutErr(): void {
@@ -287,42 +283,42 @@ export class BaseEvalElement extends HTMLElement {
if (!this.hasAttribute('output-mode')) {
this.setAttribute('output-mode', 'append');
}
- }else{
- if (this.hasAttribute('std-out')){
+ } else {
+ if (this.hasAttribute('std-out')) {
this.outputElement = document.getElementById(this.getAttribute('std-out'));
- }else{
+ } else {
// In this case neither output or std-out have been provided so we need
// to create a new output div to output to
this.outputElement = document.createElement('div');
- this.outputElement.classList.add("output");
+ this.outputElement.classList.add('output');
this.outputElement.hidden = true;
- this.outputElement.id = this.id + "-" + this.getAttribute("exec-id");
+ this.outputElement.id = this.id + '-' + this.getAttribute('exec-id');
}
- if (this.hasAttribute('std-err')){
+ if (this.hasAttribute('std-err')) {
this.outputElement = document.getElementById(this.getAttribute('std-err'));
- }else{
+ } else {
this.errorElement = this.outputElement;
}
}
}
- async getSourceFromFile(s: string): Promise{
- let pyodide = await pyodideReadyPromise;
- let response = await fetch(s);
+ async getSourceFromFile(s: string): Promise {
+ const pyodide = await pyodideReadyPromise;
+ const response = await fetch(s);
return await response.text();
}
-
+
async eval(source: string): Promise {
let output;
- let pyodide = await pyodideReadyPromise;
- try{
+ const pyodide = await pyodideReadyPromise;
+ try {
output = await pyodide.runPythonAsync(source);
- if (output !== undefined){
+ if (output !== undefined) {
console.log(output);
}
} catch (err) {
console.log(err);
}
}
- }
+}
diff --git a/pyscriptjs/src/components/pybox.ts b/pyscriptjs/src/components/pybox.ts
index acd27e5..124360f 100644
--- a/pyscriptjs/src/components/pybox.ts
+++ b/pyscriptjs/src/components/pybox.ts
@@ -5,65 +5,62 @@ export class PyBox extends HTMLElement {
wrapper: HTMLElement;
theme: string;
widths: Array;
-
+
constructor() {
super();
-
+
// attach shadow so we can preserve the element original innerHtml content
- this.shadow = this.attachShadow({ mode: 'open'});
-
+ this.shadow = this.attachShadow({ mode: 'open' });
+
this.wrapper = document.createElement('slot');
this.shadow.appendChild(this.wrapper);
- }
-
+ }
connectedCallback() {
- let mainDiv = document.createElement('div');
- addClasses(mainDiv, ["flex", "mx-8"])
-
- // Hack: for some reason when moving children, the editor box duplicates children
- // meaning that we end up with 2 editors, if there's a inside the
- // so, if we have more than 2 children with the cm-editor class, we remove one of them
- while (this.childNodes.length > 0) {
- console.log(this.firstChild);
- if ( this.firstChild.nodeName == "PY-REPL" ){
- // in this case we need to remove the child and craete a new one from scratch
- let replDiv = document.createElement('div');
- // we need to put the new repl inside a div so that if the repl has auto-generate true
- // it can replicate itself inside that constrained div
- replDiv.appendChild(this.firstChild.cloneNode());
- mainDiv.appendChild(replDiv);
- this.firstChild.remove();
- }
- else{
- if ( this.firstChild.nodeName != "#text" ){
- mainDiv.appendChild(this.firstChild);
- }else{
- this.firstChild.remove()
- }
- }
- }
+ const mainDiv = document.createElement('div');
+ addClasses(mainDiv, ['flex', 'mx-8']);
- // now we need to set widths
- this.widths = []
- if (this.hasAttribute('widths')) {
- for (let w of this.getAttribute('widths').split(";")) {
- this.widths.push(`w-${w}`);
+ // Hack: for some reason when moving children, the editor box duplicates children
+ // meaning that we end up with 2 editors, if there's a inside the
+ // so, if we have more than 2 children with the cm-editor class, we remove one of them
+ while (this.childNodes.length > 0) {
+ console.log(this.firstChild);
+ if (this.firstChild.nodeName == 'PY-REPL') {
+ // in this case we need to remove the child and craete a new one from scratch
+ const replDiv = document.createElement('div');
+ // we need to put the new repl inside a div so that if the repl has auto-generate true
+ // it can replicate itself inside that constrained div
+ replDiv.appendChild(this.firstChild.cloneNode());
+ mainDiv.appendChild(replDiv);
+ this.firstChild.remove();
+ } else {
+ if (this.firstChild.nodeName != '#text') {
+ mainDiv.appendChild(this.firstChild);
+ } else {
+ this.firstChild.remove();
+ }
+ }
}
- }else{
- for (let el of mainDiv.childNodes) {
- this.widths.push(`w-1/${mainDiv.childNodes.length}`);
+
+ // now we need to set widths
+ this.widths = [];
+ if (this.hasAttribute('widths')) {
+ for (const w of this.getAttribute('widths').split(';')) {
+ this.widths.push(`w-${w}`);
+ }
+ } else {
+ for (const el of mainDiv.childNodes) {
+ this.widths.push(`w-1/${mainDiv.childNodes.length}`);
+ }
}
- }
- for (let i in this.widths) {
- // @ts-ignore
- addClasses(mainDiv.childNodes[parseInt(i)], [this.widths[i], 'mx-4']);
- }
+ this.widths.forEach((width, index)=>{
+ const node: ChildNode = mainDiv.childNodes[index];
+ addClasses(node, [width, 'mx-4'])
- this.appendChild(mainDiv);
- console.log('py-box connected');
+ })
+
+ this.appendChild(mainDiv);
+ console.log('py-box connected');
}
- }
-
-
\ No newline at end of file
+}
diff --git a/pyscriptjs/src/components/pybutton.ts b/pyscriptjs/src/components/pybutton.ts
index 426b537..ad54f9b 100644
--- a/pyscriptjs/src/components/pybutton.ts
+++ b/pyscriptjs/src/components/pybutton.ts
@@ -10,47 +10,47 @@ export class PyButton extends BaseEvalElement {
mount_name: string;
constructor() {
super();
-
+
if (this.hasAttribute('label')) {
- this.label = this.getAttribute('label');
+ this.label = this.getAttribute('label');
}
- }
+ }
connectedCallback() {
- this.code = htmlDecode(this.innerHTML);
- this.mount_name = this.id.split("-").join("_");
- this.innerHTML = '';
-
- let mainDiv = document.createElement('button');
- mainDiv.innerHTML = this.label;
- addClasses(mainDiv, ["p-2", "text-white", "bg-blue-600", "border", "border-blue-600", "rounded"]);
-
- mainDiv.id = this.id;
- this.id = `${this.id}-container`;
+ this.code = htmlDecode(this.innerHTML);
+ this.mount_name = this.id.split('-').join('_');
+ this.innerHTML = '';
- this.appendChild(mainDiv);
- this.code = this.code.split("self").join(this.mount_name);
- let registrationCode = `${this.mount_name} = Element("${ mainDiv.id }")`;
- if (this.code.includes("def on_focus")){
- this.code = this.code.replace("def on_focus", `def on_focus_${this.mount_name}`);
- registrationCode += `\n${this.mount_name}.element.onfocus = on_focus_${this.mount_name}`
- }
+ const mainDiv = document.createElement('button');
+ mainDiv.innerHTML = this.label;
+ addClasses(mainDiv, ['p-2', 'text-white', 'bg-blue-600', 'border', 'border-blue-600', 'rounded']);
- if (this.code.includes("def on_click")){
- this.code = this.code.replace("def on_click", `def on_click_${this.mount_name}`);
- registrationCode += `\n${this.mount_name}.element.onclick = on_click_${this.mount_name}`
- }
-
- // now that we appended and the element is attached, lets connect with the event handlers
- // defined for this widget
- setTimeout(() => {
- this.eval(this.code).then(() => {
- this.eval(registrationCode).then(() => {
- console.log('registered handlers');
- });
- });
- }, 4000);
-
- console.log('py-button connected');
+ mainDiv.id = this.id;
+ this.id = `${this.id}-container`;
+
+ this.appendChild(mainDiv);
+ this.code = this.code.split('self').join(this.mount_name);
+ let registrationCode = `${this.mount_name} = Element("${mainDiv.id}")`;
+ if (this.code.includes('def on_focus')) {
+ this.code = this.code.replace('def on_focus', `def on_focus_${this.mount_name}`);
+ registrationCode += `\n${this.mount_name}.element.onfocus = on_focus_${this.mount_name}`;
+ }
+
+ if (this.code.includes('def on_click')) {
+ this.code = this.code.replace('def on_click', `def on_click_${this.mount_name}`);
+ registrationCode += `\n${this.mount_name}.element.onclick = on_click_${this.mount_name}`;
+ }
+
+ // now that we appended and the element is attached, lets connect with the event handlers
+ // defined for this widget
+ setTimeout(() => {
+ this.eval(this.code).then(() => {
+ this.eval(registrationCode).then(() => {
+ console.log('registered handlers');
+ });
+ });
+ }, 4000);
+
+ console.log('py-button connected');
}
- }
+}
diff --git a/pyscriptjs/src/components/pyenv.ts b/pyscriptjs/src/components/pyenv.ts
index c2f964c..ec924f8 100644
--- a/pyscriptjs/src/components/pyenv.ts
+++ b/pyscriptjs/src/components/pyenv.ts
@@ -9,68 +9,65 @@ let environments;
let currentMode;
pyodideLoaded.subscribe(value => {
- pyodideReadyPromise = value;
+ pyodideReadyPromise = value;
});
loadedEnvironments.subscribe(value => {
- environments = value;
+ environments = value;
});
mode.subscribe(value => {
- currentMode = value;
+ currentMode = value;
});
export class PyEnv extends HTMLElement {
- shadow: ShadowRoot;
- wrapper: HTMLElement;
- code: string;
- environment: any;
+ shadow: ShadowRoot;
+ wrapper: HTMLElement;
+ code: string;
+ environment: any;
- constructor() {
- super();
+ constructor() {
+ super();
- this.shadow = this.attachShadow({ mode: 'open'});
- this.wrapper = document.createElement('slot');
- }
+ this.shadow = this.attachShadow({ mode: 'open' });
+ this.wrapper = document.createElement('slot');
+ }
- connectedCallback() {
- this.code = this.innerHTML;
- this.innerHTML = '';
+ connectedCallback() {
+ this.code = this.innerHTML;
+ this.innerHTML = '';
- let env = [];
- let paths = [];
+ const env = [];
+ const paths = [];
- this.environment = jsyaml.load(this.code);
- if (this.environment === undefined)
- return
+ this.environment = jsyaml.load(this.code);
+ if (this.environment === undefined) return;
- for (let entry of this.environment) {
- if (typeof entry == "string" ){
- env.push(entry);
- }
- else if (entry.hasOwnProperty('paths')){
- for (let path of entry.paths) {
- paths.push(path);
+ for (const entry of this.environment) {
+ if (typeof entry == 'string') {
+ env.push(entry);
+ } else if (entry.hasOwnProperty('paths')) {
+ for (const path of entry.paths) {
+ paths.push(path);
+ }
+ }
}
- }
- }
- async function loadEnv() {
- let pyodide = await pyodideReadyPromise;
- await loadPackage(env, pyodide);
- console.log("enviroment loaded")
- }
+ async function loadEnv() {
+ const pyodide = await pyodideReadyPromise;
+ await loadPackage(env, pyodide);
+ console.log('enviroment loaded');
+ }
- async function loadPaths() {
- let pyodide = await pyodideReadyPromise;
- for (let singleFile of paths) {
- await loadFromFile(singleFile, pyodide);
- }
- console.log("paths loaded")
+ async function loadPaths() {
+ const pyodide = await pyodideReadyPromise;
+ for (const singleFile of paths) {
+ await loadFromFile(singleFile, pyodide);
+ }
+ console.log('paths loaded');
+ }
+ addInitializer(loadEnv);
+ addInitializer(loadPaths);
+ console.log('enviroment loading...', env);
}
- addInitializer(loadEnv);
- addInitializer(loadPaths);
- console.log("enviroment loading...", env)
-
- }
}
diff --git a/pyscriptjs/src/components/pyinputbox.ts b/pyscriptjs/src/components/pyinputbox.ts
index 58fec14..9fbc73e 100644
--- a/pyscriptjs/src/components/pyinputbox.ts
+++ b/pyscriptjs/src/components/pyinputbox.ts
@@ -9,46 +9,44 @@ export class PyInputBox extends BaseEvalElement {
label: string;
mount_name: string;
constructor() {
- super();
+ super();
- if (this.hasAttribute('label')) {
- this.label = this.getAttribute('label');
- }
+ if (this.hasAttribute('label')) {
+ this.label = this.getAttribute('label');
+ }
}
connectedCallback() {
- this.code = htmlDecode(this.innerHTML);
- this.mount_name = this.id.split("-").join("_");
- this.innerHTML = '';
-
- let mainDiv = document.createElement('input');
- mainDiv.type = "text";
- addClasses(mainDiv, ["border", "flex-1", "w-full", "mr-3", "border-gray-300", "p-2", "rounded"]);
+ this.code = htmlDecode(this.innerHTML);
+ this.mount_name = this.id.split('-').join('_');
+ this.innerHTML = '';
- mainDiv.id = this.id;
- this.id = `${this.id}-container`;
- this.appendChild(mainDiv);
+ const mainDiv = document.createElement('input');
+ mainDiv.type = 'text';
+ addClasses(mainDiv, ['border', 'flex-1', 'w-full', 'mr-3', 'border-gray-300', 'p-2', 'rounded']);
- // now that we appended and the element is attached, lets connect with the event handlers
- // defined for this widget
- this.appendChild(mainDiv);
- this.code = this.code.split("self").join(this.mount_name);
- let registrationCode = `${this.mount_name} = Element("${ mainDiv.id }")`;
- if (this.code.includes("def on_keypress")){
- this.code = this.code.replace("def on_keypress", `def on_keypress_${this.mount_name}`);
- registrationCode += `\n${this.mount_name}.element.onkeypress = on_keypress_${this.mount_name}`
- }
+ mainDiv.id = this.id;
+ this.id = `${this.id}-container`;
+ this.appendChild(mainDiv);
- // TODO: For now we delay execution to allow pyodide to load but in the future this
- // should really wait for it to load..
- setTimeout(() => {
- this.eval(this.code).then(() => {
- this.eval(registrationCode).then(() => {
- console.log('registered handlers');
- });
- });
+ // now that we appended and the element is attached, lets connect with the event handlers
+ // defined for this widget
+ this.appendChild(mainDiv);
+ this.code = this.code.split('self').join(this.mount_name);
+ let registrationCode = `${this.mount_name} = Element("${mainDiv.id}")`;
+ if (this.code.includes('def on_keypress')) {
+ this.code = this.code.replace('def on_keypress', `def on_keypress_${this.mount_name}`);
+ registrationCode += `\n${this.mount_name}.element.onkeypress = on_keypress_${this.mount_name}`;
+ }
+
+ // TODO: For now we delay execution to allow pyodide to load but in the future this
+ // should really wait for it to load..
+ setTimeout(() => {
+ this.eval(this.code).then(() => {
+ this.eval(registrationCode).then(() => {
+ console.log('registered handlers');
+ });
+ });
}, 4000);
}
- }
-
-
\ No newline at end of file
+}
diff --git a/pyscriptjs/src/components/pyrepl.ts b/pyscriptjs/src/components/pyrepl.ts
index 621d224..beedbd1 100644
--- a/pyscriptjs/src/components/pyrepl.ts
+++ b/pyscriptjs/src/components/pyrepl.ts
@@ -1,12 +1,11 @@
-import {EditorState, EditorView, basicSetup} from "@codemirror/basic-setup"
-import { python } from "@codemirror/lang-python"
-// @ts-ignore
-import { StateCommand, Compartment } from '@codemirror/state';
-import { keymap, ViewUpdate } from "@codemirror/view";
-import { defaultKeymap } from "@codemirror/commands";
-import { oneDarkTheme } from "@codemirror/theme-one-dark";
+import { basicSetup, EditorState, EditorView } from '@codemirror/basic-setup';
+import { python } from '@codemirror/lang-python';
+import { Compartment, StateCommand } from '@codemirror/state';
+import { keymap } from '@codemirror/view';
+import { defaultKeymap } from '@codemirror/commands';
+import { oneDarkTheme } from '@codemirror/theme-one-dark';
-import { pyodideLoaded, loadedEnvironments, componentDetailsNavOpen, currentComponentDetails, mode } from '../stores';
+import { componentDetailsNavOpen, currentComponentDetails, loadedEnvironments, mode, pyodideLoaded } from '../stores';
import { addClasses } from '../utils';
import { BaseEvalElement } from './base';
@@ -16,7 +15,7 @@ let environments;
let currentMode;
pyodideLoaded.subscribe(value => {
- pyodideReadyPromise = value;
+ pyodideReadyPromise = value;
});
loadedEnvironments.subscribe(value => {
environments = value;
@@ -24,216 +23,230 @@ loadedEnvironments.subscribe(value => {
let propertiesNavOpen;
componentDetailsNavOpen.subscribe(value => {
- propertiesNavOpen = value;
+ propertiesNavOpen = value;
});
mode.subscribe(value => {
- currentMode = value;
+ currentMode = value;
});
+const languageConf = new Compartment();
-const languageConf = new Compartment
-
-function createCmdHandler(el){
+function createCmdHandler(el) {
// Creates a codemirror cmd handler that calls the el.evaluate when an event
// triggers that specific cmd
- const toggleCheckbox:StateCommand = ({ state, dispatch }) => {
- return el.evaluate(state)
- }
- return toggleCheckbox
+ const toggleCheckbox: StateCommand = ({ state, dispatch }) => {
+ return el.evaluate(state);
+ };
+ return toggleCheckbox;
}
-
export class PyRepl extends BaseEvalElement {
editor: EditorView;
editorNode: HTMLElement;
-
+
constructor() {
super();
-
+
// add an extra div where we can attach the codemirror editor
this.editorNode = document.createElement('div');
- addClasses(this.editorNode, ["editor-box"])
+ addClasses(this.editorNode, ['editor-box']);
this.shadow.appendChild(this.wrapper);
- }
-
+ }
connectedCallback() {
- this.checkId()
- this.code = this.innerHTML;
- this.innerHTML = '';
+ this.checkId();
+ this.code = this.innerHTML;
+ this.innerHTML = '';
- let extensions = [
- basicSetup,
- languageConf.of(python()),
- keymap.of([
+ const extensions = [
+ basicSetup,
+ languageConf.of(python()),
+ keymap.of([
...defaultKeymap,
- { key: "Ctrl-Enter", run: createCmdHandler(this) },
- { key: "Shift-Enter", run: createCmdHandler(this) }
- ]),
+ { key: 'Ctrl-Enter', run: createCmdHandler(this) },
+ { key: 'Shift-Enter', run: createCmdHandler(this) },
+ ]),
- // Event listener function that is called every time an user types something on this editor
- // EditorView.updateListener.of((v:ViewUpdate) => {
- // if (v.docChanged) {
- // console.log(v.changes);
+ // Event listener function that is called every time an user types something on this editor
+ // EditorView.updateListener.of((v:ViewUpdate) => {
+ // if (v.docChanged) {
+ // console.log(v.changes);
+
+ // }
+ // })
+ ];
- // }
- // })
- ];
-
if (!this.hasAttribute('theme')) {
- this.theme = this.getAttribute('theme');
- if (this.theme == 'dark'){
- extensions.push(oneDarkTheme);
- }
- }
-
- let startState = EditorState.create({
- doc: this.code.trim(),
- extensions: extensions
- })
-
- this.editor = new EditorView({
- state: startState,
- parent: this.editorNode
- })
-
- let mainDiv = document.createElement('div');
- addClasses(mainDiv, ["parentBox", "group", "flex", "flex-col", "mt-2", "border-2", "border-gray-200", "rounded-lg", "mx-8"])
- // add Editor to main PyScript div
-
- // Butons DIV
- var eDiv = document.createElement('div');
- addClasses(eDiv, "buttons-box opacity-0 group-hover:opacity-100 relative top-0 right-0 flex flex-row-reverse space-x-reverse space-x-4 font-mono text-white text-sm font-bold leading-6 dev-buttons-group".split(" "))
- eDiv.setAttribute("role", "group");
-
- // Play Button
- this.btnRun = document.createElement('button');
- this.btnRun.innerHTML = '';
- let buttonClasses = ["mr-2", "block", "py-2", "px-4", "rounded-full"];
- addClasses(this.btnRun, buttonClasses);
- addClasses(this.btnRun, ["bg-green-500"])
- eDiv.appendChild(this.btnRun);
-
- this.btnRun.onclick = wrap(this);
-
- function wrap(el: any){
- async function evaluatePython() {
- el.evaluate()
- }
- return evaluatePython;
- }
-
- // Settings button
- this.btnConfig = document.createElement('button');
- this.btnConfig.innerHTML = '';
- this.btnConfig.onclick = function toggleNavBar(evt){
- console.log('clicked');
- componentDetailsNavOpen.set(!propertiesNavOpen);
-
- currentComponentDetails.set([
- {key: "auto-generate", value: true},
- {key:"output", value: "default"},
- {key: "source", value: "self"},
- {key: "output-mode", value: "clear"}
- ])
- }
-
- addClasses(this.btnConfig, buttonClasses);
- addClasses(this.btnConfig, ["bg-blue-500"])
- eDiv.appendChild(this.btnConfig);
-
-
- mainDiv.appendChild(eDiv);
- mainDiv.appendChild(this.editorNode);
-
- if (!this.id){
- console.log("WARNING: define with an id. should always have an id. More than one on a page won't work otherwise!")
- }
-
- if (!this.hasAttribute('exec-id')) {
- this.setAttribute("exec-id", "1");
- }
-
- if (!this.hasAttribute('root')) {
- this.setAttribute("root", this.id);
- }
-
- if (this.hasAttribute('output')) {
- this.errorElement = this.outputElement = document.getElementById(this.getAttribute('output'));
-
- // in this case, the default output-mode is append, if hasn't been specified
- if (!this.hasAttribute('output-mode')) {
- this.setAttribute('output-mode', 'append');
- }
- }else{
- if (this.hasAttribute('std-out')){
- this.outputElement = document.getElementById(this.getAttribute('std-out'));
- }else{
- // In this case neither output or std-out have been provided so we need
- // to create a new output div to output to
- this.outputElement = document.createElement('div');
- this.outputElement.classList.add("output");
- this.outputElement.hidden = true;
- this.outputElement.id = this.id + "-" + this.getAttribute("exec-id");
-
- // add the output div id if there's not output pre-defined
- mainDiv.appendChild(this.outputElement);
+ this.theme = this.getAttribute('theme');
+ if (this.theme == 'dark') {
+ extensions.push(oneDarkTheme);
+ }
}
- if (this.hasAttribute('std-err')){
- this.errorElement = document.getElementById(this.getAttribute('std-err'));
- }else{
- this.errorElement = this.outputElement;
+ const startState = EditorState.create({
+ doc: this.code.trim(),
+ extensions: extensions,
+ });
+
+ this.editor = new EditorView({
+ state: startState,
+ parent: this.editorNode,
+ });
+
+ const mainDiv = document.createElement('div');
+ addClasses(mainDiv, [
+ 'parentBox',
+ 'group',
+ 'flex',
+ 'flex-col',
+ 'mt-2',
+ 'border-2',
+ 'border-gray-200',
+ 'rounded-lg',
+ 'mx-8',
+ ]);
+ // add Editor to main PyScript div
+
+ // Butons DIV
+ const eDiv = document.createElement('div');
+ addClasses(
+ eDiv,
+ 'buttons-box opacity-0 group-hover:opacity-100 relative top-0 right-0 flex flex-row-reverse space-x-reverse space-x-4 font-mono text-white text-sm font-bold leading-6 dev-buttons-group'.split(
+ ' ',
+ ),
+ );
+ eDiv.setAttribute('role', 'group');
+
+ // Play Button
+ this.btnRun = document.createElement('button');
+ this.btnRun.innerHTML =
+ '';
+ const buttonClasses = ['mr-2', 'block', 'py-2', 'px-4', 'rounded-full'];
+ addClasses(this.btnRun, buttonClasses);
+ addClasses(this.btnRun, ['bg-green-500']);
+ eDiv.appendChild(this.btnRun);
+
+ this.btnRun.onclick = wrap(this);
+
+ function wrap(el: any) {
+ async function evaluatePython() {
+ await el.evaluate();
+ }
+
+ return evaluatePython;
}
- }
+ // Settings button
+ this.btnConfig = document.createElement('button');
+ this.btnConfig.innerHTML =
+ '';
+ this.btnConfig.onclick = function toggleNavBar(evt) {
+ console.log('clicked');
+ componentDetailsNavOpen.set(!propertiesNavOpen);
- this.appendChild(mainDiv);
- this.editor.focus();
- console.log('connected');
+ currentComponentDetails.set([
+ { key: 'auto-generate', value: true },
+ { key: 'output', value: 'default' },
+ { key: 'source', value: 'self' },
+ { key: 'output-mode', value: 'clear' },
+ ]);
+ };
+
+ addClasses(this.btnConfig, buttonClasses);
+ addClasses(this.btnConfig, ['bg-blue-500']);
+ eDiv.appendChild(this.btnConfig);
+
+ mainDiv.appendChild(eDiv);
+ mainDiv.appendChild(this.editorNode);
+
+ if (!this.id) {
+ console.log(
+ 'WARNING: define with an id. should always have an id. More than one on a page won\'t work otherwise!',
+ );
+ }
+
+ if (!this.hasAttribute('exec-id')) {
+ this.setAttribute('exec-id', '1');
+ }
+
+ if (!this.hasAttribute('root')) {
+ this.setAttribute('root', this.id);
+ }
+
+ if (this.hasAttribute('output')) {
+ this.errorElement = this.outputElement = document.getElementById(this.getAttribute('output'));
+
+ // in this case, the default output-mode is append, if hasn't been specified
+ if (!this.hasAttribute('output-mode')) {
+ this.setAttribute('output-mode', 'append');
+ }
+ } else {
+ if (this.hasAttribute('std-out')) {
+ this.outputElement = document.getElementById(this.getAttribute('std-out'));
+ } else {
+ // In this case neither output or std-out have been provided so we need
+ // to create a new output div to output to
+ this.outputElement = document.createElement('div');
+ this.outputElement.classList.add('output');
+ this.outputElement.hidden = true;
+ this.outputElement.id = this.id + '-' + this.getAttribute('exec-id');
+
+ // add the output div id if there's not output pre-defined
+ mainDiv.appendChild(this.outputElement);
+ }
+
+ if (this.hasAttribute('std-err')) {
+ this.errorElement = document.getElementById(this.getAttribute('std-err'));
+ } else {
+ this.errorElement = this.outputElement;
+ }
+ }
+
+ this.appendChild(mainDiv);
+ this.editor.focus();
+ console.log('connected');
}
addToOutput(s: string) {
- this.outputElement.innerHTML += ""+s+"
";
+ this.outputElement.innerHTML += '' + s + '
';
this.outputElement.hidden = false;
- }
+ }
postEvaluate(): void {
+ this.outputElement.hidden = false;
+ this.outputElement.style.display = 'block';
- this.outputElement.hidden = false;
- this.outputElement.style.display = 'block';
+ if (this.hasAttribute('auto-generate')) {
+ const nextExecId = parseInt(this.getAttribute('exec-id')) + 1;
+ const newPyRepl = document.createElement('py-repl');
+ newPyRepl.setAttribute('root', this.getAttribute('root'));
+ newPyRepl.id = this.getAttribute('root') + '-' + nextExecId.toString();
+ newPyRepl.setAttribute('auto-generate', null);
+ if (this.hasAttribute('output')) {
+ newPyRepl.setAttribute('output', this.getAttribute('output'));
+ }
+ if (this.hasAttribute('std-out')) {
+ newPyRepl.setAttribute('std-out', this.getAttribute('std-out'));
+ }
+ if (this.hasAttribute('std-err')) {
+ newPyRepl.setAttribute('std-err', this.getAttribute('std-err'));
+ }
- if (this.hasAttribute('auto-generate')) {
- let nextExecId = parseInt(this.getAttribute('exec-id')) + 1;
- const newPyRepl = document.createElement("py-repl");
- newPyRepl.setAttribute('root', this.getAttribute('root'));
- newPyRepl.id = this.getAttribute('root') + "-" + nextExecId.toString();
- newPyRepl.setAttribute('auto-generate', null);
- if (this.hasAttribute('output')){
- newPyRepl.setAttribute('output', this.getAttribute('output'));
+ newPyRepl.setAttribute('exec-id', nextExecId.toString());
+ this.parentElement.appendChild(newPyRepl);
}
- if (this.hasAttribute('std-out')){
- newPyRepl.setAttribute('std-out', this.getAttribute('std-out'));
- }
- if (this.hasAttribute('std-err')){
- newPyRepl.setAttribute('std-err', this.getAttribute('std-err'));
- }
-
- newPyRepl.setAttribute('exec-id', nextExecId.toString());
- this.parentElement.appendChild(newPyRepl);
- }
}
getSourceFromElement(): string {
- const sourceStrings = [`output_manager.change("`+this.outputElement.id+`")`,
- ...this.editor.state.doc.toString().split("\n")];
- return sourceStrings.join('\n')
+ const sourceStrings = [
+ `output_manager.change("` + this.outputElement.id + `")`,
+ ...this.editor.state.doc.toString().split('\n'),
+ ];
+ return sourceStrings.join('\n');
}
- render(){
- console.log('rendered');
-
+ render() {
+ console.log('rendered');
}
- }
-
+}
diff --git a/pyscriptjs/src/components/pyscript.ts b/pyscriptjs/src/components/pyscript.ts
index 8b7aacc..61267e6 100644
--- a/pyscriptjs/src/components/pyscript.ts
+++ b/pyscriptjs/src/components/pyscript.ts
@@ -1,12 +1,19 @@
-import {EditorState, EditorView, basicSetup} from "@codemirror/basic-setup"
-import { python } from "@codemirror/lang-python"
-// @ts-ignore
+import { EditorState } from '@codemirror/basic-setup';
+import { python } from '@codemirror/lang-python';
import { StateCommand } from '@codemirror/state';
-import { keymap, ViewUpdate } from "@codemirror/view";
-import { defaultKeymap } from "@codemirror/commands";
-import { oneDarkTheme } from "@codemirror/theme-one-dark";
+import { keymap } from '@codemirror/view';
+import { defaultKeymap } from '@codemirror/commands';
+import { oneDarkTheme } from '@codemirror/theme-one-dark';
-import { pyodideLoaded, loadedEnvironments, componentDetailsNavOpen, currentComponentDetails, mode, addToScriptsQueue, addInitializer, addPostInitializer } from '../stores';
+import {
+ addInitializer,
+ addPostInitializer,
+ addToScriptsQueue,
+ componentDetailsNavOpen,
+ loadedEnvironments,
+ mode,
+ pyodideLoaded,
+} from '../stores';
import { addClasses, htmlDecode } from '../utils';
import { BaseEvalElement } from './base';
@@ -17,7 +24,7 @@ let currentMode;
let handlersCollected = false;
pyodideLoaded.subscribe(value => {
- pyodideReadyPromise = value;
+ pyodideReadyPromise = value;
});
loadedEnvironments.subscribe(value => {
environments = value;
@@ -25,240 +32,233 @@ loadedEnvironments.subscribe(value => {
let propertiesNavOpen;
componentDetailsNavOpen.subscribe(value => {
- propertiesNavOpen = value;
+ propertiesNavOpen = value;
});
mode.subscribe(value => {
- currentMode = value;
+ currentMode = value;
});
-function createCmdHandler(el){
+function createCmdHandler(el) {
// Creates a codemirror cmd handler that calls the el.evaluate when an event
// triggers that specific cmd
- const toggleCheckbox:StateCommand = ({ state, dispatch }) => {
- return el.evaluate(state)
- }
- return toggleCheckbox
+ const toggleCheckbox: StateCommand = ({ state, dispatch }) => {
+ return el.evaluate(state);
+ };
+ return toggleCheckbox;
}
// TODO: use type declaractions
type PyodideInterface = {
- registerJsModule(name: string, module: object): void
-}
+ registerJsModule(name: string, module: object): void;
+};
// TODO: This should be used as base for generic scripts that need exectutoin
// from PyScript to initializers, etc...
class Script {
- source: string;
- state: string;
- output: string;
-
- constructor(source: string, output: string) {
- this.output = output;
- this.source = source;
- this.state = 'waiting';
- }
-
- async evaluate() {
- console.log('evaluate');
- let pyodide = await pyodideReadyPromise;
- // debugger
- try {
- // @ts-ignore
- // let source = this.editor.state.doc.toString();
- let output;
- if (this.source.includes("asyncio")){
- output = await pyodide.runPythonAsync(this.source);
- }else{
- output = pyodide.runPython(this.source);
- }
+ source: string;
+ state: string;
+ output: string;
- if (this.output){
- // this.editorOut.innerHTML = s;
- }
- // if (output !== undefined){
- // this.addToOutput(output);
- // }
+ constructor(source: string, output: string) {
+ this.output = output;
+ this.source = source;
+ this.state = 'waiting';
+ }
-
- } catch (err) {
- console.log("OOOPS, this happened: " + err);
- // this.addToOutput(err);
- }
- }
+ async evaluate() {
+ console.log('evaluate');
+ const pyodide = await pyodideReadyPromise;
+ // debugger
+ try {
+ // let source = this.editor.state.doc.toString();
+ let output;
+ if (this.source.includes('asyncio')) {
+ output = await pyodide.runPythonAsync(this.source);
+ } else {
+ output = pyodide.runPython(this.source);
+ }
+
+ if (this.output) {
+ // this.editorOut.innerHTML = s;
+ }
+ // if (output !== undefined){
+ // this.addToOutput(output);
+ // }
+ } catch (err) {
+ console.log('OOOPS, this happened: ', err);
+ // this.addToOutput(err);
+ }
+ }
}
export class PyScript extends BaseEvalElement {
-
constructor() {
super();
-
+
// add an extra div where we can attach the codemirror editor
this.shadow.appendChild(this.wrapper);
- }
+ }
connectedCallback() {
- this.checkId()
+ this.checkId();
this.code = this.innerHTML;
this.innerHTML = '';
- let startState = EditorState.create({
- doc: this.code,
- extensions: [
- keymap.of([
+ const startState = EditorState.create({
+ doc: this.code,
+ extensions: [
+ keymap.of([
...defaultKeymap,
- { key: "Ctrl-Enter", run: createCmdHandler(this) },
- { key: "Shift-Enter", run: createCmdHandler(this) }
- ]),
- oneDarkTheme,
- python(),
- // Event listener function that is called every time an user types something on this editor
- // EditorView.updateListener.of((v:ViewUpdate) => {
- // if (v.docChanged) {
- // console.log(v.changes);
+ { key: 'Ctrl-Enter', run: createCmdHandler(this) },
+ { key: 'Shift-Enter', run: createCmdHandler(this) },
+ ]),
+ oneDarkTheme,
+ python(),
+ // Event listener function that is called every time an user types something on this editor
+ // EditorView.updateListener.of((v:ViewUpdate) => {
+ // if (v.docChanged) {
+ // console.log(v.changes);
- // }
- // })
- ]
- })
-
- let mainDiv = document.createElement('div');
- addClasses(mainDiv, ["parentBox", "flex", "flex-col", 'mx-8'])
- // add Editor to main PyScript div
-
+ // }
+ // })
+ ],
+ });
- if (this.hasAttribute('output')) {
- this.errorElement = this.outputElement = document.getElementById(this.getAttribute('output'));
+ const mainDiv = document.createElement('div');
+ addClasses(mainDiv, ['parentBox', 'flex', 'flex-col', 'mx-8']);
+ // add Editor to main PyScript div
- // in this case, the default output-mode is append, if hasn't been specified
- if (!this.hasAttribute('output-mode')) {
- this.setAttribute('output-mode', 'append');
- }
- }else{
- if (this.hasAttribute('std-out')){
- this.outputElement = document.getElementById(this.getAttribute('std-out'));
- }else{
- // In this case neither output or std-out have been provided so we need
- // to create a new output div to output to
+ if (this.hasAttribute('output')) {
+ this.errorElement = this.outputElement = document.getElementById(this.getAttribute('output'));
- // Let's check if we have an id first and create one if not
- this.outputElement = document.createElement('div');
- const exec_id = this.getAttribute("exec-id");
- this.outputElement.id = this.id + (exec_id ? "-"+exec_id : "");
+ // in this case, the default output-mode is append, if hasn't been specified
+ if (!this.hasAttribute('output-mode')) {
+ this.setAttribute('output-mode', 'append');
+ }
+ } else {
+ if (this.hasAttribute('std-out')) {
+ this.outputElement = document.getElementById(this.getAttribute('std-out'));
+ } else {
+ // In this case neither output or std-out have been provided so we need
+ // to create a new output div to output to
- // add the output div id if there's not output pre-defined
- mainDiv.appendChild(this.outputElement);
+ // Let's check if we have an id first and create one if not
+ this.outputElement = document.createElement('div');
+ const exec_id = this.getAttribute('exec-id');
+ this.outputElement.id = this.id + (exec_id ? '-' + exec_id : '');
+
+ // add the output div id if there's not output pre-defined
+ mainDiv.appendChild(this.outputElement);
+ }
+
+ if (this.hasAttribute('std-err')) {
+ this.outputElement = document.getElementById(this.getAttribute('std-err'));
+ } else {
+ this.errorElement = this.outputElement;
+ }
}
- if (this.hasAttribute('std-err')){
- this.outputElement = document.getElementById(this.getAttribute('std-err'));
- }else{
- this.errorElement = this.outputElement;
+ if (currentMode == 'edit') {
+ // TODO: We need to build a plan for this
+ this.appendChild(mainDiv);
+ } else {
+ this.appendChild(mainDiv);
+ addToScriptsQueue(this);
}
- }
- if (currentMode=="edit"){
- // TODO: We need to build a plan for this
- this.appendChild(mainDiv);
- }else{
- this.appendChild(mainDiv);
- addToScriptsQueue(this);
- }
+ console.log('connected');
- console.log('connected');
-
- if (this.hasAttribute('src')) {
- this.source = this.getAttribute('src');
- }
+ if (this.hasAttribute('src')) {
+ this.source = this.getAttribute('src');
+ }
}
protected async _register_esm(pyodide: PyodideInterface): Promise {
- for (const node of document.querySelectorAll("script[type='importmap']")) {
- const importmap = (() => {
- try {
- return JSON.parse(node.textContent)
- } catch {
- return null
- }
- })()
+ for (const node of document.querySelectorAll("script[type='importmap']")) {
+ const importmap = (() => {
+ try {
+ return JSON.parse(node.textContent);
+ } catch {
+ return null;
+ }
+ })();
- if (importmap?.imports == null)
- continue
+ if (importmap?.imports == null) continue;
- for (const [name, url] of Object.entries(importmap.imports)) {
- if (typeof name != "string" || typeof url != "string")
- continue
+ for (const [name, url] of Object.entries(importmap.imports)) {
+ if (typeof name != 'string' || typeof url != 'string') continue;
- let exports: object
- try {
- // XXX: pyodide doesn't like Module(), failing with
- // "can't read 'name' of undefined" at import time
- exports = {...await import(url)}
- } catch {
- console.warn(`failed to fetch '${url}' for '${name}'`)
- continue
- }
+ let exports: object;
+ try {
+ // XXX: pyodide doesn't like Module(), failing with
+ // "can't read 'name' of undefined" at import time
+ exports = { ...(await import(url)) };
+ } catch {
+ console.warn(`failed to fetch '${url}' for '${name}'`);
+ continue;
+ }
- pyodide.registerJsModule(name, exports)
+ pyodide.registerJsModule(name, exports);
+ }
}
- }
}
getSourceFromElement(): string {
- return htmlDecode(this.code);
+ return htmlDecode(this.code);
}
- }
+}
/** Initialize all elements with py-onClick handlers attributes */
async function initHandlers() {
- console.log('Collecting nodes...');
- let pyodide = await pyodideReadyPromise;
- let matches : NodeListOf = document.querySelectorAll('[pys-onClick]');
- let output;
- let source;
- for (var el of matches) {
- let handlerCode = el.getAttribute('pys-onClick');
- source = `Element("${ el.id }").element.onclick = ${ handlerCode }`;
- output = await pyodide.runPythonAsync(source);
+ console.log('Collecting nodes...');
+ const pyodide = await pyodideReadyPromise;
+ let matches: NodeListOf = document.querySelectorAll('[pys-onClick]');
+ let output;
+ let source;
+ for (const el of matches) {
+ const handlerCode = el.getAttribute('pys-onClick');
+ source = `Element("${el.id}").element.onclick = ${handlerCode}`;
+ output = await pyodide.runPythonAsync(source);
- // TODO: Should we actually map handlers in JS instaed of Python?
- // el.onclick = (evt: any) => {
- // console.log("click");
- // new Promise((resolve, reject) => {
- // setTimeout(() => {
- // console.log('Inside')
- // }, 300);
- // }).then(() => {
- // console.log("resolved")
- // });
- // // let handlerCode = el.getAttribute('pys-onClick');
- // // pyodide.runPython(handlerCode);
- // }
- }
- handlersCollected = true;
+ // TODO: Should we actually map handlers in JS instaed of Python?
+ // el.onclick = (evt: any) => {
+ // console.log("click");
+ // new Promise((resolve, reject) => {
+ // setTimeout(() => {
+ // console.log('Inside')
+ // }, 300);
+ // }).then(() => {
+ // console.log("resolved")
+ // });
+ // // let handlerCode = el.getAttribute('pys-onClick');
+ // // pyodide.runPython(handlerCode);
+ // }
+ }
+ handlersCollected = true;
- matches = document.querySelectorAll('[pys-onKeyDown]');
- for (var el of matches) {
- let handlerCode = el.getAttribute('pys-onKeyDown');
- source = `Element("${ el.id }").element.addEventListener("keydown", ${ handlerCode })`;
- output = await pyodide.runPythonAsync(source);
- }
+ matches = document.querySelectorAll('[pys-onKeyDown]');
+ for (const el of matches) {
+ const handlerCode = el.getAttribute('pys-onKeyDown');
+ source = `Element("${el.id}").element.addEventListener("keydown", ${handlerCode})`;
+ output = await pyodide.runPythonAsync(source);
+ }
}
/** Mount all elements with attribute py-mount into the Python namespace */
async function mountElements() {
- console.log('Collecting nodes to be mounted into python namespace...');
- let pyodide = await pyodideReadyPromise;
- let matches : NodeListOf = document.querySelectorAll('[py-mount]');
- let output;
- let source = "";
- for (var el of matches) {
- let mountName = el.getAttribute('py-mount');
- if (!mountName){
- mountName = el.id.split("-").join("_");
+ console.log('Collecting nodes to be mounted into python namespace...');
+ const pyodide = await pyodideReadyPromise;
+ const matches: NodeListOf = document.querySelectorAll('[py-mount]');
+ let output;
+ let source = '';
+ for (const el of matches) {
+ let mountName = el.getAttribute('py-mount');
+ if (!mountName) {
+ mountName = el.id.split('-').join('_');
+ }
+ source += `\n${mountName} = Element("${el.id}")`;
}
- source += `\n${ mountName } = Element("${ el.id }")`;
- }
- await pyodide.runPythonAsync(source);
+ await pyodide.runPythonAsync(source);
}
addInitializer(mountElements);
addPostInitializer(initHandlers);
diff --git a/pyscriptjs/src/components/pytitle.ts b/pyscriptjs/src/components/pytitle.ts
index de4890c..444ff53 100644
--- a/pyscriptjs/src/components/pytitle.ts
+++ b/pyscriptjs/src/components/pytitle.ts
@@ -2,33 +2,31 @@ import { BaseEvalElement } from './base';
import { addClasses, ltrim, htmlDecode } from '../utils';
export class PyTitle extends BaseEvalElement {
- shadow: ShadowRoot;
- wrapper: HTMLElement;
- theme: string;
- widths: Array;
- label: string;
- mount_name: string;
- constructor() {
- super();
+ shadow: ShadowRoot;
+ wrapper: HTMLElement;
+ theme: string;
+ widths: Array;
+ label: string;
+ mount_name: string;
+ constructor() {
+ super();
}
- connectedCallback() {
- this.label = htmlDecode(this.innerHTML);
- this.mount_name = this.id.split("-").join("_");
- this.innerHTML = '';
+ connectedCallback() {
+ this.label = htmlDecode(this.innerHTML);
+ this.mount_name = this.id.split('-').join('_');
+ this.innerHTML = '';
- let mainDiv = document.createElement('div');
- let divContent = document.createElement('h1')
+ const mainDiv = document.createElement('div');
+ const divContent = document.createElement('h1');
- addClasses(mainDiv, ["text-center", "w-full", "mb-8"]);
- addClasses(divContent, ["text-3xl", "font-bold", "text-gray-800", "uppercase", "tracking-tight"]);
- divContent.innerHTML = this.label;
+ addClasses(mainDiv, ['text-center', 'w-full', 'mb-8']);
+ addClasses(divContent, ['text-3xl', 'font-bold', 'text-gray-800', 'uppercase', 'tracking-tight']);
+ divContent.innerHTML = this.label;
- mainDiv.id = this.id;
- this.id = `${this.id}-container`;
- mainDiv.appendChild(divContent);
- this.appendChild(mainDiv);
- }
+ mainDiv.id = this.id;
+ this.id = `${this.id}-container`;
+ mainDiv.appendChild(divContent);
+ this.appendChild(mainDiv);
+ }
}
-
-
\ No newline at end of file
diff --git a/pyscriptjs/src/interpreter.ts b/pyscriptjs/src/interpreter.ts
index ceab6ab..8459b07 100644
--- a/pyscriptjs/src/interpreter.ts
+++ b/pyscriptjs/src/interpreter.ts
@@ -1,11 +1,9 @@
-import { getLastPath } from "./utils";
+import { getLastPath } from './utils';
-// @ts-nocheck
-// @ts-ignore
let pyodideReadyPromise;
let pyodide;
-let additional_definitions = `
+const additional_definitions = `
from js import document, setInterval, console, setTimeout
import micropip
import time
@@ -413,19 +411,18 @@ class OutputManager:
pyscript = PyScript()
output_manager = OutputManager()
-`
+`;
-let loadInterpreter = async function(): Promise {
- console.log("creating pyodide runtime");
- /* @ts-ignore */
+const loadInterpreter = async function (): Promise {
+ console.log('creating pyodide runtime');
pyodide = await loadPyodide({
- stdout: console.log,
- stderr: console.log
- });
+ stdout: console.log,
+ stderr: console.log,
+ });
// now that we loaded, add additional convenience fuctions
- console.log("loading micropip");
- await pyodide.loadPackage("micropip");
+ console.log('loading micropip');
+ await pyodide.loadPackage('micropip');
console.log('loading pyscript module');
// await pyodide.runPythonAsync(`
// from pyodide.http import pyfetch
@@ -437,31 +434,36 @@ let loadInterpreter = async function(): Promise {
// `)
// let pkg = pyodide.pyimport("pyscript");
- console.log("creating additional definitions");
- let output = pyodide.runPython(additional_definitions);
- console.log("done setting up environment");
- /* @ts-ignore */
+ console.log('creating additional definitions');
+ const output = pyodide.runPython(additional_definitions);
+ console.log('done setting up environment');
return pyodide;
-}
+};
-let loadPackage = async function(package_name: string[] | string, runtime: any): Promise {
- let micropip = pyodide.globals.get('micropip');
- await micropip.install(package_name)
- micropip.destroy()
-}
+const loadPackage = async function (package_name: string[] | string, runtime: any): Promise {
+ const micropip = pyodide.globals.get('micropip');
+ await micropip.install(package_name);
+ micropip.destroy();
+};
-let loadFromFile = async function(s: string, runtime: any): Promise {
- let filename = getLastPath(s);
- await runtime.runPythonAsync(`
+const loadFromFile = async function (s: string, runtime: any): Promise {
+ const filename = getLastPath(s);
+ await runtime.runPythonAsync(
+ `
from pyodide.http import pyfetch
- response = await pyfetch("`+s+`")
+ response = await pyfetch("` +
+ s +
+ `")
content = await response.bytes()
- with open("`+filename+`", "wb") as f:
+ with open("` +
+ filename +
+ `", "wb") as f:
f.write(content)
- `)
+ `,
+ );
- runtime.pyimport(filename.replace(".py", ""));
-}
+ runtime.pyimport(filename.replace('.py', ''));
+};
-export {loadInterpreter, pyodideReadyPromise, loadPackage, loadFromFile}
+export { loadInterpreter, pyodideReadyPromise, loadPackage, loadFromFile };
diff --git a/pyscriptjs/src/main.ts b/pyscriptjs/src/main.ts
index 321a79e..9f8badf 100644
--- a/pyscriptjs/src/main.ts
+++ b/pyscriptjs/src/main.ts
@@ -1,26 +1,25 @@
-import App from "./App.svelte";
+import App from './App.svelte';
-import { PyScript } from "./components/pyscript";
-import { PyRepl } from "./components/pyrepl";
-import { PyEnv } from "./components/pyenv";
-import { PyBox } from "./components/pybox";
-import { PyButton } from "./components/pybutton";
-import { PyTitle } from "./components/pytitle";
-import { PyInputBox } from "./components/pyinputbox";
-import { PyWidget } from "./components/base";
-
-let xPyScript = customElements.define('py-script', PyScript);
-let xPyRepl = customElements.define('py-repl', PyRepl);
-let xPyEnv = customElements.define('py-env', PyEnv);
-let xPyBox = customElements.define('py-box', PyBox);
-let xPyButton = customElements.define('py-button', PyButton);
-let xPyTitle = customElements.define('py-title', PyTitle);
-let xPyInputBox = customElements.define('py-inputbox', PyInputBox);
-let xPyWidget = customElements.define('py-register-widget', PyWidget);
+import { PyScript } from './components/pyscript';
+import { PyRepl } from './components/pyrepl';
+import { PyEnv } from './components/pyenv';
+import { PyBox } from './components/pybox';
+import { PyButton } from './components/pybutton';
+import { PyTitle } from './components/pytitle';
+import { PyInputBox } from './components/pyinputbox';
+import { PyWidget } from './components/base';
+const xPyScript = customElements.define('py-script', PyScript);
+const xPyRepl = customElements.define('py-repl', PyRepl);
+const xPyEnv = customElements.define('py-env', PyEnv);
+const xPyBox = customElements.define('py-box', PyBox);
+const xPyButton = customElements.define('py-button', PyButton);
+const xPyTitle = customElements.define('py-title', PyTitle);
+const xPyInputBox = customElements.define('py-inputbox', PyInputBox);
+const xPyWidget = customElements.define('py-register-widget', PyWidget);
const app = new App({
- target: document.body,
+ target: document.body,
});
export default app;
diff --git a/pyscriptjs/src/stores.ts b/pyscriptjs/src/stores.ts
index 77bfa75..e4151a4 100644
--- a/pyscriptjs/src/stores.ts
+++ b/pyscriptjs/src/stores.ts
@@ -1,12 +1,11 @@
import { writable } from 'svelte/store';
-
export const pyodideLoaded = writable({
- loaded: false,
- premise: null
+ loaded: false,
+ premise: null,
});
-export const loadedEnvironments = writable([{}])
+export const loadedEnvironments = writable([{}]);
export const DEFAULT_MODE = 'play';
export const navBarOpen = writable(false);
@@ -14,43 +13,43 @@ export const componentsNavOpen = writable(false);
export const componentDetailsNavOpen = writable(false);
export const mainDiv = writable(null);
export const currentComponentDetails = writable([]);
-export const mode = writable(DEFAULT_MODE)
-export const scriptsQueue = writable([])
-export const initializers = writable([])
-export const postInitializers = writable([])
+export const mode = writable(DEFAULT_MODE);
+export const scriptsQueue = writable([]);
+export const initializers = writable([]);
+export const postInitializers = writable([]);
let scriptsQueue_ = [];
let initializers_ = [];
let postInitializers_ = [];
scriptsQueue.subscribe(value => {
- scriptsQueue_ = value;
+ scriptsQueue_ = value;
});
-export const addToScriptsQueue = (script) => {
- scriptsQueue.set([...scriptsQueue_, script]);
+export const addToScriptsQueue = script => {
+ scriptsQueue.set([...scriptsQueue_, script]);
};
scriptsQueue.subscribe(value => {
- scriptsQueue_ = value;
+ scriptsQueue_ = value;
});
initializers.subscribe(value => {
- initializers_ = value;
+ initializers_ = value;
});
-export const addInitializer = (initializer) => {
- console.log("adding initializer", initializer);
- initializers.set([...initializers_, initializer]);
- console.log("adding initializer", initializer);
+export const addInitializer = initializer => {
+ console.log('adding initializer', initializer);
+ initializers.set([...initializers_, initializer]);
+ console.log('adding initializer', initializer);
};
postInitializers.subscribe(value => {
- postInitializers_ = value;
+ postInitializers_ = value;
});
-export const addPostInitializer = (initializer) => {
- console.log("adding post initializer", initializer);
- postInitializers.set([...postInitializers_, initializer]);
- console.log("adding post initializer", initializer);
+export const addPostInitializer = initializer => {
+ console.log('adding post initializer', initializer);
+ postInitializers.set([...postInitializers_, initializer]);
+ console.log('adding post initializer', initializer);
};
diff --git a/pyscriptjs/src/utils.ts b/pyscriptjs/src/utils.ts
index cdcd1c7..6873396 100644
--- a/pyscriptjs/src/utils.ts
+++ b/pyscriptjs/src/utils.ts
@@ -1,44 +1,40 @@
-
-function addClasses(element: HTMLElement, classes: Array){
- for (let entry of classes) {
- element.classList.add(entry);
+function addClasses(element: HTMLElement, classes: Array) {
+ for (const entry of classes) {
+ element.classList.add(entry);
}
}
const getLastPath = function (str) {
- return str.split('\\').pop().split('/').pop();
-}
+ return str.split('\\').pop().split('/').pop();
+};
function htmlDecode(input) {
- var doc = new DOMParser().parseFromString(input, "text/html");
- return ltrim(doc.documentElement.textContent);
+ const doc = new DOMParser().parseFromString(input, 'text/html');
+ return ltrim(doc.documentElement.textContent);
}
function ltrim(code: string): string {
- const lines = code.split("\n")
- if (lines.length == 0)
- return code
+ const lines = code.split('\n');
+ if (lines.length == 0) return code;
- const lengths = lines
- .filter((line) => line.trim().length != 0)
- .map((line) => {
- const [prefix] = line.match(/^\s*/)
- return prefix.length
- })
+ const lengths = lines
+ .filter(line => line.trim().length != 0)
+ .map(line => {
+ const [prefix] = line.match(/^\s*/);
+ return prefix.length;
+ });
- const k = Math.min(...lengths)
+ const k = Math.min(...lengths);
- if (k != 0)
- return lines.map((line) => line.substring(k)).join("\n")
- else
- return code
+ if (k != 0) return lines.map(line => line.substring(k)).join('\n');
+ else return code;
}
function guidGenerator(): string {
- var S4 = function(): string {
- return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
- };
- return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
+ const S4 = function (): string {
+ return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+ };
+ return S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4();
}
-export {addClasses, getLastPath, ltrim, htmlDecode, guidGenerator}
+export { addClasses, getLastPath, ltrim, htmlDecode, guidGenerator };