{"_id":"pyfrilet","_rev":"29-7f3c90c8d111672b8747c3b71da99ed4","name":"pyfrilet","dist-tags":{"latest":"0.7.5"},"versions":{"0.1.1":{"name":"pyfrilet","version":"0.1.1","_id":"pyfrilet@0.1.1","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"726367abc349625b5d0748054606ef2fc82cb87a","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.1.1.tgz","fileCount":5,"integrity":"sha512-jPcVdk0pgKQ4TGWKt8uEjfUZXaWsVBGSYqzL3esk1wRPUO+YwMmV2ixcvOq/oYsCJykPGbTCrDqmq8VWxw5Wpw==","signatures":[{"sig":"MEYCIQDo//ZDoTwaek3nT14VwSYUHbDETbpAKl3TuoBAzGhToQIhAP/CTwDZg5uBEJk69g8/wLyHjplC+ShAP/6iLjVfUMRq","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97884},"main":"pyfrilet.js","gitHead":"98d42b7a5c0f52a29ebe0e522d5e27926f6bca10","scripts":{"build":"terser pyfrilet.js -o pyfrilet.min.js --compress --mangle"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.46.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.1.1_1772737877353_0.7290684262230476","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"pyfrilet","version":"0.2.0","_id":"pyfrilet@0.2.0","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"0205587c781d2b17c45ceab04adf9cc7238ae45e","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.2.0.tgz","fileCount":5,"integrity":"sha512-buw30uKg2cN3ickAAQ1ndokbTt07p3MoA9RHbNu5PepBmakLDcyR7M5EAXjD3qqXiQK8ir8Mkrq3cln+bGokkg==","signatures":[{"sig":"MEUCIAhdlO86E7YM5Pmcl90i4J3+CEcIJ6sN9uRWIgdaEaDCAiEA1tSoY7J5+S6Bg2oA/FWUptNJnIdhSR/HWqkG4As/suY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96523},"main":"pyfrilet.js","gitHead":"98d42b7a5c0f52a29ebe0e522d5e27926f6bca10","scripts":{"build":"terser pyfrilet.js -o pyfrilet.min.js --compress --mangle"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.46.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.2.0_1772738245399_0.9777140281099646","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"pyfrilet","version":"0.2.1","_id":"pyfrilet@0.2.1","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"b87ba83435fb9f5daab840e6d520d03499d79fe0","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.2.1.tgz","fileCount":5,"integrity":"sha512-enG4DFRXzaThNGSnTRKU9L7uVdmK8hDSPfAPG+czcTs22s+vmM9hFo92ENviuNGEwVdpsFf7lZbCU6FwAUdxHw==","signatures":[{"sig":"MEYCIQCkR8WVDAysMSGLwGkei8Uv/UDrtrK+O8//dvnuvjUqHwIhALTbrwW0USxNFmN4u5Ug+S/2TCNWv1FqEAL3fmrwBJ4/","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96535},"main":"pyfrilet.js","type":"module","gitHead":"13a6a5ed88861f52495221e0feb5c8d46ca5d0e3","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.2.1_1772739020351_0.21709542432224738","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"pyfrilet","version":"0.2.2","_id":"pyfrilet@0.2.2","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"c69321bdcb889464c48fa8428f32f8ff7bf5ac3f","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.2.2.tgz","fileCount":5,"integrity":"sha512-LbsH4n92OBxGftUY9ebUyGdSCkv9TFnPf+94ML1WtEoW5WQ7v6jr6qlcm/COSB5FDR2T8+V5PXYIK1zaWEr3yQ==","signatures":[{"sig":"MEUCIAg11QzdSTGDNxmhqf68pYrPYHQU75JkzHKBubm+L7/RAiEA7prOlglBqoBJ16KP9VsApdxYHEqmeKpQPEFca7DIBIY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":103262},"main":"pyfrilet.js","type":"module","gitHead":"a2d08847f9e4b15ac83f9f71202e28d0c42386c9","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.2.2_1772744794287_0.9131949225575675","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"pyfrilet","version":"0.2.3","_id":"pyfrilet@0.2.3","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"3fe60ca13ab06874884250aeda1738b56817e855","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.2.3.tgz","fileCount":5,"integrity":"sha512-m9ZYe14Bxyw+bxwLkXcovD0d57mQPv0XxkC46kGJt0Txv8g1KxGt6baAlqK5wb6+hWzb2GQEYiOvtOhDBpTdvg==","signatures":[{"sig":"MEYCIQCYR6pfwVuVgTr1iUWPDGXshQ8r46VIyG8P/4KExQF1mwIhAJHb87AmpcWsiQ8SUL4gzZkKSTuhxTGWg57Olv4FEn+m","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":103705},"main":"pyfrilet.js","type":"module","gitHead":"869fc4c52f26a1448e8cf496ce9113deb6e0604d","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.2.3_1772749946180_0.7088126307806175","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"pyfrilet","version":"0.3.0","_id":"pyfrilet@0.3.0","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"5ef1dfd3b47520c31685d41ee98035f9f4b1e67d","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.3.0.tgz","fileCount":5,"integrity":"sha512-X6p5GJDbIcGV1OvLI7dDSzaBcJyVGYfau8F9eSxZzbctqCGc7t1shDSu/QUid6CGuP8Ffwc4M4ooys7T1GOWZg==","signatures":[{"sig":"MEUCIHsKgwSYQOLi/0LmE+r/eyf+2OkamCVBLbkP0e+blYKHAiEAqzs082OwammDV5t3luJzlGVvTKnJawLYCn4vljtXbNw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107609},"main":"pyfrilet.js","type":"module","gitHead":"e3d8ecf83e01c77f2f127c282b6534e31314ae23","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.3.0_1772787654458_0.5096131835752828","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"pyfrilet","version":"0.3.1","_id":"pyfrilet@0.3.1","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"5c981bb3cde5f7763336479bcfeb0bf5c8450ef5","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.3.1.tgz","fileCount":5,"integrity":"sha512-pk4TeQa6hpSgS5nJwT2Yo6mHcAevfKzzYK+wyQwuu8b7LPkMgjdRVYzaDEVtyrwtzS7FQUwDY6GiClp7SSItbQ==","signatures":[{"sig":"MEYCIQCgkpF7n7R7iANH4jPFA8cOWb8nJKWeHvweziRjCLsKUAIhALcWqj2Syk/8jT+MUmWtakAPfyi0C+X2wnXZZZI052tX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":108540},"main":"pyfrilet.js","type":"module","gitHead":"4d70898d86861fdd8cb6ad70f80175c7ad50f66f","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.3.1_1772788461388_0.8048531626938096","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"pyfrilet","version":"0.3.2","_id":"pyfrilet@0.3.2","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"e17380232988dd157e61318f0ebcd2ab211a0878","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.3.2.tgz","fileCount":5,"integrity":"sha512-Mg2SkS7JE/NwdwiQu5yKZY/YFBuiUwKd54DC8zojgino3Fuh6bdQaLpLUUxxcWAGW4h5Y3A6DqGTD2sbHhWmoA==","signatures":[{"sig":"MEUCIQCvkhIHadeGfeR5P6fgl+KyBdB/gJoK3YW3/My7vGGjSAIgHr5xLy+r/+0kLp5w1PFpDztZbh/kPsbKbUutDEDc7jY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":112629},"main":"pyfrilet.js","type":"module","gitHead":"cfbd48262ff71af0b11d11a5be48bab327cd8dc7","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.3.2_1772796509131_0.6404155352325509","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"pyfrilet","version":"0.4.0","_id":"pyfrilet@0.4.0","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"55f8f83980153158ec3bb9bd2433582320fd76a2","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.4.0.tgz","fileCount":5,"integrity":"sha512-TyFnKEcZ1irHD9ADYsrhZ+BTA5rRya6TFt4Luy0LbS5xC/mSPskh++4ZNAPGfUl89Iyn2I8lrs/B7gXBRqFyTg==","signatures":[{"sig":"MEYCIQCvyxl2xite9/Xnz1nTQTI7BiN25QXBbdQUiqpMGQWwJgIhAPNUd9OrpcvoZaWd0nPEfswV/YhsDPhc/DxCnBhvbQUA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117030},"main":"pyfrilet.js","type":"module","gitHead":"38c56d97313bea5000faac8ea4bc1da380440a32","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.4.0_1772885184175_0.45736437968620347","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"pyfrilet","version":"0.4.1","_id":"pyfrilet@0.4.1","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"0332fbe4f800e99ccbc791cee1b00958a81e4ecf","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.4.1.tgz","fileCount":5,"integrity":"sha512-4Get9lIiy7xzjFqErVkZ8i++FmFN4iTMqkxJRKmaP7DiP8Gp1l4Ba+1DwaE+0WtagX38BIgzyrTKwzIJp8U9GA==","signatures":[{"sig":"MEQCICl+v20E/wUzeI4DCenEH6uv7X3qAWkgUF/ltx5t2gqRAiA0WZ4bV6tUwk7kjLMzzq4ukHAaZErNrIyxnGZZQ438Cg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117757},"main":"pyfrilet.js","type":"module","gitHead":"c209ea28104de7420e68f4dffd27f18f836d52d3","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.4.1_1772886419606_0.7690891208250814","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"pyfrilet","version":"0.4.2","_id":"pyfrilet@0.4.2","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"c6d357831f036bdc3acd62ac6a1950445f89f902","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.4.2.tgz","fileCount":5,"integrity":"sha512-j65FqB5LKxw8JCiGE6zU21jXWNZCA9Ert79N/Sn1fT8FO9eBvi0UzDHM+cp8dGoZMOuJC9I/aK2mnWCcJO3DIw==","signatures":[{"sig":"MEYCIQCZNYYGNKGLf2ayBcPrWguddlB7kW+ZmEENmnQCPpHIZgIhAJqimHkkX5rvGc8vbSwq9inxYv/tmO4puzup8Ryf5JrW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":118575},"main":"pyfrilet.js","type":"module","gitHead":"36c224b1657d9edfe0c0fc4e77a3bd8631be62c9","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.4.2_1772889410985_0.6297172444888617","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"pyfrilet","version":"0.4.3","_id":"pyfrilet@0.4.3","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"54c80c87ba9470841a4cf647dfde34a8ea48a9b3","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.4.3.tgz","fileCount":5,"integrity":"sha512-ag8M8nBt8LiTC623P3mVnd/UN1XuBZRz1GkkTTCZYlfN6cuNFFTRm0rJngyXFpK9IAmFs1RRixAKJV1LpRwNeg==","signatures":[{"sig":"MEQCIEL+oaFj8uTo9jGgJoQ3sBzvE1MPRnK2PRK+xNcYmtmhAiAYJBJcLChCN/xi1vvhmOsZCgOxwjnXT5Uqs1v+/ajtCA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":118578},"main":"pyfrilet.js","type":"module","gitHead":"d747061b0d0e2f8d375dc3301d488dcbb4d0faf2","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.4.3_1772898589109_0.9877240154518698","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"pyfrilet","version":"0.5.0","_id":"pyfrilet@0.5.0","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"9a65ba8814e8564de5cd855c18623469cd1c086a","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.5.0.tgz","fileCount":5,"integrity":"sha512-GMbdkQwMVZeCvES4wAHNW8LWEOG+5zwkR9N6YaaE3g9K7WuvprMy/EQ5vfXrIgakgtzgA+aPn+JOikyHyURxZw==","signatures":[{"sig":"MEUCIQCgw2XLIBW63PwOjvPTxwPNufdnzsj0UNlS90G9/u8RfAIgbq4zTiNiFIqIg4zKqxo7DAKN6JUWN0ZpB5dOVTfTji4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":135939},"main":"pyfrilet.js","type":"module","gitHead":"3d583d635268381a77a2dbb1250f2a3c91feac73","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.5.0_1773068212916_0.26798052889926116","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"pyfrilet","version":"0.5.1","_id":"pyfrilet@0.5.1","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"eb386900a8436ddce00720a0fb329f237a3cbf5b","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.5.1.tgz","fileCount":5,"integrity":"sha512-+ciqfmua+FARDEGY+0K6FUEJ48erjEXhlvLdCIrB9Dcu5RhqTFtxo0A5tx62Hf9LQenSG8uhzoSCgGKBhb69Og==","signatures":[{"sig":"MEUCIQCnPJk6CyimE3fbKE81kXiEEJqt9aBU4jPhmT5224STggIgI2LKTMDh9y6b2QWs0PEUJ8ihS2Ukn5rddtWxPFtZTPU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":146697},"main":"pyfrilet.js","type":"module","gitHead":"7f1f5ea40cc438f75287bdb8adcfd325c2919b19","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.5.1_1773075800366_0.2048409219005567","host":"s3://npm-registry-packages-npm-production"}},"0.5.2":{"name":"pyfrilet","version":"0.5.2","_id":"pyfrilet@0.5.2","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"09ea99e706d42fb4efbc9989d569bddb0be315aa","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.5.2.tgz","fileCount":5,"integrity":"sha512-b6T/tHFkjN9SwvR6UzXm+cQekhp1HW7hEeXSGfQfzBJdWmvfAwzXi81uCXK32GrJ5/DKR1aH9RG3j3/cTsul5w==","signatures":[{"sig":"MEUCIQD6kqE5PNZssHvcDfnX94HGJzoot8CmXsWkKW34rdyotQIgLl6In7agLH0DEk9PiNu+3Qf8MMbeVool3Zdi7fvzvl4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":150521},"main":"pyfrilet.js","type":"module","gitHead":"4978a8dc778a45655b6032a70fde768e15b26825","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.5.2_1773076381546_0.7625845754506237","host":"s3://npm-registry-packages-npm-production"}},"0.5.3":{"name":"pyfrilet","version":"0.5.3","_id":"pyfrilet@0.5.3","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"dfb4b7df3f87adc154f51345e7d8744425da2487","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.5.3.tgz","fileCount":5,"integrity":"sha512-JJvtDackmniw18gFBKEYRLiuKmbkrddUiNiTTG4hMPS/CQeI0+mjqfHnm0t2gcxOiIm58FSnZbmE8Jk0kSaEMQ==","signatures":[{"sig":"MEUCIEaT+KTdTiDhguy0IP5g5bQ9UuWfZ+vf3hFkoEMwH4jGAiEAoBJS/wv9Uv/XcEODCf35PCCnBIF8c2iQN/stD5jgnqw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":151363},"main":"pyfrilet.js","type":"module","gitHead":"c24d6ed991d2eff168fe3821e2ca189b3ca0bb67","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.5.3_1773079074325_0.821769925633562","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"pyfrilet","version":"0.6.0","_id":"pyfrilet@0.6.0","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"0acb67cc5c8d17c89686a5192dae428f09896a45","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.6.0.tgz","fileCount":5,"integrity":"sha512-obVS0gRmU41Qdv7pjg0n1ncnNjQr9Fm0l7SuOSuPbZPY0Uz+i5k9GgR0aB0XMBP+SHilAHwiVgMsCYTB9j9uEA==","signatures":[{"sig":"MEYCIQCr8EgwQr2glsMlCx5Pgli1PiFRCaeDfyM29QLrEiEfFAIhAIz4xxJBTqDDA+LBZi0mhKXalIFMWf9VPrS15T2V6lIX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":173531},"main":"pyfrilet.js","type":"module","gitHead":"0fa4434664f74db775691d596e8f14f26730954a","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.6.0_1773100226641_0.46254820114631534","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"pyfrilet","version":"0.6.1","_id":"pyfrilet@0.6.1","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"2a3bb738fc52f66450a9aa83a44376aee7bea495","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.6.1.tgz","fileCount":5,"integrity":"sha512-8+XBej0laBXe1msF+VhMSmCsxmXttpm8/5U7Mh71Xtv7qjg20Wqr3vvJ+axX9O+5TL/+nLspcklSsAUH5s54nQ==","signatures":[{"sig":"MEYCIQDmh4BznPKmzWZW0B1e+n9tfzda5XA2XIfTg+9CBMmUBgIhAOm/uHwet2TGW9E284HMrC9s0X4jyPxfF6yrtLv8C7jK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":174674},"main":"pyfrilet.js","type":"module","gitHead":"0491616699d5136c17c79f890950a1ce049ae79f","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.6.1_1773101189567_0.3229333504551406","host":"s3://npm-registry-packages-npm-production"}},"0.6.2":{"name":"pyfrilet","version":"0.6.2","_id":"pyfrilet@0.6.2","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"407a0b48a1e89e715f386a8af7b7f3b4e9a39f5a","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.6.2.tgz","fileCount":5,"integrity":"sha512-y8FkVQnjOdHy5vSM1CR/eZsINR/7ijz1ehTRDM+QXUbrEHJrSEnVddvPjlM0XV0y4+ESbAXVZkxLiTO2b2F/YA==","signatures":[{"sig":"MEYCIQCvLVAbVigu/8Gy8GYqNlFcn+YO3fWLUQK04s09+foSJAIhAMNJ7hq/KCrr8K+5SyJA2/VrqsF79r2kAIezgQGF3ID6","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":174822},"main":"pyfrilet.js","type":"module","gitHead":"2960ac9753f93d5b4fab0455fffc03012750f669","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.6.2_1773101655007_0.27297403607771353","host":"s3://npm-registry-packages-npm-production"}},"0.6.3":{"name":"pyfrilet","version":"0.6.3","_id":"pyfrilet@0.6.3","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"3ddbe71dddeaf5c63cf0139437f583de4b41ac37","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.6.3.tgz","fileCount":5,"integrity":"sha512-oQPkMLSi1s/gtPS1zxCq0XR4r+sUlQQ0zjkIAdRNg4v2bc/23wU2/UG2dgVrTl2h5LsFhAWSXZETNwiq9plNiQ==","signatures":[{"sig":"MEUCIQC2yYHqbQX27H8HGpVcVotlntEDPaT+t56pPsynF0xUfwIgUmdv1hW88+3dR+cBRfcZYsHiav8XiGPoj0K/mE2Bx9U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":180554},"main":"pyfrilet.js","type":"module","gitHead":"d592bc54d6523d97f7917d559fa1bd2a8da73921","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.6.3_1773131968200_0.26438854722936234","host":"s3://npm-registry-packages-npm-production"}},"0.6.4":{"name":"pyfrilet","version":"0.6.4","_id":"pyfrilet@0.6.4","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"43fb77af45615aa7fc05e7bc5c7b00b4f8cbeaad","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.6.4.tgz","fileCount":5,"integrity":"sha512-4nUMPTkILh3xARgLLI7+DEUyBPeT4k8inhcHPgLSMHMaZdhog7ivOJyNWSqhaJID5Kha9m+fBVOLSZVrhavnxA==","signatures":[{"sig":"MEYCIQD8FY4UAhSPpYVJ7UgjrEnCTR5vra3MBvakj+oDF8dnvgIhANOpkPohVV2OdQvGqKbYzSGTnen2l1aNtCa+hcssSGth","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":184474},"main":"pyfrilet.js","type":"module","gitHead":"c6add8bc0f3dfe3156f48f7fb991819d449b99a0","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.6.4_1773144176654_0.35166821913110513","host":"s3://npm-registry-packages-npm-production"}},"0.6.5":{"name":"pyfrilet","version":"0.6.5","_id":"pyfrilet@0.6.5","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"00c589addf31b2abc546b54efc86ddfd03826adb","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.6.5.tgz","fileCount":5,"integrity":"sha512-mkro9cdVRnsyYzavJlfSP22GYns42956yuWs/1otS7ciyCsgGsg5oUC0XN+ftxHnkrj+LwIb93V1IE7rcdzKnQ==","signatures":[{"sig":"MEYCIQCLsfmWqEfr8DQczWhXLtB9c/Rl6MjKMh+p9ymHY5yjmAIhAKOuEOa6eAzJaBZT1yvJpL84CFeaKgWEi8xKag45Zdx9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":184445},"main":"pyfrilet.js","type":"module","gitHead":"49b163e887dc6bc77524606e786a0f69c4165fbf","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.6.5_1773162279018_0.39815428842263967","host":"s3://npm-registry-packages-npm-production"}},"0.6.6":{"name":"pyfrilet","version":"0.6.6","_id":"pyfrilet@0.6.6","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"88f9fd5452421dfa2699c6e6084684b7ff39a807","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.6.6.tgz","fileCount":5,"integrity":"sha512-hdO9sbNWRejDoTMYjtU2vZEfhSlqZsl3x7ITNYQL+Lg4SFkNLpkw8+LkUoOZ20+Gd6l+gKEGbXRIuLeZhh4bBQ==","signatures":[{"sig":"MEUCIFVA7FUa6bQepk91yJivset6cCOuQrpEZeUVWWP7ltyFAiEA1x31iBKL29wCTxGJPip/6Eo+IbJuvSBmOMDuy2ENJvQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":195483},"main":"pyfrilet.js","type":"module","gitHead":"f762dd27d3cde30a995434ecd6e85cfd0dc435e2","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.6.6_1773166921866_0.8442668346615549","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"pyfrilet","version":"0.7.0","_id":"pyfrilet@0.7.0","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"244b343ec4637a0549910ccfcf9d494ce7ac6ec7","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.7.0.tgz","fileCount":5,"integrity":"sha512-snEZclhro+TUh8X1NA8wQlAJ2ioUR/NwTr5EMgLq4duV1GFtgmG8XXDankjS9hHIgjtjEPF+NfTByRKbKcGOGQ==","signatures":[{"sig":"MEUCIH7I+Upo/XAQY7tid1jK4LvfPLzwTHZJi47gMi2TcCZyAiEA1U0VgExvc4Ukzl4HCbtBtO69eCN2F1H8yKVD8HGxI78=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":209476},"main":"pyfrilet.js","type":"module","gitHead":"45114299b96cb8efd41d7b059f494e4523933270","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.7.0_1773221477203_0.9519081619759282","host":"s3://npm-registry-packages-npm-production"}},"0.7.1":{"name":"pyfrilet","version":"0.7.1","_id":"pyfrilet@0.7.1","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"f70bd700d538654e613f5aa6d1a608e7302491e1","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.7.1.tgz","fileCount":5,"integrity":"sha512-HbJo2g8W4tJ8ReAJvuAKs28zKjvianVThcDZ8pfjX6/qJBbJkwaniNfxJvLc9id8KAjL9laNe/Rcf8L1HP6QWQ==","signatures":[{"sig":"MEUCIEDCCQDDCgUCTZGjQlXtj9hAXfHDbq08pnxHFlPYhdt7AiEAgjqggKU4QsewXpZtVeeNp38PeAiBls/nwtZrMaJgZfc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":210331},"main":"pyfrilet.js","type":"module","gitHead":"862e061d6e942a77bada7667ed5deb4d74314f4c","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.7.1_1773303583147_0.4075026877001209","host":"s3://npm-registry-packages-npm-production"}},"0.7.2":{"name":"pyfrilet","version":"0.7.2","_id":"pyfrilet@0.7.2","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"ba189bade0500d9c92e03f502ed427e805e6d8cb","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.7.2.tgz","fileCount":5,"integrity":"sha512-SHC2I+nqpfQD9OgJNQxrzvc1IfVxYg47hISxrwFlO4PdUP+041BQxJhSG4BBEZYL5KGOQjOzIZZubGzL/nIXmg==","signatures":[{"sig":"MEQCIEbSKV9M/VivZMPkKUv/N6Jb5B9Sm/5nR9OMn0Fr6R+7AiAykJ5Oj1BINbQCj+fJYpTpzqxWZDjc4xglOWxBrqqsyw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":210959},"main":"pyfrilet.js","type":"module","gitHead":"902b6d36f773206f66ce30e1378d3c8b091c1586","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.7.2_1773311655064_0.0939925336537133","host":"s3://npm-registry-packages-npm-production"}},"0.7.3":{"name":"pyfrilet","version":"0.7.3","_id":"pyfrilet@0.7.3","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"fb6d48874fb017425618935a2b99afefeb446b62","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.7.3.tgz","fileCount":5,"integrity":"sha512-bi2sDsN8pHFQ9eMeFEaUoqC8FSOXCUYNWY/etZeOzC7d5NPE+aULdOeUfK+0BCPT5NrrFWPSuQ5Yd6w5nPPFpQ==","signatures":[{"sig":"MEUCIQCYR7viYG4fK+dMbDPDsnDfDVR6m8MgrnVb0ELcbrj6QgIgONEHa/sZPlSH67XRBUwhCoEl2040kQbTX3hvgvmXOsw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":210969},"main":"pyfrilet.js","type":"module","gitHead":"ec5b2322166588bec25f6f81268254e1d403ae6b","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.7.3_1773328814121_0.818799672733046","host":"s3://npm-registry-packages-npm-production"}},"0.7.4":{"name":"pyfrilet","version":"0.7.4","_id":"pyfrilet@0.7.4","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"dist":{"shasum":"6010930755daf3c1efa990527536a90c2082a18f","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.7.4.tgz","fileCount":5,"integrity":"sha512-82Z/3Gk6rpo5jTC9b7rkRZG0pMFVKRaj4VmjtTDEmkmF814OJFb2xYF2+YfsLnwpp4/9freXb0iC8DemgifSgg==","signatures":[{"sig":"MEQCIGoRPvIVn9/KJEn/cYTu7gxlQ6ZFsIY/X3UbMdNw3C6pAiBL1LsiaoGVXjZ/IZ6odcvhSuWV8+w/bhY6xm2IQmVMpw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":213552},"main":"pyfrilet.js","type":"module","gitHead":"1bd40780d5b59cbd29c4eb4c34a432911d343ed2","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"_npmVersion":"11.9.0","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","directories":{},"_nodeVersion":"24.13.0","_hasShrinkwrap":false,"devDependencies":{"terser":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/pyfrilet_0.7.4_1773507295553_0.3365608506254554","host":"s3://npm-registry-packages-npm-production"}},"0.7.5":{"name":"pyfrilet","version":"0.7.5","type":"module","main":"pyfrilet.js","scripts":{"build":"node build.js","prepublishOnly":"npm run build"},"devDependencies":{"terser":"^5.0.0"},"gitHead":"c4cd0157259538208360123b7f74c67a81cd2bfe","_id":"pyfrilet@0.7.5","description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","_nodeVersion":"24.13.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-8NmZFTfcTFC/sTk2JKb66FzLsG2kGXUt0p3i6KmZgt4WEHfviZT+ps5MwATx3sKfno9BmwABcbCcPgmhUdJSaQ==","shasum":"9df08a7d933e3103d66d4e1880d31fb029fe169e","tarball":"https://registry.npmjs.org/pyfrilet/-/pyfrilet-0.7.5.tgz","fileCount":5,"unpackedSize":213906,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEcwjrUDpE6kc+KgVJocjCZfSO37/nVtenzKlro5gN7dAiEArjvlTMlNqsNf+oCh6EyEeotOUblK34BnCZijbbCEXyU="}]},"_npmUser":{"name":"nopid","email":"nopid@free.fr"},"directories":{},"maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pyfrilet_0.7.5_1773507677786_0.646138008623935"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-05T19:11:17.182Z","modified":"2026-03-14T17:01:18.074Z","0.1.1":"2026-03-05T19:11:17.529Z","0.2.0":"2026-03-05T19:17:25.572Z","0.2.1":"2026-03-05T19:30:20.510Z","0.2.2":"2026-03-05T21:06:34.484Z","0.2.3":"2026-03-05T22:32:26.342Z","0.3.0":"2026-03-06T09:00:54.608Z","0.3.1":"2026-03-06T09:14:21.522Z","0.3.2":"2026-03-06T11:28:29.286Z","0.4.0":"2026-03-07T12:06:24.354Z","0.4.1":"2026-03-07T12:26:59.761Z","0.4.2":"2026-03-07T13:16:51.140Z","0.4.3":"2026-03-07T15:49:49.288Z","0.5.0":"2026-03-09T14:56:53.067Z","0.5.1":"2026-03-09T17:03:20.535Z","0.5.2":"2026-03-09T17:13:01.700Z","0.5.3":"2026-03-09T17:57:54.479Z","0.6.0":"2026-03-09T23:50:26.802Z","0.6.1":"2026-03-10T00:06:29.734Z","0.6.2":"2026-03-10T00:14:15.168Z","0.6.3":"2026-03-10T08:39:28.359Z","0.6.4":"2026-03-10T12:02:56.803Z","0.6.5":"2026-03-10T17:04:39.179Z","0.6.6":"2026-03-10T18:22:02.021Z","0.7.0":"2026-03-11T09:31:17.355Z","0.7.1":"2026-03-12T08:19:43.339Z","0.7.2":"2026-03-12T10:34:15.214Z","0.7.3":"2026-03-12T15:20:14.280Z","0.7.4":"2026-03-14T16:54:55.707Z","0.7.5":"2026-03-14T17:01:17.948Z"},"description":"pyfrilet est un petit système pour publier des animations Python interactives sur une page web. Il combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire dep","maintainers":[{"name":"nopid","email":"nopid@free.fr"}],"readme":"# pyfrilet — documentation\n\npyfrilet est un petit système pour publier des animations Python interactives sur une page web.\nIl combine [p5.js](https://p5js.org/) (dessin 2D) et [Pyodide](https://pyodide.org/) (Python dans le navigateur) avec un éditeur de code intégré qu'on tire depuis le bas de la page.\n\n---\n\n## Démarrage rapide\n```html\n<!doctype html>\n<html lang=\"fr\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>Mon sketch</title>\n  <script src=\"https://cdn.jsdelivr.net/npm/pyfrilet@latest/pyfrilet.min.js\"></script>\n</head>\n<body>\n<script type=\"text/python\">\n\nfrom p5 import *\n\ndef setup():\n    size(400, 400)\n    frameRate(30)\n\ndef draw():\n    background(20)\n    fill('#e0af68')\n    circle(mouseX, mouseY, 40)\n\n</script>\n</body>\n</html>\n```\n\nC'est tout. pyfrilet se charge de démarrer Pyodide, de monter le module `p5`, et de lancer le sketch. Les dépendances (p5.js, Pyodide, ACE) sont chargées depuis des CDN publics par défaut.\n\n---\n\n## Écrire un sketch Python\n\n### API p5 disponible\n\nLe module `p5` expose **toute l'API p5.js** via introspection dynamique : au démarrage, pyfrilet instancie p5.js en arrière-plan, inspecte ses membres, et construit le module Python en conséquence. `from p5 import *` importe donc automatiquement toutes les fonctions et constantes de p5.js, à l'exception des builtins Python qui pourraient entrer en conflit (`map`, `filter`, `set`, `int`, `print`, etc.) et des hooks de cycle de vie (`setup`, `draw`…) que vous définissez vous-même.\n\nL'autocomplétion dans l'éditeur intégré connaît l'ensemble de ces symboles.\n\n> **Noms snake_case** : pyfrilet accepte les noms de fonctions, callbacks et attributs en style Python et les convertit silencieusement en camelCase. Les deux styles sont équivalents :\n> - fonctions : `create_graphics`, `load_image`, `no_stroke`…\n> - callbacks : `key_pressed`, `mouse_pressed`, `mouse_dragged`…\n> - attributs dynamiques : `key_is_pressed`, `frame_count`, `mouse_x`, `mouse_y`…\n\nLes fonctions ci-dessous sont un aperçu des plus couramment utilisées, à titre d'illustration :\n\n| Fonction | Description |\n|---|---|\n| `background(v)` | Efface le fond. Valeur grise (0–255) ou couleur CSS (`'#ff0000'`, `'red'`…). |\n| `fill(...)` | Couleur de remplissage. |\n| `stroke(...)` | Couleur de contour. |\n| `noStroke()` | Supprime le contour. |\n| `noFill()` | Supprime le remplissage. |\n| `rect(x, y, w, h)` | Rectangle. |\n| `circle(x, y, d)` | Cercle (x, y = centre, d = diamètre). |\n| `ellipse(x, y, w, h)` | Ellipse. |\n| `line(x1, y1, x2, y2)` | Segment. |\n| `text(s, x, y)` | Affiche une chaîne. |\n| `textSize(sz)` | Taille du texte en pixels. |\n| `textAlign(h, v)` | Alignement horizontal et vertical. |\n| `push()` / `pop()` | Sauvegarde / restaure l'état graphique. |\n| `translate(x, y)` | Déplace l'origine. |\n| `rotate(angle)` | Rotation (angle en radians). |\n| `scale(sx, sy)` | Mise à l'échelle. |\n| `image(img, x, y)` | Affiche une image. |\n| `loadImage(url)` | Charge une image (à appeler dans `preload()`). |\n| `random(min, max)` | Nombre aléatoire entre min et max. |\n| `noise(x)` | Bruit de Perlin. |\n\nPour la référence complète, consulter la [documentation p5.js](https://p5js.org/reference/).\n\n#### Cycle de vie\n\nCes fonctions sont définies par l'utilisateur et appelées automatiquement par pyfrilet :\n\n| Fonction | Rôle |\n|---|---|\n| `preload()` | Appelée avant `setup()`. Utilisée pour charger des ressources (`loadImage`…) — p5 attend la fin du chargement avant de continuer. |\n| `setup()` | Appelée une seule fois au démarrage. Obligatoire pour appeler `size()` ou `frameRate()`. |\n| `draw()` | Appelée à chaque frame. **Obligatoire.** |\n| `windowResized()` | Appelée quand la zone d'affichage change (redimensionnement de la fenêtre ou du tiroir éditeur). |\n| `mousePressed()` | Bouton souris enfoncé. |\n| `mouseReleased()` | Bouton souris relâché. |\n| `mouseDragged()` | Souris déplacée bouton enfoncé. |\n| `mouseMoved()` | Souris déplacée sans bouton (survol). |\n| `mouseWheel()` | Molette / pinch trackpad. `deltaY` est accessible via `p5py._p.deltaY`. |\n| `doubleClicked()` | Double-clic. |\n| `keyPressed()` | Touche enfoncée. `keyCode` et `key` sont déjà à jour au moment de l'appel. |\n| `keyReleased()` | Touche relâchée. Utile pour les mouvements continus dans les jeux. |\n| `keyTyped()` | Touche pressée avec caractère imprimable. |\n| `touchStarted()` | Début de contact tactile. `touches[]` est accessible via p5. |\n| `touchMoved()` | Contact tactile déplacé. Utile pour le multi-touch (pinch zoom…). |\n| `touchEnded()` | Fin de contact tactile. |\n\n> **Watchdog `draw()`** : pyfrilet surveille le temps d'exécution de `draw()` via `sys.settrace`. Si une exécution dépasse **300 ms**, le sketch est arrêté et une erreur est affichée — cela protège le navigateur contre les boucles infinies accidentelles (`while True: pass`, récursion sans fin…). La trace est vérifiée toutes les 100 lignes Python pour minimiser l'overhead. Pour désactiver ce comportement (calculs intensifs légitimes hors de `draw()`), ajouter `data-no-watchdog` sur la balise `<script src=\"pyfrilet.js\">` :\n>\n> ```html\n> <script src=\"pyfrilet.js\" data-no-watchdog></script>\n> ```\n\n#### Fonctions pyfrilet (hors p5.js standard)\n\n| Fonction | Description |\n|---|---|\n| `size(w, h)` | Crée ou redimensionne le canvas. Le canvas est mis à l'échelle CSS pour remplir l'écran sans déformation. Retourne le `p5.Element` du canvas. |\n| `size(w, h, WEBGL)` | Crée un canvas en mode WebGL 3D. `WEBGL` est une constante p5 importable avec `from p5 import *`. |\n| `size('max')` | Canvas plein écran, redimensionné dynamiquement. |\n| `createCanvas(w, h)` | Alias de `size()` — accepte les mêmes arguments et retourne le canvas. Permet de copier des exemples p5.js sans adaptation. |\n| `smooth()` | Active l'antialiasing (par défaut). |\n| `noSmooth()` | Désactive l'antialiasing (pixel art). Affecte formes **et** texte. |\n| `sketchTitle(s)` | Affiche un texte dans la barre de contrôle. À appeler dans `setup()`. |\n| `getCanvas()` | Retourne le `p5.Element` wrappant le canvas. Utile pour appeler des méthodes p5.Element comme `.drop()`. À appeler dans `setup()` ou après. |\n| `safe_proxy(fn)` | Wrape une fonction Python pour l'utiliser comme callback JS (équivalent de `create_proxy`) en capturant les erreurs et en les affichant dans le terminal. À préférer à `create_proxy` pour les callbacks utilisateur (`.drop()`, événements DOM…). |\n| `persist()` | Synchronise `/persist` vers IndexedDB (fire-and-forget). Fonctionne en mode p5 et en mode terminal. Disponible via `from p5 import *` ou directement en mode terminal. |\n\n#### Propriétés dynamiques\n\nCes variables sont mises à jour automatiquement avant chaque appel à `draw()`, `keyPressed()` et `mousePressed()`, y compris si elles ont été importées avec `from p5 import *` :\n```python\nmouseX, mouseY   # position de la souris dans le repère du canvas\nwidth, height    # dimensions logiques du canvas\nframeCount       # numéro de la frame courante\nkey              # dernière touche appuyée (caractère)\nkeyCode          # code numérique de la dernière touche\n```\n\n> **Note sur `keyCode`** : p5.js expose des constantes nommées (`LEFT_ARROW`, `RIGHT_ARROW`, `UP_ARROW`, `DOWN_ARROW`, `ENTER`, `BACKSPACE`…) directement importables avec `from p5 import *`.\n\n### Exemple : plein écran réactif\n```python\nfrom p5 import *\n\ndef setup():\n    size('max')\n    frameRate(60)\n    sketchTitle(\"Mon sketch · Échap → éditeur\")\n\ndef windowResized():\n    size('max')   # redimensionne le canvas quand le tiroir bouge\n\ndef draw():\n    background(0)\n    noStroke()\n    fill('#7aa2f7')\n    circle(width / 2, height / 2, min(width, height) * 0.4)\n```\n\n### Exemple : navigation clavier\n```python\nfrom p5 import *\n\npage = 0\n\ndef setup():\n    size(400, 300)\n\ndef keyPressed():\n    global page\n    if keyCode == RIGHT_ARROW: page += 1\n    if keyCode == LEFT_ARROW:  page -= 1\n\ndef draw():\n    background(20)\n    smooth()\n    fill('#e0af68')\n    textSize(16)\n    text(\"page \" + str(page), 160, 150)\n```\n\n### Packages Python tiers\n\npyfrilet détecte automatiquement les imports du sketch et charge les packages disponibles dans la distribution Pyodide avant l'exécution. Il n'y a rien à faire :\n```python\nfrom p5 import *\nimport numpy as np        # chargé automatiquement\nimport networkx as nx     # chargé automatiquement\n\ndef setup():\n    size(400, 400)\n\ndef draw():\n    background(20)\n```\n\nUn message \"Chargement des dépendances…\" s'affiche pendant le téléchargement. Seuls les packages inclus dans la [distribution Pyodide](https://pyodide.org/en/stable/usage/packages-in-pyodide.html) sont supportés (numpy, scipy, pandas, networkx, pillow…). Les packages pip arbitraires ne sont pas supportés.\n\n> **`rich` et `pygments`** sont chargés d'office au démarrage — ils alimentent l'affichage coloré des erreurs et sont disponibles dans vos sketches sans import supplémentaire.\n\n### Glisser-déposer de fichiers\n\nPour recevoir des fichiers glissés sur le canvas, on utilise `getCanvas().drop()` avec `safe_proxy` :\n```python\nfrom p5 import *\n\nimg = None\n\ndef setup():\n    size(400, 400)\n    getCanvas().drop(safe_proxy(on_drop))\n\ndef on_drop(file):\n    global img\n    if not file.type.startswith(\"image\"):\n        return\n    if img:\n        img.remove()\n    img = createImg(file.data, \"\")\n    img.hide()\n\ndef draw():\n    background(40)\n    if img:\n        image(img, 0, 0, width, height)\n```\n\n`safe_proxy` est préférable à `create_proxy` (de `pyodide.ffi`) pour les callbacks utilisateur : les erreurs qui surviennent dans le callback sont capturées et affichées proprement dans le terminal au lieu de disparaître silencieusement dans la console du navigateur.\n\n---\n\n### Note sur `smooth()` / `noSmooth()` et le texte\n\nPar défaut le canvas est rendu en mode antialiasé. `noSmooth()` bascule en mode pixel art — formes **et** texte sont pixelisés. Pour mélanger les deux dans le même `draw()` :\n```python\nnoSmooth()\nrect(10, 10, 80, 80)   # bords nets\nsmooth()\ntextSize(14)\ntext(\"lisible\", 10, 120)  # texte antialiasé\n```\n\n---\n\n### Gestion des erreurs\n\nQuelle que soit l'origine de l'erreur (mode p5 ou mode terminal), pyfrilet affiche un traceback formaté par [rich](https://rich.readthedocs.io/) dans le terminal intégré : cadre coloré, fichier et numéro de ligne, extrait du code source avec quelques lignes de contexte autour de la ligne fautive. Les frames internes de pyfrilet sont automatiquement filtrées — seul le code utilisateur apparaît.\n\nEn mode p5, le sketch est arrêté dès la première erreur (y compris les erreurs au niveau module, hors des fonctions `setup`/`draw`) et le traceback s'affiche en overlay semi-transparent par-dessus le canvas. Corriger le code et relancer suffit à reprendre.\n\n---\n\n## Mode terminal\n\nQuand le code Python ne contient **aucun import de `p5`**, pyfrilet bascule automatiquement en **mode terminal** : le canvas est remplacé par un terminal [xterm.js](https://xtermjs.org/) qui reçoit `stdout` et `stderr`.\n\nCe mode permet d'écrire des programmes Python classiques — algorithmes, structures de données, jeux textuels, visualisations — sans aucun lien avec p5.\n\n### async/await transparent\n\nLe mode terminal tourne dans la boucle asyncio de Pyodide. Comme `input()` doit attendre la saisie de l'utilisateur, le moteur d'exécution est fondamentalement asynchrone. pyfrilet s'en charge automatiquement : **le code utilisateur n'a pas besoin de connaître async/await**.\n\n```python\n# Pas d'import p5 → mode terminal automatique\n# Ni async, ni await : ça marche simplement\n\ndef demander_nombre():\n    return int(input(\"Un nombre : \"))\n\nn = demander_nombre()\nprint(f\"Le double : {n * 2}\")\n```\n\nEn coulisses, pyfrilet applique une transformation AST avant l'exécution :\n- toutes les `def` sont converties en `async def`\n- tous les appels de fonctions sont wrappés dans `await` automatiquement\n- `time.sleep(x)` est redirigé vers `asyncio.sleep(x)` pour ne pas geler l'onglet\n\n```python\nimport time\n\ndef compte_a_rebours(n):\n    for i in range(n, 0, -1):\n        print(i)\n        time.sleep(1)   # → asyncio.sleep automatiquement\n    print(\"Go !\")\n\ncompte_a_rebours(3)\n```\n\n### Limites de la transformation automatique\n\nLa transformation couvre les cas courants mais a des angles morts :\n\n**Les méthodes dunder (`__init__`, `__str__`…) restent synchrones.** Python les appelle directement sans passer par le wrapper. Elles ne peuvent donc pas appeler `input()` :\n\n```python\nclass Animal:\n    def __init__(self, nom):\n        self.nom = nom          # OK\n        # self.nom = input()   # ← ne fonctionnerait pas ici\n\n    def parler(self):           # converti en async def automatiquement\n        return input(f\"{self.nom} dit : \")   # OK ici\n```\n\n**Les lambdas restent synchrones** (Python ne supporte pas les lambdas async) — ne pas y appeler `input()`.\n\n**Le sleep rebindé n'est pas détecté.** pyfrilet reconnaît `sleep(x)`, `time.sleep(x)` et `asyncio.sleep(x)` et les redirige tous vers un sleep annulable. En revanche `mon_sleep = time.sleep; mon_sleep(x)` ne sera pas intercepté.\n\n### Quand écrire async/await explicitement\n\nPour des programmes plus avancés, on peut écrire `async`/`await` directement — pyfrilet les respecte et ne double-wrappe pas :\n\n```python\nimport asyncio\nfrom rich.progress import Progress\n\nasync def charger():\n    with Progress(auto_refresh=False) as progress:\n        task = progress.add_task(\"calcul…\", total=100)\n        for i in range(100):\n            await asyncio.sleep(0.03)\n            progress.advance(task)\n            progress.refresh()\n\nawait charger()\n```\n\nEn pratique : pour des scripts simples avec `input()` et `time.sleep()`, pas besoin de `async`/`await`. Dès qu'on fait de l'animation fine, des appels réseau, ou qu'on combine plusieurs coroutines, les écrire explicitement est plus sûr et plus lisible.\n\n### `input()`\n\n`input()` est entièrement supporté : le programme se met en attente, le terminal affiche le prompt et accepte la saisie clavier.\n```python\nnom = input(\"Ton prénom : \")\nprint(f\"Bonjour, {nom} !\")\n```\n\nCtrl+C interrompt une saisie en cours et retourne `None` — prévoir un guard si nécessaire :\n```python\nval = input(\"Valeur : \")\nif val is None:\n    print(\"annulé\")\n```\n\n### rich\n\n`rich` est disponible directement — tableaux, couleurs ANSI, barres de progression :\n```python\nfrom rich.console import Console\nfrom rich.table import Table\n\nconsole = Console()\n\ntable = Table(title=\"Planètes\")\ntable.add_column(\"Nom\")\ntable.add_column(\"Diamètre (km)\", justify=\"right\")\ntable.add_row(\"Mercure\", \"4 879\")\ntable.add_row(\"Vénus\",   \"12 104\")\ntable.add_row(\"Terre\",   \"12 742\")\nconsole.print(table)\n```\n\n### Persistence (IndexedDB)\n\nPour conserver des données entre les rechargements de page, pyfrilet monte automatiquement un répertoire IndexedDB sur `/persist` au démarrage de chaque sketch — aussi bien en mode p5 qu'en mode terminal. Ce répertoire est disponible sans aucune configuration.\n\nLa fonction `persist()` déclenche la synchronisation MEMFS → IndexedDB. Elle fonctionne dans les deux modes sans `await` :\n\n```python\nimport json, os\n\nDB = '/persist/data.json'\n\n# Lire\ndata = json.loads(open(DB).read()) if os.path.exists(DB) else {}\n\n# Modifier et persister\ndata['compteur'] = data.get('compteur', 0) + 1\nwith open(DB, 'w') as f:\n    json.dump(data, f)\npersist()   # fire-and-forget — fonctionne en p5 et en terminal\n```\n\nEn mode p5, importer avec `from p5 import persist` ou `from p5 import *`. En mode terminal, `persist` est disponible directement sans import.\n\n> La synchronisation est asynchrone côté navigateur : la Promise est lancée dès l'appel et exécutée dès que la stack JS se libère. En mode terminal, on peut aussi `await _pfSyncIdbfs()` depuis `js` pour attendre explicitement la fin de l'écriture.\n\n### Relancer\n\nLe bouton ▶ (ou `Shift+Entrée`) interrompt le programme en cours et relance l'exécution depuis le début. L'interruption est propre même si le programme est en attente de `input()` ou en train de dormir dans un `time.sleep()` — ces deux opérations sont annulables sans délai. Si le programme est suspendu sur autre chose (réseau, calcul long…), pyfrilet attend au maximum 3 secondes avant de forcer le nouveau départ.\n\nCliquer plusieurs fois rapidement sur ▶ est sans danger : seul le **dernier** clic produit une exécution, les intermédiaires sont ignorés.\n\n---\n\n## Mode sans éditeur\n\nDeux attributs permettent d'intégrer pyfrilet dans un contexte où l'éditeur de code n'est pas souhaité.\n\n### `data-no-editor`\n\nCache entièrement le tiroir éditeur. Le sketch tourne en pleine page, sans interface visible. Les erreurs s'affichent en overlay semi-transparent au bas du canvas plutôt que dans le tiroir.\n\n```html\n<script src=\"pyfrilet.js\" data-no-editor></script>\n```\n\n`Shift+Entrée` reste actif pour relancer le sketch. Tous les autres raccourcis clavier (Échap, Ctrl+S, Ctrl+R) sont désactivés pour ne pas interférer avec la page hôte.\n\n### `data-pyfrilet-detached`\n\nMode de rendu découplé, conçu pour intégrer un sketch dans une page qui a sa propre mise en page (présentation RevealJS, article interactif…). Implique `data-no-editor`.\n\n```html\n<script src=\"pyfrilet.js\" data-pyfrilet-detached></script>\n```\n\nDifférences avec le mode normal :\n\n- Le markup pyfrilet est **ajouté** à `document.body` au lieu de le remplacer — la page hôte est préservée.\n- `#pf-sketch` (le conteneur du canvas) est rendu hors-écran et exposé sous `window.__pyfriletSketchEl` pour qu'un plugin externe puisse le déplacer dans n'importe quel élément de la page.\n- Le **localStorage est ignoré** — le code Python est toujours lu depuis le HTML source. Dans un contexte intégré, la page est la source de vérité.\n\n---\n\n## Intégration RevealJS (`reveal-pyfrilet.js`)\n\n`reveal-pyfrilet.js` est un plugin RevealJS qui connecte un sketch pyfrilet à une présentation. Le canvas devient un élément comme les autres dans les slides — RevealJS gère entièrement le layout.\n\n### Principe\n\nLe plugin crée un conteneur hors-écran (le « garage ») au démarrage. À chaque changement de slide, il déplace `#pf-sketch` dans l'élément `[data-pyfrilet-canvas]` de la slide active, et appelle `window.pyfrilet_on_step(n)` avec le step déclaré sur la section. Le canvas est ainsi partagé entre toutes les slides — l'état Python persiste d'une slide à l'autre.\n\n### Démarrage rapide\n\n**1. Déclarer le sketch hors des slides :**\n\n```html\n<script src=\"pyfrilet.js\" data-pyfrilet-detached></script>\n\n<script type=\"text/python\">\nfrom p5 import *\nimport js\n\nstep = 0\n\ndef setup():\n    size(540, 380)\n    frame_rate(30)\n\ndef draw():\n    background(20)\n    # utilise la variable `step` pour changer d'état visuel\n\ndef on_step(n, payload=None):\n    global step\n    step = int(n)\n\njs.window.pyfrilet_on_step = on_step\n</script>\n```\n\n**2. Placer `[data-pyfrilet-canvas]` dans les slides qui doivent afficher le canvas :**\n\n```html\n<section data-pyfrilet-step=\"1\">\n  <div class=\"slide-split\">\n    <div class=\"text\">\n      <h2>Mon titre</h2>\n      <p>Mon texte...</p>\n    </div>\n    <div data-pyfrilet-canvas></div>\n  </div>\n</section>\n```\n\nLes slides sans `[data-pyfrilet-canvas]` n'affichent pas le canvas — le sketch continue de tourner en arrière-plan.\n\n**3. Initialiser RevealJS avec le plugin :**\n\n```html\n<script src=\"reveal.js\"></script>\n<script src=\"reveal-pyfrilet.js\"></script>\n<script>\n  Reveal.initialize({\n    plugins: [ RevealPyfrilet ],\n  });\n</script>\n```\n\n### Attributs\n\n| Attribut | Emplacement | Rôle |\n|---|---|---|\n| `data-pyfrilet-step=\"n\"` | `<section>` | Step envoyé à `on_step(n)` à l'activation de la slide |\n| `data-pyfrilet-step=\"n\"` | `.fragment` | Step envoyé à `on_step(n)` à l'apparition du fragment |\n| `data-pyfrilet-canvas` | n'importe quel élément dans la slide | Emplacement où le canvas est injecté |\n\n### Dimensionnement du canvas\n\nLe plugin injecte `max-width:100%; max-height:100%; width:auto; height:auto` sur le canvas. Le slot `[data-pyfrilet-canvas]` doit donc être un conteneur dont la largeur **et** la hauteur sont définies — le canvas s'y inscrit en conservant son ratio (défini par `size(W, H)` en Python), exactement comme `object-fit:contain`. La mise en page à l'intérieur des slides est entièrement libre et ne dépend pas du plugin.\n\n### Relancer le sketch en cours de présentation\n\n`Shift+Entrée` relance le sketch (Python repart de zéro). Le plugin écoute l'événement `pyfrilet:ready` déclenché à la fin du re-run et ré-envoie automatiquement le step de la slide courante — le sketch restaure son état visuel sans intervention.\n\n### Hook Python\n\nLe seul contrat entre le sketch et le plugin est l'exposition d'un callable JS :\n\n```python\nimport js\n\ndef on_step(n, payload=None):\n    global step\n    step = int(n)\n\njs.window.pyfrilet_on_step = on_step\n```\n\n`payload` est toujours `None` dans cette version — réservé pour des données structurées futures.\n\n\n---\n\n## Interface utilisateur\n\nLa barre de contrôle est collée en bas de l'écran.\n\n| Élément | Action |\n|---|---|\n| ☰ (hamburger, à gauche) | Ouvre / ferme le tiroir éditeur |\n| Glisser la barre vers le haut/bas | Redimensionne le tiroir — relâcher sous 120 px le referme |\n| ▶ | Relance l'exécution du code (sans fermer l'éditeur) |\n| ✏️ | Ouvre l'éditeur en **plein écran** ; referme si déjà ouvert |\n| 💾 | Télécharge la page en HTML autonome (voir ci-dessous) |\n| ⏺ | Démarre l'enregistrement WebM du canvas ; devient ⏹ pendant l'enregistrement — cliquer pour arrêter et télécharger |\n| ↻ | Réinitialise **tous les onglets** à la version du fichier source (confirmation demandée). Un point orange apparaît sur le bouton dès qu'un onglet a été modifié par rapport à sa version d'origine. |\n\n### Raccourcis clavier\n\n| Raccourci | Action |\n|---|---|\n| `Shift+Entrée` | Relance l'exécution (depuis l'éditeur ou depuis le sketch) |\n| `Échap` | Ouvre le tiroir si fermé, ferme si ouvert |\n| `Ctrl+S` | Sauvegarde le code dans le localStorage |\n| `Ctrl+R` | Réinitialise **tous les onglets** à la version d'origine (confirmation demandée) |\n\nQuand le tiroir se ferme, le focus clavier est automatiquement donné au canvas — les événements `keyPressed()` du sketch fonctionnent sans clic préalable.\n\nLe code est **sauvegardé automatiquement** dans le `localStorage` à chaque modification. pyfrilet enregistre un snapshot JSON complet de tous les onglets (structure, types, contenus — y compris les blocs cachés et Markdown). À la prochaine visite, la page s'affiche exactement telle qu'elle a été laissée, avec le même nombre d'onglets et les mêmes contenus. Cliquer sur ↻ efface le snapshot et restaure la structure et le contenu du fichier HTML source.\n\n### Télécharger\n\nLe bouton 💾 génère un fichier `sketch.html` autonome : il référence pyfrilet depuis jsDelivr et reconstruit tous les blocs `<script>` tels qu'ils sont dans l'éditeur au moment du clic, en préservant leur structure (onglets, blocs cachés, blocs en lecture seule). Le fichier produit charge p5.js et Pyodide depuis le CDN et n'a besoin d'aucun serveur pour fonctionner.\n\n---\n\n## Onglets (utilisation avancée)\n\nQuand une page contient plusieurs blocs de code, pyfrilet affiche une barre d'onglets dans l'éditeur. Chaque bloc est déclaré avec un `<script>` séparé.\n\nTous les blocs Python partagent le même namespace : les variables et fonctions définies dans un bloc sont visibles dans les autres.\n\n### Attributs disponibles\n\n| Attribut | Effet |\n|---|---|\n| `data-tab=\"Nom\"` | Crée un onglet visible avec ce libellé |\n| `data-readonly` | L'onglet est visible mais non modifiable (cadenas affiché) |\n| `data-hidden` | Le bloc est exécuté mais n'apparaît pas dans l'éditeur |\n| `type=\"text/markdown\"` | Le contenu est rendu en Markdown (non exécuté) |\n\n### Exemple : énoncé + code utilitaire + zone élève\n```html\n<script type=\"text/markdown\" data-tab=\"Énoncé\">\n# Exercice\n\nComplète la fonction `dessiner()` pour afficher un cercle rouge au centre du canvas.\n</script>\n\n<script type=\"text/python\" data-tab=\"Utilitaires\" data-readonly>\n# Fonctions fournies — non modifiables\ndef rouge():\n    fill(255, 0, 0)\n    no_stroke()\n</script>\n\n<script type=\"text/python\" data-tab=\"Ta solution\">\nfrom p5 import *\n\ndef setup():\n    size(400, 400)\n\ndef draw():\n    background(20)\n    # à toi de jouer !\n</script>\n```\n\n### Bloc caché\n\nUn bloc `data-hidden` est concaténé au code exécuté mais invisible dans l'éditeur. Utile pour du code d'initialisation ou de vérification qu'on ne souhaite pas exposer :\n```html\n<script type=\"text/python\" data-hidden>\n# Code invisible — exécuté en premier\nPALETTE = ['#7aa2f7', '#e0af68', '#9ece6a']\n</script>\n\n<script type=\"text/python\" data-tab=\"Sketch\">\nfrom p5 import *\n\ndef setup():\n    size(400, 400)\n\ndef draw():\n    background(20)\n    fill(PALETTE[frameCount // 60 % 3])\n    circle(200, 200, 100)\n</script>\n```\n\n### Rendu des onglets Markdown\n\nLes onglets Markdown sont affichés sur fond clair avec une mise en page soignée : largeur de lecture limitée à 680 px, centrage automatique sur grand écran, police [Alegreya Sans](https://fonts.google.com/specimen/Alegreya+Sans) (chargée depuis Google Fonts en mode CDN). Les diagrammes Mermaid utilisent le thème neutre (clair).\n\nEn mode déploiement local sans accès internet, la fonte se replie sur Georgia.\n\nLe contenu d'un onglet `type=\"text/markdown\"` est rendu avec [marked](https://marked.js.org/) et supporte les formules mathématiques via [KaTeX](https://katex.org/) et les diagrammes via [Mermaid](https://mermaid.js.org/).\n\n**Formules mathématiques (KaTeX) :**\n\n| Syntaxe | Rendu |\n|---|---|\n| `$f(x) = x^2$` | Formule inline dans le texte |\n| `$$\\sum_{i=0}^{n} i = \\frac{n(n+1)}{2}$$` | Bloc centré sur sa propre ligne |\n\n**Diagrammes (Mermaid) :**\n\nUn bloc de code avec le langage `mermaid` est rendu comme un diagramme SVG :\n```markdown\n    ```mermaid\n    graph TD\n        A[Départ] --> B{Condition}\n        B -->|oui| C[Résultat 1]\n        B -->|non| D[Résultat 2]\n    ```\n```\n\nMermaid supporte de nombreux types de diagrammes : `graph`, `sequenceDiagram`, `classDiagram`, `flowchart`, `gantt`, `pie`… Voir la [documentation Mermaid](https://mermaid.js.org/intro/) pour la syntaxe complète.\n\n**Exemple combiné :**\n```html\n<script type=\"text/markdown\" data-tab=\"Cours\">\n# Algorithme de Dijkstra\n\nSoit un graphe $G = (V, E)$ avec des poids $w(u, v) \\geq 0$.\n\nL'algorithme maintient un ensemble $S$ de sommets dont la distance\nminimale depuis la source $s$ est connue. À chaque étape on extrait\nle sommet $u \\notin S$ qui minimise :\n\n$$d(s, u) = \\min_{v \\in S} \\left( d(s, v) + w(v, u) \\right)$$\n\nLa complexité est $O((V + E) \\log V)$ avec un tas binaire.\n    ```mermaid\n    graph LR\n        A((1)) -->|4| B((2))\n        A -->|1| C((3))\n        C -->|2| B\n        B -->|1| D((4))\n    ```\n</script>\n```\n\nLes blocs Python sont concaténés dans l'ordre du DOM avant exécution : blocs cachés et visibles sont traités ensemble, dans l'ordre où ils apparaissent dans le HTML. L'onglet actif dans l'éditeur n'influence pas l'exécution.\n\n> **Numéros de ligne** : les numéros affichés par l'éditeur ACE dans chaque onglet correspondent aux numéros réels dans le code Python exécuté. Un message d'erreur mentionnant la ligne 142 pointe donc directement vers la bonne ligne dans le bon onglet.\n\n---\n\n## Déploiement local (mode `vendor/`)\n\nPar défaut, pyfrilet charge p5.js, Pyodide et ACE depuis des CDN publics. Pour un déploiement entièrement local — intranet, usage hors ligne, ou pour ne pas dépendre de services tiers — on peut héberger les dépendances soi-même.\n\n### Configuration\n\nCes attributs se placent de préférence sur la balise `<script src=\"pyfrilet.js\">` elle-même. Pour la rétrocompatibilité, `data-sources` et `data-vendor` sont également acceptés sur le premier bloc `<script type=\"text/python\">`.\n\n| Attribut | Valeurs | Description |\n|---|---|---|\n| `data-sources` | `cdn` (défaut) / `local` | Source des dépendances JS (CDN ou dossier `vendor/`) |\n| `data-vendor` | chemin | Chemin vers le dossier vendor, relatif à la page HTML (défaut : `vendor/`) |\n| `data-no-watchdog` | — | Désactive le watchdog `draw()` (calculs intensifs légitimes) |\n| `data-no-editor` | — | Cache le tiroir éditeur — canvas uniquement, erreurs en overlay |\n| `data-pyfrilet-detached` | — | Mode découplé pour intégration dans une page hôte (implique `data-no-editor`) |\n\n```html\n<!-- CDN, éditeur visible (comportement par défaut) -->\n<script src=\"pyfrilet.js\"></script>\n\n<!-- Local, sans éditeur -->\n<script src=\"pyfrilet.js\" data-sources=\"local\" data-vendor=\"vendor/\" data-no-editor></script>\n\n<!-- Intégration RevealJS -->\n<script src=\"pyfrilet.js\" data-pyfrilet-detached></script>\n\n<!-- Rétrocompat (ancienne syntaxe) -->\n<script src=\"pyfrilet.js\"></script>\n<script type=\"text/python\" data-sources=\"local\" data-vendor=\"vendor/\">\n  …\n</script>\n```\n\n`data-vendor` indique le chemin vers le dossier `vendor/` **relatif à la page HTML**. La valeur par défaut est `vendor/`.\n\n### Structure de fichiers\n```\nmon-projet/\n├── pyfrilet.js\n├── mon-sketch.html\n└── vendor/\n    ├── p5.min.js\n    ├── ace.min.js\n    ├── mode-python.min.js\n    ├── theme-monokai.min.js\n    ├── ext-language_tools.min.js\n    ├── ext-searchbox.min.js\n    ├── xterm.min.css\n    ├── xterm.min.js\n    ├── addon-fit.min.js\n    ├── addon-unicode11.min.js\n    ├── marked.min.js                   ← uniquement si onglets Markdown\n    ├── katex.min.css                   ← uniquement si onglets Markdown\n    ├── katex.min.js                    ← uniquement si onglets Markdown\n    ├── marked-katex-extension.js       ← uniquement si onglets Markdown\n    ├── mermaid.min.js                  ← uniquement si onglets Markdown\n    └── pyodide/\n        ├── pyodide.js\n        ├── pyodide.asm.wasm\n        ├── python_stdlib.zip\n        └── … (autres fichiers Pyodide)\n```\n\n### Télécharger les dépendances\n\n**p5.js**\n```\nhttps://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.min.js\n```\n\n**ACE editor** (5 fichiers)\n```\nhttps://cdnjs.cloudflare.com/ajax/libs/ace/1.36.5/ace.min.js\nhttps://cdnjs.cloudflare.com/ajax/libs/ace/1.36.5/mode-python.min.js\nhttps://cdnjs.cloudflare.com/ajax/libs/ace/1.36.5/theme-monokai.min.js\nhttps://cdnjs.cloudflare.com/ajax/libs/ace/1.36.5/ext-language_tools.min.js\nhttps://cdnjs.cloudflare.com/ajax/libs/ace/1.36.5/ext-searchbox.min.js\n```\n\n**xterm.js** (4 fichiers)\n```\nhttps://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.min.css\nhttps://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.min.js\nhttps://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.10.0/lib/addon-fit.min.js\nhttps://cdn.jsdelivr.net/npm/@xterm/addon-unicode11@0.8.0/lib/addon-unicode11.min.js\n```\nRenommer respectivement en `xterm.min.css`, `xterm.min.js`, `addon-fit.min.js`, `addon-unicode11.min.js`.\n\n**marked.js + KaTeX + Mermaid** (uniquement si onglets Markdown)\n```\nhttps://cdnjs.cloudflare.com/ajax/libs/marked/12.0.0/marked.min.js\nhttps://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css\nhttps://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.js\nhttps://cdn.jsdelivr.net/npm/marked-katex-extension@5.1.1/lib/index.umd.js\nhttps://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js\n```\nRenommer `index.umd.js` en `marked-katex-extension.js` dans le dossier vendor.\n\n**Pyodide** — télécharger l'archive complète depuis les releases GitHub :\n```\nhttps://github.com/pyodide/pyodide/releases/tag/0.26.4\n```\nExtraire le contenu dans `vendor/pyodide/`.\n\n### Serveur local\n\nLes navigateurs bloquent le chargement de fichiers locaux (`file://`) pour des raisons de sécurité. Il faut un serveur HTTP minimal pour tester en local :\n```bash\n# Python 3\npython -m http.server 8000\n\n# Node.js\nnpx serve .\n```\n\nPuis ouvrir `http://localhost:8000/mon-sketch.html`.\n\n---\n\n## Build et publication\n\nLe build est géré par `build.js` (Node.js + Terser). Il concatène les fragments de `src/`, injecte CSS et HTML, puis génère `pyfrilet.js` (lisible) et `pyfrilet.min.js`.\n```bash\nnpm run build        # génère pyfrilet.js + pyfrilet.min.js\n````\n\nLe hook `prepublishOnly` dans `package.json` déclenche le build automatiquement avant chaque `npm publish`. Le flux complet d'une release :\n```bash\ngit add .\ngit commit -m \"feat: ...\"   # committer le travail\n\nnpm version patch            # (ou minor / major) — modifie package.json, commit + tag\nnpm publish                  # build automatique puis publication sur npm\n\ngit push && git push --tags  # pousser commits et tag sur Codeberg\n```\n\n---\n\n## Licence\n\npyfrilet.js est distribué sous **GNU Lesser General Public License v2.1** (LGPL-2.1).\n\nEn pratique cela signifie :\n\n- Tu peux l'utiliser dans un projet propriétaire ou open source sans contrainte.\n- Si tu modifies pyfrilet.js lui-même, tu dois publier ces modifications sous LGPL.\n- Tu n'as pas à inclure p5.js, Pyodide ou ACE dans ton dépôt : pyfrilet les charge dynamiquement, il n'y a pas de liaison statique.\n\n### Licences des dépendances\n\npyfrilet ne contient aucun code de ces bibliothèques ; elles sont chargées séparément au moment de l'exécution. Leurs licences s'appliquent à elles seules :\n\n| Bibliothèque | Licence |\n|---|---|\n| [p5.js](https://p5js.org/) | LGPL 2.1 |\n| [Pyodide](https://pyodide.org/) | MPL 2.0 |\n| [ACE editor](https://ace.c9.io/) | BSD 3-Clause |\n| [xterm.js](https://xtermjs.org/) | MIT |\n| [marked](https://marked.js.org/) | MIT |\n| [KaTeX](https://katex.org/) | MIT |\n| [marked-katex-extension](https://github.com/UziTech/marked-katex-extension) | MIT |\n| [Mermaid](https://mermaid.js.org/) | MIT |\n| [rich](https://rich.readthedocs.io/) | MIT |\n\n---\n\n## Remerciements\n\nLa gestion du module Python `p5` s'inspire du travail de [Basthon](https://basthon.fr/) (Romain Casati). L'idée d'instancier p5.js en arrière-plan pour en inspecter les membres dynamiquement, puis de construire le module Python par introspection plutôt qu'en listant les fonctions à la main, est directement issue de cette approche. Merci à Basthon pour ce travail pionnier sur Python dans le navigateur pour l'enseignement.\n","readmeFilename":"README.md"}