pyxle-framework 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/PKG-INFO +1 -1
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/README.md +1 -1
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/faq.md +1 -1
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyproject.toml +1 -1
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/_escape.py +15 -8
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_escape.py +34 -4
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/.github/pyxle-logo.svg +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/.github/workflows/publish.yml +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/.gitignore +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/CLAUDE.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/LICENSE +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/Makefile +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/README.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/advanced/compiler-internals.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/advanced/ssr-pipeline.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/README.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/build-and-serve.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/cli.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/compiler.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/dev-server.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/overview.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/parser.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/pyxl-files.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/routing.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/runtime.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/architecture/ssr.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/core-concepts/data-loading.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/core-concepts/layouts.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/core-concepts/pyxl-files.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/core-concepts/routing.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/core-concepts/server-actions.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/getting-started/installation.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/getting-started/project-structure.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/getting-started/quick-start.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/api-routes.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/client-components.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/deployment.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/editor-setup.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/environment-variables.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/error-handling.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/for-ai-agents.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/head-management.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/middleware.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/migration-pyx-to-pyxl.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/security.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/guides/styling.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/reference/cli.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/reference/client-api.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/reference/configuration.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/docs/reference/runtime-api.md +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/build/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/build/manifest.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/build/pipeline.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/build/vite.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/cli/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/cli/assets.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/cli/init.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/cli/logger.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/cli/scaffold.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/cli/templates.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/ClientOnly.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/Form.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/Head.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/Image.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/Script.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/index.js +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/useAction.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/client/usePathname.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/core.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/exceptions.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/jsx_imports.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/jsx_parser.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/model.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/parser.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/compiler/writers.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/config.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/_security.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/build.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/builder.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/client_files.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/csrf.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/error_pages.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/layouts.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/middleware.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/overlay.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/path_utils.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/proxy.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/registry.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/route_hooks.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/routes.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/scanner.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/scripts.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/settings.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/starlette_app.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/styles.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/tailwind.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/vite.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/devserver/watcher.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/env.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/routing/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/routing/paths.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/runtime/ClientOnly.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/runtime/Head.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/runtime/Image.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/runtime/Script.jsx +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/runtime.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/head_merger.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/render_component.mjs +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/renderer.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/ssr_worker.mjs +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/template.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/view.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/ssr/worker_pool.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/.gitignore +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/package.json +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/pages/api/pulse.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/pages/index.pyxl +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/pages/layout.pyxl +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/pages/styles/tailwind.css +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/postcss.config.cjs +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/public/branding/pyxle-mark.svg +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/public/styles/tailwind.css +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/pyxle.config.json +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/requirements.txt +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/tailwind.config.cjs +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/build/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/build/test_manifest.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/build/test_pipeline.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/build/test_pipeline_css.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/build/test_vite.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/cli/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/cli/test_commands.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/cli/test_logger.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/cli/test_scaffold.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/cli/test_templates.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_action_compile.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_action_model.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_action_parser.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_action_writers.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_compile.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_head_jsx.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_jsx_imports.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_jsx_parser.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_parser.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_parser_diagnostics.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_parser_hardening.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_script_image_detection.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_script_image_integration.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/sample_middlewares.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_action_routes.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_build.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_builder.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_client_files.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_client_only.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_csrf.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_devserver_start.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_error_pages.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_layouts.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_middleware.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_overlay.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_proxy.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_registry.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_route_error_boundary.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_route_hooks.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_routes.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_scanner.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_scripts.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_security_utils.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_settings.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_starlette_app.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_styles.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_tailwind.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_vite.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_watcher.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/__init__.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_dynamic_head.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_head_merger_extra.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_head_merging.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_integration.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_renderer.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_script_injection.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_template.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_view.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_view_error_boundaries.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/test_worker_pool.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/ssr/utils.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/test_config.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/test_config_security.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/test_env.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/test_runtime.py +0 -0
- {pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/test_runtime_errors.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Pyxle is a Python-first full-stack web framework that brings the Next.js developer experience to the Python ecosystem. Write server logic in Python, UI in React, and ship them together in `.pyxl` files.
|
|
4
4
|
|
|
5
|
-
**Current version:** 0.2.
|
|
5
|
+
**Current version:** 0.2.3 (beta)
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -22,7 +22,7 @@ Django and Flask are backend frameworks that render templates. Pyxle is a full-s
|
|
|
22
22
|
|
|
23
23
|
### Is Pyxle production-ready?
|
|
24
24
|
|
|
25
|
-
Pyxle is in **beta** (version 0.2.
|
|
25
|
+
Pyxle is in **beta** (version 0.2.3). The core features are implemented and tested (1100+ tests, 95%+ coverage), but the API may change before 1.0. Use it for new projects and experiments, but be prepared for breaking changes.
|
|
26
26
|
|
|
27
27
|
### What Python version do I need?
|
|
28
28
|
|
|
@@ -15,13 +15,20 @@ from __future__ import annotations
|
|
|
15
15
|
def escape_inline_json(value: str) -> str:
|
|
16
16
|
"""Escape *value* for safe inclusion inside an HTML ``<script>`` block.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Every replacement is chosen to break an HTML-tokenizer sequence while
|
|
19
|
+
staying **valid JSON**, so the output can still be placed inside a
|
|
20
|
+
``<script type="application/json">`` block and parsed with ``JSON.parse``:
|
|
19
21
|
|
|
20
|
-
* ``</`` → ``<\\/``
|
|
21
|
-
* ``<!--`` →
|
|
22
|
-
* ``-->`` →
|
|
23
|
-
* U+2028 → ``\\u2028
|
|
24
|
-
* U+2029 → ``\\u2029
|
|
22
|
+
* ``</`` → ``<\\/`` — ``\\/`` is a valid JSON escape for ``/``
|
|
23
|
+
* ``<!--`` → ``\\u003c!--`` — ``\\u003c`` is the Unicode escape for ``<``
|
|
24
|
+
* ``-->`` → ``--\\u003e`` — ``\\u003e`` is the Unicode escape for ``>``
|
|
25
|
+
* U+2028 → ``\\u2028`` — JS line separator (not a newline in JSON)
|
|
26
|
+
* U+2029 → ``\\u2029`` — JS paragraph separator
|
|
27
|
+
|
|
28
|
+
The earlier implementation of the comment replacements used ``\\!`` and
|
|
29
|
+
``\\>`` which are **not** valid JSON escape sequences and caused
|
|
30
|
+
``JSON.parse`` to fail on pages whose props happened to contain
|
|
31
|
+
``<!--`` or ``-->`` verbatim (e.g. docs pages embedding shell output).
|
|
25
32
|
|
|
26
33
|
The input is expected to be the return value of :func:`json.dumps` or
|
|
27
34
|
raw CSS text — **not** arbitrary HTML.
|
|
@@ -29,8 +36,8 @@ def escape_inline_json(value: str) -> str:
|
|
|
29
36
|
return (
|
|
30
37
|
value
|
|
31
38
|
.replace("</", "<\\/")
|
|
32
|
-
.replace("<!--", "
|
|
33
|
-
.replace("-->", "
|
|
39
|
+
.replace("<!--", "\\u003c!--")
|
|
40
|
+
.replace("-->", "--\\u003e")
|
|
34
41
|
.replace("\u2028", "\\u2028")
|
|
35
42
|
.replace("\u2029", "\\u2029")
|
|
36
43
|
)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Tests for pyxle.ssr._escape — inline-JSON escaping utilities."""
|
|
2
2
|
|
|
3
|
+
import json
|
|
4
|
+
|
|
3
5
|
import pytest
|
|
4
6
|
|
|
5
7
|
from pyxle.ssr._escape import escape_inline_json
|
|
@@ -18,12 +20,12 @@ class TestEscapeInlineJson:
|
|
|
18
20
|
def test_html_comment_open(self):
|
|
19
21
|
result = escape_inline_json("<!-- comment -->")
|
|
20
22
|
assert "<!--" not in result
|
|
21
|
-
assert "
|
|
23
|
+
assert "\\u003c!--" in result
|
|
22
24
|
|
|
23
25
|
def test_html_comment_close(self):
|
|
24
26
|
result = escape_inline_json("<!-- comment -->")
|
|
25
27
|
assert "-->" not in result
|
|
26
|
-
assert "
|
|
28
|
+
assert "--\\u003e" in result
|
|
27
29
|
|
|
28
30
|
def test_unicode_line_separator(self):
|
|
29
31
|
result = escape_inline_json('{"x":"\u2028"}')
|
|
@@ -55,11 +57,39 @@ class TestEscapeInlineJson:
|
|
|
55
57
|
"input_val,expected_fragment",
|
|
56
58
|
[
|
|
57
59
|
("</", "<\\/"),
|
|
58
|
-
("<!--", "
|
|
59
|
-
("-->", "
|
|
60
|
+
("<!--", "\\u003c!--"),
|
|
61
|
+
("-->", "--\\u003e"),
|
|
60
62
|
("\u2028", "\\u2028"),
|
|
61
63
|
("\u2029", "\\u2029"),
|
|
62
64
|
],
|
|
63
65
|
)
|
|
64
66
|
def test_individual_replacements(self, input_val, expected_fragment):
|
|
65
67
|
assert expected_fragment in escape_inline_json(input_val)
|
|
68
|
+
|
|
69
|
+
@pytest.mark.parametrize(
|
|
70
|
+
"payload",
|
|
71
|
+
[
|
|
72
|
+
{"raw": "--> shell prompt"},
|
|
73
|
+
{"raw": "<!-- html comment -->"},
|
|
74
|
+
{"raw": "</script><script>alert(1)</script>"},
|
|
75
|
+
{"raw": "line1\u2028line2"},
|
|
76
|
+
{"nested": {"list": ["-->", "<!--", "</script>"]}},
|
|
77
|
+
{"combo": "foo --> bar <!-- baz --> qux </script>"},
|
|
78
|
+
],
|
|
79
|
+
)
|
|
80
|
+
def test_output_is_valid_json_after_escape(self, payload):
|
|
81
|
+
"""Regression: the escaped output MUST still be parseable with
|
|
82
|
+
JSON.parse / json.loads, and it must round-trip to the original data.
|
|
83
|
+
|
|
84
|
+
Earlier versions replaced ``<!--`` with ``<\\!--`` and ``-->`` with
|
|
85
|
+
``--\\>``, both of which are invalid JSON escape sequences — this
|
|
86
|
+
broke every docs page whose rendered content contained a literal
|
|
87
|
+
``-->`` (e.g. shell output examples)."""
|
|
88
|
+
raw = json.dumps(payload, ensure_ascii=False)
|
|
89
|
+
escaped = escape_inline_json(raw)
|
|
90
|
+
# Must still parse, and must round-trip to the original data.
|
|
91
|
+
assert json.loads(escaped) == payload
|
|
92
|
+
# And none of the dangerous literal sequences survived.
|
|
93
|
+
assert "</" not in escaped or "<\\/" in escaped
|
|
94
|
+
assert "<!--" not in escaped
|
|
95
|
+
assert "-->" not in escaped
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/pages/styles/tailwind.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/public/styles/tailwind.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/pyxle/templates/scaffold/tailwind.config.cjs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_script_image_detection.py
RENAMED
|
File without changes
|
{pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/compiler/test_script_image_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyxle_framework-0.2.2 → pyxle_framework-0.2.3}/tests/devserver/test_route_error_boundary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|