hyperweave 0.2.0__tar.gz → 0.2.1__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.
- {hyperweave-0.2.0 → hyperweave-0.2.1}/CHANGELOG.md +12 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/PKG-INFO +5 -5
- {hyperweave-0.2.0 → hyperweave-0.2.1}/README.md +4 -4
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/_version.py +2 -2
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/config/genome_validator.py +1 -3
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/connectors/github.py +11 -4
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/render/chart_engine.py +7 -15
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge/chrome-content.j2 +10 -10
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge/chrome-defs.j2 +21 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/stats/chrome-content.j2 +15 -2
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/stats/chrome-defs.j2 +7 -9
- hyperweave-0.2.1/src/hyperweave/templates/frames/strip/brutalist-defs.j2 +26 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/chrome-defs.j2 +35 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip.svg.j2 +12 -13
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_assembler.py +1 -2
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_chart_engine.py +2 -2
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_github_scrape.py +41 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_telemetry_integration.py +3 -6
- hyperweave-0.2.0/src/hyperweave/templates/frames/strip/brutalist-defs.j2 +0 -6
- {hyperweave-0.2.0 → hyperweave-0.2.1}/.dockerignore +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/.github/workflows/ci.yml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/.github/workflows/deploy.yml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/.github/workflows/publish.yml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/.gitignore +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/Dockerfile +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/LICENSE +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/buttons/button-liquid.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/cards/card-butterfly.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/cards/card-python.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/cards/card-sunflower.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/cards/card-waves.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/badge_critical.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/badge_passing.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/badge_warning.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/banner.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/icons/discord.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/icons/notion.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/icons/reddit.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/icons/spotify.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/icons/youtube.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/marquee_counter.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/marquee_horizontal.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/marquee_vertical.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/profile-cards/chart_stars_full.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/profile-cards/stats.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/strip.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/badge_critical.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/badge_passing.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/badge_warning.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/banner.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/icons/bluesky.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/icons/github.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/icons/instagram.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/icons/mastodon.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/icons/x.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/marquee_counter.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/marquee_horizontal.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/marquee_vertical.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/profile-cards/chart_stars_full.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/profile-cards/stats.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/chrome-horizon/strip.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/telemetry/master_card.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/telemetry/receipt.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/telemetry/rhythm_strip.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/footers/inneraura-footer-liquid.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/footers/inneraura-footer-purple.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/footers/inneraura-footer.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/hyperweave-banner.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-discord.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-docs.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-github.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-instagram.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-linkedin.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-tiktok.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-x.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/icons/cobalt-sapphire-youtube.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/marquees/badge-showcase-triple.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/marquees/genome-marquee-triple.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/marquees/sample-badges.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/404.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/callout-icons.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/divider.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/favicon.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/hero-banner.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/hyperweave-banner-v2.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/hyperweave-navbar-logo.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/loader.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/mintlify-assets/og-image.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/assets/timelines/hyperweave-roadmap.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/assets/favicon.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/assets/hyperweave-banner.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/assets/hyperweave-navbar-logo.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/assets/og-image.svg +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/explanation/architecture.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/explanation/camo-compatibility.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/explanation/cim-compliance.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/explanation/genome-profile-system.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/explanation/metadata-tiers.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/how-to/add-motion-to-badges.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/how-to/create-session-receipts.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/how-to/set-up-claude-code-hooks.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/how-to/use-live-data-badges.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/introduction.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/mint.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/quickstart.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/reference/cli.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/reference/compose-spec.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/reference/genomes.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/reference/http-api.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/reference/mcp-tools.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/reference/motions.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/reference/telemetry-contract.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/spec/hyperweave-protocol.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/tutorials/build-an-artifact-kit.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/tutorials/compose-your-first-badge.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/docs/tutorials/install-session-telemetry.mdx +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/fly.toml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/hooks/install.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/hooks/session_end.sh +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/justfile +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/pyproject.toml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/__main__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/cli.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/assembler.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/context.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/engine.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/lanes.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/resolver.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/resolvers/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/resolvers/chart.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/resolvers/stats.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/compose/resolvers/timeline.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/config/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/config/loader.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/config/registry.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/config/settings.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/connectors/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/connectors/arxiv.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/connectors/base.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/connectors/cache.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/connectors/rest.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/color.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/contracts.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/enums.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/models.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/schema.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/text.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/core/thresholds.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/css/accessibility.css +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/css/bridge.css +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/css/expression.css +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/css/phase-colors.css +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/css/status.css +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/css/telemetry.css +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/font-metrics/inter.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/fonts/jetbrains-mono.b64 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/fonts/jetbrains-mono.meta.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/fonts/orbitron.b64 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/fonts/orbitron.meta.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/genomes/brutalist-emerald.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/genomes/chrome-horizon.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/genomes/telemetry-void.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/glyphs.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/border/chromatic-pulse.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/border/corner-trace.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/border/dual-orbit.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/border/entanglement.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/border/rimrun.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/bars.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/breach.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/broadcast.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/cascade.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/collapse.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/converge.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/crash.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/drop.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/kinetic/pulse.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/motions/static.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/policies/normal.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/policies/permissive.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/policies/ungoverned.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/profiles/brutalist.contract.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/profiles/brutalist.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/profiles/chrome.contract.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/profiles/chrome.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/specimens.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/telemetry/model-pricing.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/telemetry/stage-config.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/telemetry/stage-labels.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/telemetry/tool-classes.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/telemetry/tool-colors.yaml +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/arrow.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/aurora.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/beacon.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/bracket3d.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/chevron.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/crosshair.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/diamond.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/rocket.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/rules/bar.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/rules/dashed.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/rules/five-wave.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/rules/spectral.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/rules/straight.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/rules/wave.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/data/terminals/stijl.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/kit.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/mcp/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/mcp/__main__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/mcp/server.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/py.typed +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/render/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/render/fonts.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/render/glyphs.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/render/motion.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/render/templates.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/serve/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/serve/app.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/capture.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/contract.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/corrections.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/cost.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/models.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/parser.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/telemetry/stages.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/filter.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/glyph-inline.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/glyph.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/gradient.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/metadata.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/metric.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/phase-segment.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/rule.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/status.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/terminal.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/components/treemap.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/document.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/error-badge.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge/default-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge/default-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/banner/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/banner/chrome-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/banner/default-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/banner.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/catalog.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/chart/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/chart/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/chart/chrome-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/chart/chrome-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/chart.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/divider.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/icon/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/icon/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/icon/chrome-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/icon/chrome-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/icon/default-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/icon/default-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/icon.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-counter/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-counter/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-counter/chrome-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-counter/chrome-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-counter.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-horizontal/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-horizontal/chrome-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-horizontal/chrome-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-horizontal.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-vertical/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-vertical/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-vertical/chrome-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-vertical/chrome-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/marquee-vertical.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/master-card.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/receipt.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/rhythm-strip.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/stats/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/stats/brutalist-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/stats.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/brutalist-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/brutalist-status.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/chrome-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/chrome-status.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/default-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/default-defs.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/strip/default-status.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/timeline/default-content.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/timeline.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/border/chromatic-pulse.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/border/corner-trace.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/border/dual-orbit.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/border/entanglement.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/border/rimrun.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/bars.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/breach.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/broadcast.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/cascade.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/collapse.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/converge.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/crash.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/drop.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/motions/kinetic/pulse.svg.j2 +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/__init__.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/conftest.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/fixtures/github_contributions/synthetic.html +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/fixtures/session.json +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/fixtures/session.jsonl +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_chart_frame.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_connectors.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_core.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_kit.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_mcp.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_paradigm_dispatch.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_proofset.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_render.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_serve.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_stats_card.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_telemetry.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/tests/test_timeline.py +0 -0
- {hyperweave-0.2.0 → hyperweave-0.2.1}/uv.lock +0 -0
|
@@ -5,6 +5,18 @@ All notable changes to HyperWeave are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.1] - 2026-04-13
|
|
9
|
+
|
|
10
|
+
Post-v0.2.0 stabilization: typography alignment, mobile rendering fix, and a streak computation correction.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Stats card "streak" reports 0d for active contributors.** The contribution-calendar parser walked backwards from the latest cell and broke on the first zero, which is always today's empty cell before the user has committed. The streak calculator now treats the most-recent cell as a single grace day — if today hasn't happened yet, the streak continues from yesterday. Any zero day after the first one still breaks the streak as before.
|
|
15
|
+
- **Activity bars blur on mobile.** The `barglow` filter on the stats card's 52-week activity bars used `feGaussianBlur`, which rasterizes to a pixel buffer and gets downsampled when the SVG is scaled to smaller mobile viewports — producing soft, fuzzy bars. Replaced with a pure-vector 2-layer halo (sibling rects at decreasing opacity). Same cyan halo aesthetic from the chrome-horizon magazine specimen, but crisp at every scale. The `{uid}-barglow` filter definition was removed from `stats/chrome-defs.j2`.
|
|
16
|
+
- **chrome-horizon badge and strip typography** now match the stats and chart cards introduced in v0.2.0. Badge values render in Orbitron (the bundled display font) instead of the prior Impact+skew treatment; strip metric values keep the shields.io-style Impact+skew but gain the silver `ct-hero` gradient fill, tying them visually to the hero numbers on the stats and chart frames. Identity and metric labels render in JetBrains Mono at the sizes and letter-spacing used by the chrome-horizon magazine specimen.
|
|
17
|
+
- Badge and strip chrome templates migrated to the same class-based `<style>` pattern stats and chart already use (`.{uid}-label`, `.{uid}-value`, `.{uid}-identity`, `.{uid}-metric-label`, `.{uid}-metric-value`). Inline `font-family` / `font-size` / `font-weight` attributes removed from `strip.svg.j2`, `badge/chrome-content.j2`, and replaced with class references defined in each paradigm's `*-defs.j2` file. This is chrome-paradigm-only — brutalist-emerald output is unchanged.
|
|
18
|
+
- Applied `ruff format` to three files added in v0.2.0 (`config/genome_validator.py`, `connectors/github.py`, `render/chart_engine.py`). No behavior change — CI's `ruff format --check` job runs separately from `ruff check` and was the only thing red on the v0.2.0 push.
|
|
19
|
+
|
|
8
20
|
## [0.2.0] - 2026-04-12
|
|
9
21
|
|
|
10
22
|
Live-data profile artifacts. HyperWeave can now render GitHub profile cards, star-history charts, and milestone timelines directly from a single API call, the CLI, or an MCP tool. Genomes gain a per-frame paradigm layer so two genomes on the same profile can diverge structurally, not just chromatically. Custom genomes can be loaded from a local JSON file and validated against a profile contract. Fonts are bundled as base64 WOFF2 for fully self-contained SVGs. Test suite: 435 passing.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperweave
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Headless visual output layer for AI agents. One API call → self-contained SVG.
|
|
5
5
|
Project-URL: Repository, https://github.com/InnerAura/hyperweave
|
|
6
6
|
Project-URL: Issues, https://github.com/InnerAura/hyperweave/issues
|
|
@@ -120,12 +120,12 @@ Why genome and not theme? Because brand isn't a design problem, it's an infrastr
|
|
|
120
120
|
</tr>
|
|
121
121
|
<tr>
|
|
122
122
|
<td rowspan="2" align="center"><strong>Profile cards</strong></td>
|
|
123
|
-
<td><img src="
|
|
124
|
-
<td><img src="
|
|
123
|
+
<td><img src="https://hyperweave.app/v1/stats/eli64s/brutalist-emerald.static" alt="stats" width="100%"/></td>
|
|
124
|
+
<td><img src="https://hyperweave.app/v1/stats/eli64s/chrome-horizon.static" alt="stats" width="100%"/></td>
|
|
125
125
|
</tr>
|
|
126
126
|
<tr>
|
|
127
|
-
<td><img src="
|
|
128
|
-
<td><img src="
|
|
127
|
+
<td><img src="https://hyperweave.app/v1/chart/stars/eli64s/readme-ai/brutalist-emerald.static" alt="star chart" width="100%"/></td>
|
|
128
|
+
<td><img src="https://hyperweave.app/v1/chart/stars/eli64s/readme-ai/chrome-horizon.static" alt="star chart" width="100%"/></td>
|
|
129
129
|
</tr>
|
|
130
130
|
<tr>
|
|
131
131
|
<td rowspan="3" align="center"><strong>Marquee</strong></td>
|
|
@@ -88,12 +88,12 @@ Why genome and not theme? Because brand isn't a design problem, it's an infrastr
|
|
|
88
88
|
</tr>
|
|
89
89
|
<tr>
|
|
90
90
|
<td rowspan="2" align="center"><strong>Profile cards</strong></td>
|
|
91
|
-
<td><img src="
|
|
92
|
-
<td><img src="
|
|
91
|
+
<td><img src="https://hyperweave.app/v1/stats/eli64s/brutalist-emerald.static" alt="stats" width="100%"/></td>
|
|
92
|
+
<td><img src="https://hyperweave.app/v1/stats/eli64s/chrome-horizon.static" alt="stats" width="100%"/></td>
|
|
93
93
|
</tr>
|
|
94
94
|
<tr>
|
|
95
|
-
<td><img src="
|
|
96
|
-
<td><img src="
|
|
95
|
+
<td><img src="https://hyperweave.app/v1/chart/stars/eli64s/readme-ai/brutalist-emerald.static" alt="star chart" width="100%"/></td>
|
|
96
|
+
<td><img src="https://hyperweave.app/v1/chart/stars/eli64s/readme-ai/chrome-horizon.static" alt="star chart" width="100%"/></td>
|
|
97
97
|
</tr>
|
|
98
98
|
<tr>
|
|
99
99
|
<td rowspan="3" align="center"><strong>Marquee</strong></td>
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
21
|
+
__version__ = version = '0.2.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 1)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -69,9 +69,7 @@ def load_and_validate_genome_file(
|
|
|
69
69
|
ratio = contrast_ratio(fg, bg)
|
|
70
70
|
min_ratio = pair["min_ratio"]
|
|
71
71
|
if ratio < min_ratio:
|
|
72
|
-
errors.append(
|
|
73
|
-
f"WCAG FAIL: {pair['label']} — {ratio:.1f}:1 < {min_ratio}:1 ({fg} on {bg})"
|
|
74
|
-
)
|
|
72
|
+
errors.append(f"WCAG FAIL: {pair['label']} — {ratio:.1f}:1 < {min_ratio}:1 ({fg} on {bg})")
|
|
75
73
|
except (ValueError, TypeError):
|
|
76
74
|
errors.append(f"INVALID COLOR: {pair['label']} — cannot parse {fg} or {bg}")
|
|
77
75
|
|
|
@@ -247,7 +247,7 @@ _CELL_RE = re.compile(
|
|
|
247
247
|
r'<td(?=[^>]*\bclass="[^"]*ContributionCalendar-day[^"]*")'
|
|
248
248
|
r'(?=[^>]*\bdata-date="(?P<date>\d{4}-\d{2}-\d{2})")'
|
|
249
249
|
r'(?=[^>]*\bdata-level="(?P<level>\d+)")'
|
|
250
|
-
r
|
|
250
|
+
r"[^>]*>",
|
|
251
251
|
re.IGNORECASE,
|
|
252
252
|
)
|
|
253
253
|
|
|
@@ -257,7 +257,7 @@ _CELL_RE = re.compile(
|
|
|
257
257
|
# format, not ISO, so we do NOT try to extract the date from the tooltip —
|
|
258
258
|
# instead we pair tooltips and cells positionally in document order.
|
|
259
259
|
_COUNT_TOOLTIP_RE = re.compile(
|
|
260
|
-
r
|
|
260
|
+
r"<tool-tip[^>]*>\s*(?P<count>\d+|No)\s+contributions?",
|
|
261
261
|
re.IGNORECASE,
|
|
262
262
|
)
|
|
263
263
|
|
|
@@ -298,11 +298,18 @@ def parse_contribution_html(html: str) -> dict[str, Any]:
|
|
|
298
298
|
|
|
299
299
|
contrib_total = sum(c["count"] for c in cells)
|
|
300
300
|
|
|
301
|
-
# Streak: walk backwards from the latest cell, counting consecutive
|
|
301
|
+
# Streak: walk backwards from the latest cell, counting consecutive
|
|
302
|
+
# non-zero days. The most recent cell (today) is allowed to be zero
|
|
303
|
+
# as a grace day — GitHub renders today's empty cell before the user
|
|
304
|
+
# has committed today, and we don't want a morning stats check to
|
|
305
|
+
# report a false 0d streak for an otherwise active contributor.
|
|
306
|
+
# Any zero day AFTER the first one still breaks the streak.
|
|
302
307
|
streak = 0
|
|
303
|
-
for cell in reversed(cells):
|
|
308
|
+
for i, cell in enumerate(reversed(cells)):
|
|
304
309
|
if cell["count"] > 0:
|
|
305
310
|
streak += 1
|
|
311
|
+
elif i == 0:
|
|
312
|
+
continue
|
|
306
313
|
else:
|
|
307
314
|
break
|
|
308
315
|
|
|
@@ -198,7 +198,7 @@ def _marker_rect(x: int, y: int, size: int) -> str:
|
|
|
198
198
|
f'stroke="var(--dna-signal-dim,var(--dna-signal))" stroke-width="1"/>'
|
|
199
199
|
f'<line x1="0" y1="-{cross}" x2="0" y2="{cross}" '
|
|
200
200
|
f'stroke="var(--dna-signal-dim,var(--dna-signal))" stroke-width="1"/>'
|
|
201
|
-
f
|
|
201
|
+
f"</g>"
|
|
202
202
|
)
|
|
203
203
|
|
|
204
204
|
|
|
@@ -210,10 +210,7 @@ def _marker_circle(x: int, y: int, size: int) -> str:
|
|
|
210
210
|
def _marker_diamond(x: int, y: int, size: int) -> str:
|
|
211
211
|
"""Chrome diamond marker: white-filled rotated rect with dark stroke."""
|
|
212
212
|
half = size // 2
|
|
213
|
-
return (
|
|
214
|
-
f'<rect x="-{half}" y="-{half}" width="{size}" height="{size}" '
|
|
215
|
-
f'transform="translate({x} {y}) rotate(45)"/>'
|
|
216
|
-
)
|
|
213
|
+
return f'<rect x="-{half}" y="-{half}" width="{size}" height="{size}" transform="translate({x} {y}) rotate(45)"/>'
|
|
217
214
|
|
|
218
215
|
|
|
219
216
|
_MARKER_BUILDERS = {
|
|
@@ -238,7 +235,7 @@ def _marker_endpoint_rect(x: int, y: int, size: int) -> str:
|
|
|
238
235
|
f'fill="var(--dna-surface)"/>'
|
|
239
236
|
f'<rect x="{x - h3}" y="{y - h3}" width="{s3}" height="{s3}" '
|
|
240
237
|
f'fill="var(--dna-ink-primary,#D1FAE5)"/>'
|
|
241
|
-
f
|
|
238
|
+
f"</g>"
|
|
242
239
|
)
|
|
243
240
|
|
|
244
241
|
|
|
@@ -254,7 +251,7 @@ def _marker_endpoint_diamond(x: int, y: int, size: int) -> str:
|
|
|
254
251
|
f'fill="#38BDF8"/>'
|
|
255
252
|
f'<rect x="-{h2}" y="-{h2}" width="{s2}" height="{s2}" rx="0.4" '
|
|
256
253
|
f'transform="rotate(45)" fill="#FFFFFF" stroke="#000A14" stroke-width="1"/>'
|
|
257
|
-
f
|
|
254
|
+
f"</g>"
|
|
258
255
|
)
|
|
259
256
|
|
|
260
257
|
|
|
@@ -308,10 +305,7 @@ def _build_gridlines(vp: Viewport, rows: int = 4) -> str:
|
|
|
308
305
|
lines: list[str] = []
|
|
309
306
|
for i in range(1, rows + 1):
|
|
310
307
|
y = vp.y + round(vp.h * i / (rows + 1))
|
|
311
|
-
lines.append(
|
|
312
|
-
f'<line x1="{vp.x}" y1="{y}" x2="{vp.x + vp.w}" y2="{y}" '
|
|
313
|
-
f'class="hw-chart-gridline"/>'
|
|
314
|
-
)
|
|
308
|
+
lines.append(f'<line x1="{vp.x}" y1="{y}" x2="{vp.x + vp.w}" y2="{y}" class="hw-chart-gridline"/>')
|
|
315
309
|
return "".join(lines)
|
|
316
310
|
|
|
317
311
|
|
|
@@ -415,15 +409,13 @@ def build_chart_svg(
|
|
|
415
409
|
pts = _build_area_polygon_points(projected, baseline_y)
|
|
416
410
|
if pts:
|
|
417
411
|
area_fragment = (
|
|
418
|
-
f'<polygon points="{pts}" fill="var(--dna-signal)" '
|
|
419
|
-
f'fill-opacity="0.65" class="hw-chart-area"/>'
|
|
412
|
+
f'<polygon points="{pts}" fill="var(--dna-signal)" fill-opacity="0.65" class="hw-chart-area"/>'
|
|
420
413
|
)
|
|
421
414
|
elif fill_density == "bezier-smooth":
|
|
422
415
|
path_d = _build_area_path(projected, baseline_y)
|
|
423
416
|
if path_d:
|
|
424
417
|
area_fragment = (
|
|
425
|
-
f'<path d="{path_d}" fill="var(--dna-signal)" '
|
|
426
|
-
f'fill-opacity="0.12" class="hw-chart-area-smooth"/>'
|
|
418
|
+
f'<path d="{path_d}" fill="var(--dna-signal)" fill-opacity="0.12" class="hw-chart-area-smooth"/>'
|
|
427
419
|
)
|
|
428
420
|
|
|
429
421
|
markers_fragment = _build_markers(projected, shape, point_size)
|
{hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/badge/chrome-content.j2
RENAMED
|
@@ -24,20 +24,20 @@
|
|
|
24
24
|
</g>
|
|
25
25
|
{% endif %}
|
|
26
26
|
|
|
27
|
-
{# Label #}
|
|
27
|
+
{# Label — class-styled for chrome paradigm (matches stats/chart typography) #}
|
|
28
28
|
<text data-hw-zone="label"
|
|
29
29
|
x="{{ label_x }}" y="{{ (h / 2) + 1 }}"
|
|
30
30
|
text-anchor="middle" dominant-baseline="central"
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
class="{{ uid }}-label"
|
|
32
|
+
fill="var(--dna-signal)">{{ label_display | default(label) | upper }}</text>
|
|
33
33
|
|
|
34
|
-
{# Value
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
</
|
|
34
|
+
{# Value — class-styled, no skew. Magazine specimen uses Orbitron here for
|
|
35
|
+
geometric clarity at small sizes; Impact+skew was the pre-v0.2.2 treatment. #}
|
|
36
|
+
<text data-hw-zone="value"
|
|
37
|
+
x="{{ value_x }}" y="{{ h / 2 }}"
|
|
38
|
+
text-anchor="middle" dominant-baseline="central"
|
|
39
|
+
class="{{ uid }}-value"
|
|
40
|
+
fill="{{ glyph_fill | default('var(--dna-ink-primary)') }}">{{ value }}</text>
|
|
41
41
|
|
|
42
42
|
{# Diamond status indicator #}
|
|
43
43
|
{% if show_indicator | default(true) %}
|
|
@@ -35,4 +35,25 @@
|
|
|
35
35
|
<stop offset="70%" stop-color="var(--dna-signal)" stop-opacity="0.35"/>
|
|
36
36
|
<stop offset="100%" stop-color="var(--dna-signal)" stop-opacity="0"/>
|
|
37
37
|
</linearGradient>
|
|
38
|
+
{# ── Hero text gradient (silver, matches stats/chart hero values) ── #}
|
|
39
|
+
<linearGradient id="{{ uid }}-ct-hero" x1="0" y1="0" x2="1" y2="0">
|
|
40
|
+
{% for stop in hero_text_gradient | default([
|
|
41
|
+
{"offset":"0%","color":"#94A3B8"},
|
|
42
|
+
{"offset":"50%","color":"#FFFFFF"},
|
|
43
|
+
{"offset":"100%","color":"#94A3B8"}
|
|
44
|
+
]) %}
|
|
45
|
+
<stop offset="{{ stop.offset }}" stop-color="{{ stop.color }}"/>
|
|
46
|
+
{% endfor %}
|
|
47
|
+
</linearGradient>
|
|
48
|
+
{# ── Typography (class-based, matches stats/chart pattern) ── #}
|
|
49
|
+
<style>
|
|
50
|
+
.{{ uid }}-label {
|
|
51
|
+
font-family: var(--dna-font-mono, 'JetBrains Mono', 'SF Mono', monospace);
|
|
52
|
+
font-size: 11px; font-weight: 600; letter-spacing: 0.10em;
|
|
53
|
+
}
|
|
54
|
+
.{{ uid }}-value {
|
|
55
|
+
font-family: var(--dna-font-display, 'Orbitron', 'Space Grotesk', sans-serif);
|
|
56
|
+
font-size: 17px; font-weight: 900; letter-spacing: 0.02em;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
38
59
|
<clipPath id="{{ uid }}-clip"><rect width="{{ width }}" height="{{ height }}" rx="{{ chrome_corner | default('4') }}"/></clipPath>
|
{hyperweave-0.2.0 → hyperweave-0.2.1}/src/hyperweave/templates/frames/stats/chrome-content.j2
RENAMED
|
@@ -78,7 +78,10 @@
|
|
|
78
78
|
<line x1="{{ (ch_start_x + q * ch_stride) | round(1) }}" y1="{{ ch_baseline + 1.5 }}" x2="{{ (ch_start_x + q * ch_stride) | round(1) }}" y2="{{ ch_baseline + 4 }}" stroke="#A8C0D0" stroke-width="0.4" opacity="0.5"/>
|
|
79
79
|
{% endfor %}
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
{# Activity bars — 2-layer vector halo replaces feGaussianBlur so the bars
|
|
82
|
+
stay crisp when the SVG is scaled down on mobile (iOS Safari downsamples
|
|
83
|
+
filter-rasterized buffers, which fuzzed the 7px-wide bars). #}
|
|
84
|
+
<g data-hw-zone="activity-bars">
|
|
82
85
|
{% for bar in activity_bars %}
|
|
83
86
|
{# Zero-count weeks render as 2px stubs; non-zero weeks use sqrt scaling. #}
|
|
84
87
|
{% if bar.count == 0 %}
|
|
@@ -86,7 +89,17 @@
|
|
|
86
89
|
{% else %}
|
|
87
90
|
{% set h = [4, ((bar.count / ch_peak) ** 0.5 * ch_max_h) | int] | max %}
|
|
88
91
|
{% endif %}
|
|
89
|
-
|
|
92
|
+
{% set bx = (ch_start_x + loop.index0 * ch_stride) | round(1) %}
|
|
93
|
+
{% set by = ch_baseline - h %}
|
|
94
|
+
{# Outer halo — soft wide glow #}
|
|
95
|
+
<rect x="{{ bx - 2 }}" y="{{ by - 2 }}" width="{{ ch_bar_w + 4 }}" height="{{ h + 4 }}" rx="2"
|
|
96
|
+
fill="#A8D4F0" opacity="0.10"/>
|
|
97
|
+
{# Inner halo — tighter brighter glow #}
|
|
98
|
+
<rect x="{{ bx - 1 }}" y="{{ by - 1 }}" width="{{ ch_bar_w + 2 }}" height="{{ h + 2 }}" rx="1.5"
|
|
99
|
+
fill="#A8D4F0" opacity="0.22"/>
|
|
100
|
+
{# Bar body — gradient fill #}
|
|
101
|
+
<rect x="{{ bx }}" y="{{ by }}" width="{{ ch_bar_w }}" height="{{ h }}" rx="1"
|
|
102
|
+
fill="url(#{{ uid }}-bar)" shape-rendering="geometricPrecision"/>
|
|
90
103
|
{% endfor %}
|
|
91
104
|
</g>
|
|
92
105
|
|
|
@@ -98,15 +98,13 @@
|
|
|
98
98
|
</feMerge>
|
|
99
99
|
</filter>
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
</feMerge>
|
|
109
|
-
</filter>
|
|
101
|
+
{# NOTE: the magazine specimen uses an feGaussianBlur-based `barglow` filter
|
|
102
|
+
for the activity bars. That filter rasterizes to a pixel buffer and then
|
|
103
|
+
resamples when the SVG is downscaled on mobile, which produces a soft,
|
|
104
|
+
blurry appearance on small viewports. The stats card is commonly embedded
|
|
105
|
+
in README profiles viewed on phones, so we replace the filter with a
|
|
106
|
+
pure-vector 2-layer halo (sibling rects at decreasing opacity) — same
|
|
107
|
+
cyan halo aesthetic, crisp at every scale. #}
|
|
110
108
|
|
|
111
109
|
<clipPath id="{{ uid }}-clip"><rect width="{{ width }}" height="{{ height }}" rx="6"/></clipPath>
|
|
112
110
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{# Brutalist strip defs: plate gradient. #}
|
|
2
|
+
<linearGradient id="{{ uid }}-plate" x1="0" x2="0" y1="0" y2="1">
|
|
3
|
+
<stop offset="0%" style="stop-color: var(--dna-surface)"/>
|
|
4
|
+
<stop offset="40%" style="stop-color: var(--dna-surface-alt)"/>
|
|
5
|
+
<stop offset="100%" style="stop-color: var(--dna-surface-deep)"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
{# Typography (class-based, preserves pre-v0.2.2 brutalist strip rendering).
|
|
8
|
+
strip.svg.j2 emits class names on identity / metric text; this block defines
|
|
9
|
+
what those classes look like under the default/brutalist paradigm. #}
|
|
10
|
+
<style>
|
|
11
|
+
.{{ uid }}-identity {
|
|
12
|
+
font-family: var(--dna-font-mono, 'SF Mono', monospace);
|
|
13
|
+
font-size: 11px; font-weight: 900; letter-spacing: 0.18em;
|
|
14
|
+
fill: var(--dna-brand-text);
|
|
15
|
+
}
|
|
16
|
+
.{{ uid }}-metric-label {
|
|
17
|
+
font-family: var(--dna-font-mono, 'SF Mono', monospace);
|
|
18
|
+
font-size: 7px; font-weight: 700; letter-spacing: 0.2em;
|
|
19
|
+
fill: var(--dna-ink-muted);
|
|
20
|
+
}
|
|
21
|
+
.{{ uid }}-metric-value {
|
|
22
|
+
font-family: var(--dna-font-display, 'Inter', system-ui);
|
|
23
|
+
font-size: 18px; font-weight: 900; letter-spacing: -0.01em;
|
|
24
|
+
fill: var(--dna-ink-primary);
|
|
25
|
+
}
|
|
26
|
+
</style>
|
|
@@ -48,3 +48,38 @@
|
|
|
48
48
|
<filter id="{{ uid }}-txt" x="-6%" y="-18%" width="112%" height="136%">
|
|
49
49
|
<feDropShadow dx="0" dy="0" stdDeviation="0.6" flood-color="var(--dna-surface, #000A14)" flood-opacity="0.9"/>
|
|
50
50
|
</filter>
|
|
51
|
+
{# Hero text gradient (silver — matches stats/chart hero values) #}
|
|
52
|
+
<linearGradient id="{{ uid }}-ct-hero" x1="0" y1="0" x2="1" y2="0">
|
|
53
|
+
{% for stop in hero_text_gradient | default([
|
|
54
|
+
{"offset":"0%","color":"#94A3B8"},
|
|
55
|
+
{"offset":"20%","color":"#CBD5E1"},
|
|
56
|
+
{"offset":"40%","color":"#F1F5F9"},
|
|
57
|
+
{"offset":"50%","color":"#FFFFFF"},
|
|
58
|
+
{"offset":"60%","color":"#F1F5F9"},
|
|
59
|
+
{"offset":"80%","color":"#CBD5E1"},
|
|
60
|
+
{"offset":"100%","color":"#94A3B8"}
|
|
61
|
+
]) %}
|
|
62
|
+
<stop offset="{{ stop.offset }}" stop-color="{{ stop.color }}"/>
|
|
63
|
+
{% endfor %}
|
|
64
|
+
</linearGradient>
|
|
65
|
+
{# Typography (class-based, matches stats/chart pattern).
|
|
66
|
+
Magazine specimen: strip identity + metric-label use JetBrains Mono; metric-value
|
|
67
|
+
keeps shields.io-style Impact+skew but with silver hero gradient fill tying it
|
|
68
|
+
visually to stats/chart hero numbers. #}
|
|
69
|
+
<style>
|
|
70
|
+
.{{ uid }}-identity {
|
|
71
|
+
font-family: var(--dna-font-mono, 'JetBrains Mono', monospace);
|
|
72
|
+
font-size: 11px; font-weight: 900; letter-spacing: 0.18em;
|
|
73
|
+
fill: var(--dna-brand-text);
|
|
74
|
+
}
|
|
75
|
+
.{{ uid }}-metric-label {
|
|
76
|
+
font-family: var(--dna-font-mono, 'JetBrains Mono', monospace);
|
|
77
|
+
font-size: 10px; font-weight: 700; letter-spacing: 0.14em;
|
|
78
|
+
fill: var(--dna-signal);
|
|
79
|
+
}
|
|
80
|
+
.{{ uid }}-metric-value {
|
|
81
|
+
font-family: 'Impact', 'Arial Black', system-ui, sans-serif;
|
|
82
|
+
font-size: 22px; font-weight: 800; letter-spacing: -0.01em;
|
|
83
|
+
fill: url(#{{ uid }}-ct-hero);
|
|
84
|
+
}
|
|
85
|
+
</style>
|
|
@@ -59,10 +59,7 @@
|
|
|
59
59
|
<g clip-path="url(#{{ uid }}-id-clip)">
|
|
60
60
|
<text data-hw-zone="identity"
|
|
61
61
|
x="{{ identity_x }}" y="{{ (strip_h // 2) + 4 }}"
|
|
62
|
-
|
|
63
|
-
font-size="11" font-weight="{{ strip_identity_weight | default(900) }}"
|
|
64
|
-
fill="{{ strip_identity_fill | default('var(--dna-brand-text)') }}"
|
|
65
|
-
letter-spacing="{{ strip_identity_letter_spacing | default('0.18em') }}">{{ identity | upper }}</text>
|
|
62
|
+
class="{{ uid }}-identity">{{ identity | upper }}</text>
|
|
66
63
|
</g>
|
|
67
64
|
|
|
68
65
|
{# === Metric cells with dividers === #}
|
|
@@ -86,16 +83,18 @@
|
|
|
86
83
|
{% set cell_x = cell_start + (loop.index0 * metric_pitch) %}
|
|
87
84
|
<g data-hw-zone="metric-{{ loop.index0 }}" transform="translate({{ cell_x }},0)">
|
|
88
85
|
<text x="{{ metric_pitch // 2 }}" y="{{ strip_metric_label_y | default(18) }}" text-anchor="middle"
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
class="{{ uid }}-metric-label">{{ metric.label | upper }}</text>
|
|
87
|
+
{# Metric value — chrome paradigm gets a translate+skew group so the skew
|
|
88
|
+
pivots around the text center. Other paradigms render upright. #}
|
|
89
|
+
{% if paradigm_strip == "chrome" %}
|
|
90
|
+
<g transform="translate({{ metric_pitch // 2 }},{{ strip_metric_value_y | default(36) }}) skewX(-8)">
|
|
91
|
+
<text x="0" y="0" text-anchor="middle" dominant-baseline="central"
|
|
92
|
+
class="{{ uid }}-metric-value">{{ metric.value }}</text>
|
|
93
|
+
</g>
|
|
94
|
+
{% else %}
|
|
93
95
|
<text x="{{ metric_pitch // 2 }}" y="{{ strip_metric_value_y | default(36) }}" text-anchor="middle"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
fill="{{ strip_metric_value_fill | default(glyph_fill | default('var(--dna-ink-primary)')) }}"
|
|
97
|
-
letter-spacing="-0.01em"
|
|
98
|
-
{% if strip_metric_value_skew | default(0) %}transform="skewX({{ strip_metric_value_skew }})"{% endif %}>{{ metric.value }}</text>
|
|
96
|
+
class="{{ uid }}-metric-value">{{ metric.value }}</text>
|
|
97
|
+
{% endif %}
|
|
99
98
|
{% if metric.delta %}
|
|
100
99
|
<text x="{{ metric_pitch // 2 }}" y="48" text-anchor="middle"
|
|
101
100
|
class="hw-delta hw-delta--{{ metric.delta_dir | default('neutral') }}">{{ metric.delta }}</text>
|
|
@@ -55,5 +55,4 @@ def test_non_stateful_frame_omits_status_and_expression() -> None:
|
|
|
55
55
|
assert ".hw-value" not in css, "Divider should not include expression layer"
|
|
56
56
|
|
|
57
57
|
# Bridge classes should NOT be present (divider is not in bridge frames)
|
|
58
|
-
assert ".hw-frame-bg" not in css or "divider" in css,
|
|
59
|
-
"Divider should not include bridge classes"
|
|
58
|
+
assert ".hw-frame-bg" not in css or "divider" in css, "Divider should not include bridge classes"
|
|
@@ -161,7 +161,7 @@ def test_build_markers_square_emits_crosshair() -> None:
|
|
|
161
161
|
out = _build_markers([(50, 50), (100, 200)], shape="square", size=10)
|
|
162
162
|
assert "<rect" in out
|
|
163
163
|
# Non-final marker: translate-centered group with crosshair lines.
|
|
164
|
-
assert
|
|
164
|
+
assert "translate(50,50)" in out
|
|
165
165
|
assert 'width="10"' in out
|
|
166
166
|
assert "<line" in out # crosshair lines present
|
|
167
167
|
# Final marker: endpoint beacon (nested squares).
|
|
@@ -236,7 +236,7 @@ def test_build_chart_svg_miter_angular(
|
|
|
236
236
|
},
|
|
237
237
|
)
|
|
238
238
|
assert "<polyline" in result["polyline"]
|
|
239
|
-
assert
|
|
239
|
+
assert 'stroke-linejoin="miter"' in result["polyline"]
|
|
240
240
|
assert "<polygon" in result["area"]
|
|
241
241
|
assert "<rect" in result["markers"]
|
|
242
242
|
|
|
@@ -58,6 +58,47 @@ def test_parse_streak_walks_backwards(synthetic_html: str) -> None:
|
|
|
58
58
|
assert parsed["streak_days"] == 3
|
|
59
59
|
|
|
60
60
|
|
|
61
|
+
def test_parse_streak_grace_day_for_empty_today() -> None:
|
|
62
|
+
"""The most-recent cell may be zero without breaking the streak.
|
|
63
|
+
|
|
64
|
+
GitHub renders today's empty cell at the rightmost position before the
|
|
65
|
+
user has committed today. A morning stats check on an otherwise active
|
|
66
|
+
contributor should NOT report streak=0 just because today hasn't happened
|
|
67
|
+
yet. Subsequent zeros still break the streak.
|
|
68
|
+
"""
|
|
69
|
+
html = (
|
|
70
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-08" data-level="0"> </td>'
|
|
71
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-09" data-level="2"> </td>'
|
|
72
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-10" data-level="3"> </td>'
|
|
73
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-11" data-level="4"> </td>'
|
|
74
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-12" data-level="0"> </td>'
|
|
75
|
+
'<tool-tip>No contributions on April 8</tool-tip>'
|
|
76
|
+
'<tool-tip>5 contributions on April 9</tool-tip>'
|
|
77
|
+
'<tool-tip>12 contributions on April 10</tool-tip>'
|
|
78
|
+
'<tool-tip>30 contributions on April 11</tool-tip>'
|
|
79
|
+
'<tool-tip>No contributions on April 12</tool-tip>'
|
|
80
|
+
)
|
|
81
|
+
parsed = parse_contribution_html(html)
|
|
82
|
+
# Today (Apr 12) is empty → grace. Apr 11 (30), Apr 10 (12), Apr 9 (5) are
|
|
83
|
+
# all non-zero → streak = 3. Apr 8 is zero → break.
|
|
84
|
+
assert parsed["streak_days"] == 3
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_parse_streak_two_consecutive_zeros_break() -> None:
|
|
88
|
+
"""Grace applies to the single most-recent cell only, not cumulative."""
|
|
89
|
+
html = (
|
|
90
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-10" data-level="3"> </td>'
|
|
91
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-11" data-level="0"> </td>'
|
|
92
|
+
'<td class="ContributionCalendar-day" data-date="2025-04-12" data-level="0"> </td>'
|
|
93
|
+
'<tool-tip>12 contributions on April 10</tool-tip>'
|
|
94
|
+
'<tool-tip>No contributions on April 11</tool-tip>'
|
|
95
|
+
'<tool-tip>No contributions on April 12</tool-tip>'
|
|
96
|
+
)
|
|
97
|
+
parsed = parse_contribution_html(html)
|
|
98
|
+
# Today (Apr 12) is grace-zero, Apr 11 is also zero → streak breaks.
|
|
99
|
+
assert parsed["streak_days"] == 0
|
|
100
|
+
|
|
101
|
+
|
|
61
102
|
def test_parse_chronological_order(synthetic_html: str) -> None:
|
|
62
103
|
parsed = parse_contribution_html(synthetic_html)
|
|
63
104
|
dates = [c["date"] for c in parsed["heatmap_grid"]]
|
|
@@ -260,8 +260,7 @@ def test_receipt_tier2_vertical_stacking() -> None:
|
|
|
260
260
|
assert len(tier2_cells) >= 2, f"Expected >=2 tier-2 cells, got {len(tier2_cells)}"
|
|
261
261
|
for name_y, name, meta_y in tier2_cells:
|
|
262
262
|
assert name_y != meta_y, (
|
|
263
|
-
f"Tier-2 cell '{name}' has name_y={name_y} == meta_y={meta_y} — "
|
|
264
|
-
f"text collision (stacking regression)"
|
|
263
|
+
f"Tier-2 cell '{name}' has name_y={name_y} == meta_y={meta_y} — text collision (stacking regression)"
|
|
265
264
|
)
|
|
266
265
|
|
|
267
266
|
|
|
@@ -287,9 +286,7 @@ def test_receipt_treemap_error_annotations() -> None:
|
|
|
287
286
|
|
|
288
287
|
# Every tool with errors must have a matching annotation
|
|
289
288
|
for name, count in expected_errors.items():
|
|
290
|
-
assert str(count) in error_annotations,
|
|
291
|
-
f"Expected ✗{count} for {name}, got annotations: {error_annotations}"
|
|
292
|
-
)
|
|
289
|
+
assert str(count) in error_annotations, f"Expected ✗{count} for {name}, got annotations: {error_annotations}"
|
|
293
290
|
|
|
294
291
|
# No extra annotations beyond what the fixture defines
|
|
295
292
|
assert len(error_annotations) == len(expected_errors), (
|
|
@@ -300,4 +297,4 @@ def test_receipt_treemap_error_annotations() -> None:
|
|
|
300
297
|
for m in re.finditer(r'<g clip-path="[^"]*">(.*?)</g>', svg, re.DOTALL):
|
|
301
298
|
clip_content = m.group(1)
|
|
302
299
|
if "cell-error" in clip_content:
|
|
303
|
-
assert
|
|
300
|
+
assert 'text-anchor="end"' in clip_content, "Error text must be right-aligned"
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{# Brutalist strip defs: plate gradient. #}
|
|
2
|
-
<linearGradient id="{{ uid }}-plate" x1="0" x2="0" y1="0" y2="1">
|
|
3
|
-
<stop offset="0%" style="stop-color: var(--dna-surface)"/>
|
|
4
|
-
<stop offset="40%" style="stop-color: var(--dna-surface-alt)"/>
|
|
5
|
-
<stop offset="100%" style="stop-color: var(--dna-surface-deep)"/>
|
|
6
|
-
</linearGradient>
|
|
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
|
{hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/marquee_horizontal.svg
RENAMED
|
File without changes
|
{hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/marquee_vertical.svg
RENAMED
|
File without changes
|
|
File without changes
|
{hyperweave-0.2.0 → hyperweave-0.2.1}/assets/examples/brutalist-emerald/profile-cards/stats.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|