Files
Marcos Paulo 567ee63c7a feat: export sites, translate pages, and harden agent tools and sync
New agent tools (98 to 104):
- export_site writes a website from frames in one call: plain HTML,
  Astro, Vue (Nuxt or Vite), React (Next or Vite) or Angular; css, scss
  or tailwind, and for React vanilla-extract, styled-components or
  emotion; static pages or a single-page app; a folder per language.
  Fonts are subset to WOFF2 with metric-matched fallbacks, images are
  resized, headings follow the outline, pages reflow below the designed
  width, and _headers, vercel.json, _redirects and .nojekyll cache
  hashed assets for a year.
- get_strings and set_strings treat languages as variable modes: read a
  page's text for translation, fill a language or a pseudo-locale.
- get_context says where the agent is, what is cheap to read next and
  what lint found, in one call; big reads take maxTokens and report
  estimatedTokens.
- import_html opens a page from a prompt-to-design tool (.html or .zip)
  as layers.
- install_font adds fonts on top of the bundled Inter; text can name one.

App:
- Present mode plays a page's frames as a prototype: links jump to
  frames, open overlays, go back or open an address.
- Panics are kept in crash.log; release builds keep line tables so its
  traces name files and lines.
- Settings > Canvas is kept between sessions; a keyboard shortcuts
  sheet; icons in the menus.
- Chat: an opencode turn waiting out a rate limit moves on to the
  fallback model.
- The updater checks each download against the SHA-256 GitHub publishes.

Fixes:
- A NaN or infinite tool argument no longer makes a project unopenable.
- Agent paths cannot reach other machines, devices or NTFS streams; a
  tool writes only its own file type, and fills only a new, empty or
  earlier export folder.
- delegate and imagegen pass each value in its own environment
  variable, never as shell syntax.
- An instance placed inside its own component is refused.
- A panic in a tool fails that call instead of closing the app.
- An agent call during a drag waits for it, so the undo step stays whole.
- Sync holds downloads while the open project has unsaved edits, writes
  pages atomically, and leaves a page saved while its download was in
  flight for the next round to merge. Merges repair the tree instead
  of giving a node two parents or orphaning it.
- Share tokens come from the OS random generator.
- Imports have a total memory cap; Excalidraw import is linear.
- Unused images are freed when a project opens.
- Pages that use no added font are still written as format 3, so 0.9.1
  can open them.
- Code export escapes text, attributes and CSS in one place.

CI: a clippy job (warnings do not fail it yet).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J9PiVCQxc2QYmArFq9VBUX
2026-11-06 10:29:43 -03:00

109 lines
4.7 KiB
YAML

# Pull requests and main run the full test suite and release-profile builds. The release workflow
# calls the same test job; its own platform jobs build the release artifacts. Gitea reads
# .github/workflows too, so jobs are gated on the server URL.
name: test
on:
pull_request:
branches: [main]
push:
branches: [main]
workflow_call:
inputs:
ref:
type: string
required: false
workflow_dispatch:
inputs:
ref:
description: Branch or tag to test (default the one you run from)
required: false
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
test:
name: CI Windows tests
if: github.server_url == 'https://github.com'
# Windows: the platform the app is developed on, and its runners render with a software GPU.
runs-on: windows-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with: { ref: "${{ inputs.ref || github.ref }}" }
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # master; toolchain stable
with: { toolchain: stable, targets: wasm32-unknown-unknown }
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
with:
shared-key: papercraft-test
save-if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- run: cargo test --locked --no-fail-fast
- run: cargo check --locked --lib --target wasm32-unknown-unknown
clippy:
name: CI Clippy
if: github.server_url == 'https://github.com'
runs-on: windows-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with: { ref: "${{ inputs.ref || github.ref }}" }
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # master; toolchain stable
with: { toolchain: stable, components: clippy }
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
with:
shared-key: papercraft-clippy
save-if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
# Warnings are not fatal yet; errors (the lottie module's deny list) fail the job.
- run: cargo clippy --all-targets --locked
windows:
name: CI Windows release build
if: github.server_url == 'https://github.com' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main'))
runs-on: windows-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # master; toolchain stable
with: { toolchain: stable }
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
with:
shared-key: papercraft-release
save-if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- run: cargo build --release --locked --bins
macos:
name: CI macOS release build
if: github.server_url == 'https://github.com' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main'))
runs-on: macos-latest
env:
MACOSX_DEPLOYMENT_TARGET: '11.0'
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # master; toolchain stable
with: { toolchain: stable, targets: aarch64-apple-darwin }
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
with:
shared-key: papercraft-release
save-if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- run: cargo build --release --locked --bins --target aarch64-apple-darwin
linux:
name: CI Linux release build
if: github.server_url == 'https://github.com' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main'))
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # master; toolchain stable
with: { toolchain: stable }
- uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
with:
shared-key: papercraft-release
save-if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- name: Build dependencies
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libssl-dev libxkbcommon-x11-dev libxcb-xkb-dev libx11-xcb-dev libwayland-dev libvulkan-dev libdbus-1-dev
- run: cargo build --release --locked --bins