diff --git a/.github/release-notes/desktop.md b/.github/release-notes/desktop.md index 4f969e8..c06eca2 100644 --- a/.github/release-notes/desktop.md +++ b/.github/release-notes/desktop.md @@ -1,8 +1,8 @@ -Native desktop builds for Jauto. +Signed native desktop builds for Jauto. SHA-256 checksums are included in `SHA256SUMS.txt`. Download the installer for your operating system from the assets below: - Windows: use the `.msi` or `.exe` installer. - macOS: use the `.dmg` installer. -The macOS build is unsigned for now, so macOS may ask you to confirm that you want to open it. +Windows installers are Authenticode-signed. The macOS DMG is signed with a Developer ID certificate, notarized by Apple, and stapled before publication. diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 0000000..95ef53f --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,47 @@ +name: Project checks + +on: + pull_request: + push: + branches: [main, master, develop] + +permissions: + contents: read + +concurrency: + group: checks-${{ github.ref }} + cancel-in-progress: true + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v6 + with: + node-version: 22 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm audit --prod --audit-level moderate + - run: pnpm check:release-version + - run: pnpm lint + - run: pnpm test + - run: pnpm typecheck + - run: pnpm --filter @jauto/web build + - run: pnpm --filter @jauto/desktop build:frontend + + native-check: + name: Native check (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, macos-latest] + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@stable + with: { components: rustfmt } + - uses: swatinem/rust-cache@v2 + with: { workspaces: apps/desktop/src-tauri } + - run: cargo fmt --manifest-path apps/desktop/src-tauri/Cargo.toml --check + - run: cargo check --manifest-path apps/desktop/src-tauri/Cargo.toml diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml index 242c7f1..0fa84bc 100644 --- a/.github/workflows/desktop-release.yml +++ b/.github/workflows/desktop-release.yml @@ -1,54 +1,99 @@ -name: Desktop native releases +name: Signed desktop release on: push: - tags: - - 'v*' - - 'Beta' + tags: ['v*'] workflow_dispatch: inputs: release_tag: - description: 'GitHub Release tag to create or update, for example v0.2.0' + description: 'Version tag matching repository metadata, for example v0.2.0' required: true default: 'v0.2.0' permissions: contents: write +concurrency: + group: desktop-release-${{ github.ref }}-${{ inputs.release_tag }} + cancel-in-progress: false + jobs: + validate: + name: Validate release metadata and credentials + runs-on: ubuntu-latest + env: + RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }} + WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} + WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: { node-version: 22 } + - name: Match tag to every project version + run: node scripts/check-release-version.mjs "$RELEASE_TAG" + - name: Require signing and notarization credentials + shell: bash + run: | + set -euo pipefail + required=(WINDOWS_CERTIFICATE WINDOWS_CERTIFICATE_PASSWORD APPLE_CERTIFICATE APPLE_CERTIFICATE_PASSWORD APPLE_SIGNING_IDENTITY APPLE_ID APPLE_PASSWORD APPLE_TEAM_ID) + for name in "${required[@]}"; do + if [ -z "${!name:-}" ]; then echo "Missing required release secret: $name"; exit 1; fi + done + + quality: + name: Release quality gate + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v6 + with: + node-version: 22 + cache: pnpm + - run: pnpm install --frozen-lockfile + - run: pnpm audit --prod --audit-level moderate + - run: pnpm lint + - run: pnpm test + - run: pnpm typecheck + - run: pnpm --filter @jauto/web build + - run: pnpm --filter @jauto/desktop build:frontend + build: - name: Build ${{ matrix.label }} + name: Build and sign ${{ matrix.label }} + needs: [validate, quality] runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - - label: windows-x64 - os: windows-latest - args: '' - - label: macos-universal - os: macos-latest - args: '--target universal-apple-darwin' - + - { label: windows-x64, os: windows-latest } + - { label: macos-universal, os: macos-latest } + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} + WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Enable pnpm - uses: pnpm/action-setup@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 + - uses: actions/checkout@v6 + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v6 with: node-version: 22 cache: pnpm - cache-dependency-path: pnpm-lock.yaml - - - name: Set up Rust - uses: dtolnay/rust-toolchain@stable - - - name: Add macOS universal targets - if: runner.os == 'macOS' + - uses: dtolnay/rust-toolchain@stable + - uses: swatinem/rust-cache@v2 + with: { workspaces: apps/desktop/src-tauri } + - if: runner.os == 'macOS' run: rustup target add aarch64-apple-darwin x86_64-apple-darwin - name: Install dependencies @@ -59,55 +104,94 @@ jobs: - name: Build native desktop app working-directory: apps/desktop - run: pnpm tauri build ${{ matrix.args }} - - - name: Upload native installers - uses: actions/upload-artifact@v4 + run: pnpm tauri build --config src-tauri/tauri.release.conf.json + - name: Build signed and notarized universal macOS installer + if: runner.os == 'macOS' + working-directory: apps/desktop + run: pnpm tauri build --target universal-apple-darwin + - name: Verify Windows signatures and installers + if: runner.os == 'Windows' + shell: pwsh + run: | + $files = Get-ChildItem apps/desktop/src-tauri/target/release/bundle -Recurse -Include *.exe,*.msi + if (-not $files) { throw 'No Windows installers were produced.' } + foreach ($file in $files) { + $signature = Get-AuthenticodeSignature $file.FullName + if ($signature.Status -ne 'Valid') { throw "Invalid signature on $($file.Name): $($signature.Status)" } + } + - name: Smoke-test installed Windows application + if: runner.os == 'Windows' + shell: pwsh + run: | + $msi = Get-ChildItem apps/desktop/src-tauri/target/release/bundle -Recurse -Filter *.msi | Select-Object -First 1 + $installRoot = Join-Path $env:RUNNER_TEMP 'jauto-installed' + $process = Start-Process msiexec.exe -ArgumentList @('/a', $msi.FullName, '/qn', "TARGETDIR=$installRoot") -Wait -PassThru + if ($process.ExitCode -ne 0) { throw "MSI administrative install failed: $($process.ExitCode)" } + $executable = Get-ChildItem $installRoot -Recurse -Filter jauto.exe | Select-Object -First 1 + if (-not $executable) { throw 'Installed jauto.exe was not found.' } + $app = Start-Process $executable.FullName -PassThru + Start-Sleep -Seconds 5 + if ($app.HasExited -and $app.ExitCode -ne 0) { throw "Installed app exited with $($app.ExitCode)" } + if (-not $app.HasExited) { Stop-Process -Id $app.Id } + - name: Verify macOS signature and notarization + if: runner.os == 'macOS' + shell: bash + run: | + set -euo pipefail + app=$(find apps/desktop/src-tauri/target/universal-apple-darwin/release/bundle -name '*.app' -type d | head -1) + dmg=$(find apps/desktop/src-tauri/target/universal-apple-darwin/release/bundle -name '*.dmg' -type f | head -1) + test -n "$app" && test -n "$dmg" + codesign --verify --deep --strict --verbose=2 "$app" + xcrun stapler validate "$dmg" + - name: Smoke-test installed macOS application + if: runner.os == 'macOS' + shell: bash + run: | + set -euo pipefail + dmg=$(find apps/desktop/src-tauri/target/universal-apple-darwin/release/bundle -name '*.dmg' -type f | head -1) + mount_point="$RUNNER_TEMP/jauto-dmg" + installed_app="$RUNNER_TEMP/Jauto.app" + mkdir -p "$mount_point" + hdiutil attach "$dmg" -mountpoint "$mount_point" -nobrowse + cp -R "$mount_point/Jauto.app" "$installed_app" + hdiutil detach "$mount_point" + codesign --verify --deep --strict "$installed_app" + "$installed_app/Contents/MacOS/jauto" & app_pid=$! + sleep 5 + kill -0 "$app_pid" + kill "$app_pid" + - uses: actions/upload-artifact@v7 with: name: jauto-${{ matrix.label }} if-no-files-found: error path: | apps/desktop/src-tauri/target/release/bundle/**/*.msi apps/desktop/src-tauri/target/release/bundle/**/*.exe - apps/desktop/src-tauri/target/release/bundle/**/*.dmg - apps/desktop/src-tauri/target/release/bundle/**/*.app.tar.gz apps/desktop/src-tauri/target/universal-apple-darwin/release/bundle/**/*.dmg - apps/desktop/src-tauri/target/universal-apple-darwin/release/bundle/**/*.app.tar.gz publish: - name: Publish GitHub Release downloads + name: Publish GitHub Release runs-on: ubuntu-latest needs: build env: RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }} + GH_TOKEN: ${{ github.token }} steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Download native installers - uses: actions/download-artifact@v4 - with: - path: release-assets - - - name: Create or update GitHub Release - env: - GH_TOKEN: ${{ github.token }} + - uses: actions/checkout@v6 + - uses: actions/download-artifact@v8 + with: { path: release-assets } + - name: Create checksums + run: find release-assets -type f -print0 | sort -z | xargs -0 sha256sum > release-assets/SHA256SUMS.txt + - name: Create or update release + shell: bash run: | set -euo pipefail + prerelease=() + [[ "$RELEASE_TAG" == *-* ]] && prerelease=(--prerelease) if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then - gh release edit "$RELEASE_TAG" --title "Jauto $RELEASE_TAG" --notes-file .github/release-notes/desktop.md + gh release edit "$RELEASE_TAG" --title "Jauto $RELEASE_TAG" --notes-file .github/release-notes/desktop.md "${prerelease[@]}" else - gh release create "$RELEASE_TAG" --target "$GITHUB_SHA" --title "Jauto $RELEASE_TAG" --notes-file .github/release-notes/desktop.md - fi - - - name: Upload release assets - env: - GH_TOKEN: ${{ github.token }} - run: | - set -euo pipefail - mapfile -t files < <(find release-assets -type f \( -name "*.msi" -o -name "*.exe" -o -name "*.dmg" -o -name "*.app.tar.gz" \)) - if [ "${#files[@]}" -eq 0 ]; then - echo "No native installers were found." - exit 1 + gh release create "$RELEASE_TAG" --target "$GITHUB_SHA" --title "Jauto $RELEASE_TAG" --notes-file .github/release-notes/desktop.md "${prerelease[@]}" fi + mapfile -d '' files < <(find release-assets -type f -print0) gh release upload "$RELEASE_TAG" "${files[@]}" --clobber diff --git a/ACTION_PLAN.md b/ACTION_PLAN.md new file mode 100644 index 0000000..1c411de --- /dev/null +++ b/ACTION_PLAN.md @@ -0,0 +1,275 @@ +# Jauto audit and action plan + +**Date:** 2026-09-05 +**Goal:** Build a modern alternative to JFLAP with reliable JFLAP 7.1 file compatibility. +**Status:** Implementation in progress. Each completed feature is validated and committed separately. + +## Assessment + +Jauto has a sound modular foundation, but it is not yet a reliable JFLAP-compatible alternative. The immediate priorities are file preservation, simulation correctness, and protection of users' work. Keep the existing separation between core models, JFF handling, simulators, file services, and shared UI while addressing these gaps. + +Compatibility must distinguish three guarantees: + +1. A document can be imported. +2. Its contents and meaning are preserved when saved. +3. Its execution matches JFLAP's behavior. + +Passing a Jauto parse/serialize round trip alone does not establish compatibility with JFLAP. + +## Audit baseline + +The following checks were completed against the existing installation: + +| Check | Result | +| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| Existing automated tests | 80 passed across core, JFF, and simulator packages | +| Type checking | Passed | +| Web production build | Passed | +| Desktop frontend build | Passed | +| Rust `cargo check --locked --offline` | Passed | +| Lint | Passed, but Vue components are ignored by the current configuration | +| Production dependency audit | Three high and one moderate advisory involving transitive PostCSS/nanoid dependencies; runtime exploitability was not established | +| Browser verification | Confirmed that Backspace in the state-name input deletes the selected state | +| Additional correctness probes | Executed against current source using in-memory transpilation, including official JFLAP fixtures | + +No source or configuration files were changed during the audit. Native installer execution, macOS behavior, and exhaustive compatibility across the full JFLAP corpus remain unverified. Existing build caches were present; these checks do not establish clean-checkout release reproducibility. + +## Prioritized findings + +**P1:** Blocker for a dependable compatible release. +**P2:** Important correctness, reliability, or usability improvement. +**P3:** Later expansion or optimization after the compatible automata milestone. + +| ID | Priority | Finding | Evidence and consequence | +| --- | -------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F01 | P1 | Exported state IDs are incompatible with JFLAP | `packages/core/src/ids.ts:4` generates IDs such as `s0`. `packages/jff/src/serializers/states.ts:13` writes them unchanged. JFLAP parses integer IDs, causing multiple invalid IDs to collide. | +| F02 | P1 | Transition values are not XML-escaped | FA/PDA/TM serializers interpolate transition fields directly. Symbols containing `<` or `&` can produce malformed XML or change on reimport. | +| F03 | P1 | Imports silently change or discard information | `packages/jff/src/parser.ts:19` trims meaningful whitespace. Multi-tape values become strings such as `[object Object]`; building blocks are ignored. `packages/file-io/src/open.ts:22` discards parser warnings. | +| F04 | P1 | The editor runs every finite automaton as a DFA | `packages/ui/src/stores/simulation.ts:35` always selects the DFA runner for finite automata. An epsilon edge from an initial state to a final state incorrectly rejects empty input. | +| F05 | P1 | PDA initialization disagrees with JFLAP | `packages/simulator/src/pda-runner.ts:23` starts with an empty stack instead of `Z`. The official PDA example imports without warnings but rejects valid inputs `ab`, `aabb`, and `aaabbb`. | +| F06 | P1 | Valid execution paths are lost | FA/PDA runners do not support relevant multi-character transition strings. PDA execution truncates configurations at 1,000. `packages/simulator/src/tm-runner.ts:61` follows only the first matching transition. These can produce false rejection. | +| F07 | P1 | Ordinary text editing can delete graph elements | `packages/ui/src/components/AutomatonCanvas.vue:103` forwards global keyboard events to graph interaction handling without protecting all editable targets. Confirmed in the browser. | +| F08 | P1 | Unsaved documents lack lifecycle protection | New/Open can replace unsaved work without protection. Reload/close recovery is absent. Home retains the graph internally but provides no Resume action. | +| F09 | P2 | Simulation replay and visualization are misleading | Previous/Next changes highlights without restoring the corresponding status/configuration. Rejection can highlight an edge that never executed. An accepted PDA result can display a losing branch. | +| F10 | P2 | Editing during simulation creates inconsistent state | The runner retains the starting machine while the UI can display and use an edited document to infer highlights. | +| F11 | P2 | Validation and identity invariants are incomplete | `packages/core/src/validation.ts:127` misses duplicate IDs and invalid TM properties. Imported IDs can collide with new IDs. Multiple initial states and dangling references are insufficiently guarded. | +| F12 | P2 | Execution lifecycle and analysis helpers are unreliable | PDA initial acceptance can be lost on stepping. `run(0)` crashes. Resource limits can look like rejection. Some determinism checks are incorrect, and PDA/TM completeness checks unconditionally return true. | +| F13 | P2 | Undo does not restore exact structure | Remove-state/remove-transition undo appends restored objects, changing order. With current first-match execution, this can change results. | +| F14 | P2 | Inspector drafts can disappear or be omitted | Local drafts reset on selection/object changes. Save and Start operate on committed graph data without resolving pending inspector edits. | +| F15 | P2 | Pointer and viewport behavior is incomplete | Mouse release outside the canvas can leave gestures active. No pointer capture is used. Resize handling misses container changes, high-DPI scaling is absent, and Fit/Zoom helpers are not exposed. | +| F16 | P2 | Teaching and accessibility features are missing | The UI lacks stack/tape/head and branch views, remaining-input visualization, and batch input results. Canvas editing lacks a keyboard-accessible semantic alternative; controls and responsive layouts need work. | +| F17 | P2 | File persistence and export behavior is incomplete | Desktop file paths and actual saved filenames are discarded. Dirty tracking is not revision-based. Web save ignores the boolean result. PNG export captures the current viewport rather than intentional whole-diagram bounds. | +| F18 | P2 | Delivery checks leave important gaps | Vue files are not linted; UI/apps lack test coverage and file-io passes with no tests. The release workflow invokes desktop packaging without first building workspace libraries. Native event capabilities need verification. | +| F19 | P2/P3 | Rendering and trace storage may scale poorly | Continuous idle rendering, repeated graph scans and geometry work, and growing trace arrays warrant measurement and targeted optimization. Performance impact has not yet been benchmarked. | +| F20 | P3 | Current scope covers only part of JFLAP | The model supports FA/PDA/TM, while JFLAP also supports other machine/document families and teaching workflows. Full parity requires separate milestones. | + +## Implementation plan + +### 1. Define the compatibility contract and establish independent checks + +**Priority:** P1 +**Dependencies:** None + +- [x] Target JFLAP 7.1 explicitly and publish a compatibility matrix for import, preservation, and execution. +- [x] Define supported transition syntax, epsilon/blank conventions, acceptance policies, and unsupported-feature behavior. +- [x] Start with FA/NFA, PDA, and single-tape TM as the first compatibility milestone. +- [x] Build a conformance suite from official JFLAP files and independently established expected outcomes. +- [x] Verify Jauto-created exports in JFLAP, including files with multiple new states. +- [x] Add regression cases for the confirmed defects, including empty input, string transitions, epsilon cycles, nondeterminism, malformed XML, and resource exhaustion. +- [x] Enable Vue linting and meaningful UI/store/file-service integration tests. +- [x] Add pull-request checks for tests, lint, type checking, and builds. + +**Acceptance criteria:** Every advertised feature has an independent compatibility check. Unsupported documents cannot silently become altered editable documents. Tests cover integration behavior as well as isolated engines. + +### 2. Repair the document model and JFF import/export + +**Priority:** P1 +**Dependencies:** Compatibility rules and initial regression cases from step 1 + +- [x] Make automaton types a discriminated union with machine-specific transition schemas. +- [x] Allocate internal IDs without collisions and enforce graph uniqueness. +- [x] Map internal IDs to unique integer IDs on export, updating all transition endpoints consistently. +- [x] Use a shared XML writer or escaping utility for every text field and attribute; reject characters forbidden by XML. +- [x] Preserve semantic whitespace and trim only structural fields where appropriate. +- [x] Validate XML structure, document shape, references, initial-state rules, finite coordinates, tape counts, and movement values. +- [x] Preserve notes, state labels, and transition curve geometry. +- [x] Retain compatible document extensions or explicitly diagnose information that cannot be preserved. +- [x] Carry structured import diagnostics through file I/O to the UI. +- [x] Detect multi-tape and building-block documents. Reject unsupported editable imports or offer an explicit mode preserving the original contents. + +**Acceptance criteria:** Supported files survive exchange in both directions without altered symbols, topology, annotations, or execution meaning. Unsupported constructs and invalid graphs produce actionable diagnostics. + +### 3. Protect document editing and saving + +**Priority:** P1 +**Dependencies:** Can proceed alongside steps 2 and 4 + +- [x] Centralize keyboard handling with editable-target, focus, modifier, and IME guards. +- [x] Add a shared document lifecycle for New/Open/Home/Close with Save/Discard/Cancel behavior. +- [x] Add recoverable drafts, reload/close protection, and a Resume path from Home. +- [x] Track document identity, current revision, and saved revision rather than a manually toggled dirty flag. +- [x] Bind asynchronous save completion to the document revision actually saved. +- [x] Preserve desktop paths and actual chosen filenames; distinguish Save from Save As. +- [x] Handle cancellation, false save results, and errors without clearing unsaved state. +- [x] Display actionable open/save/export errors instead of relying on console output. +- [x] Resolve inspector drafts consistently before saving, starting simulation, changing selection, or undoing. +- [x] Make undo restore exact graph structure and order; test undo back to the saved revision. + +**Acceptance criteria:** Typing never deletes graph elements. Canceled or failed operations retain work. Save indicators accurately describe the saved revision, and pending edits cannot disappear silently. + +### 4. Correct the execution engines + +**Priority:** P1 +**Dependencies:** Compatibility semantics from step 1; coordinate model changes with step 2 + +- [x] Connect NFA execution and epsilon closure to the editor. +- [x] Support the declared FA/PDA string-transition semantics, including PDA stack-string matching. +- [x] Initialize PDA stacks consistently with JFLAP and correct initial-configuration acceptance. +- [x] Implement fair nondeterministic exploration and configuration deduplication where appropriate. +- [x] Support nondeterministic TMs or explicitly prevent unsupported execution until implemented. +- [x] Specify and implement the targeted TM acceptance policies and shortcut syntax. +- [x] Replace silent branch truncation with explicit resource-limit outcomes. +- [x] Standardize accepted, rejected, invalid, canceled, and incomplete outcomes across runners. +- [x] Validate execution budgets, including zero/negative values, and make terminal steps idempotent. +- [x] Repair determinism checks and remove placeholder completeness results. +- [x] Separate input, stack, and tape alphabet helpers. +- [x] Update existing tests that encode incompatible PDA initialization assumptions. + +**Acceptance criteria:** Official examples and edge cases produce expected results. Exhausted resources never count as proof of rejection. Unsupported execution modes are identified before running. + +### 5. Make simulation useful for learning + +**Priority:** P2 +**Dependencies:** Correct engine behavior and result contracts from step 4 + +- [x] Emit actual transition IDs, complete configurations, branch identities, and accepting paths from runners. +- [x] Include the initial configuration in traces and replay complete snapshots directly. +- [x] Separate the replay cursor from the execution head. +- [x] Restart or invalidate simulations after semantic edits; define behavior for layout-only edits. +- [x] Show consumed/remaining input, PDA stack, TM tape/head, and active configurations. +- [x] Show branch selection and accepting witnesses for nondeterministic runs. +- [x] Expose meaningful execution limits and clear incomplete/canceled statuses. +- [x] Add batch input testing after individual simulation and replay are dependable. + +**Acceptance criteria:** Every displayed step, highlight, configuration, and status describes the same execution point. Users can inspect why a word was accepted or rejected. + +### 6. Improve editor interaction, accessibility, and performance + +**Priority:** P2; optimize based on measurements +**Dependencies:** Coordinate with document transactions and trace UI + +- [x] Use Pointer Events and pointer capture for dragging and transition creation. +- [x] Handle pointer cancellation, lost capture, Escape, blur, and document switches. +- [x] Preserve drag offsets and use one history transaction per gesture. +- [x] Add visible Fit/Zoom controls and fit imported diagrams into view. +- [x] Observe container resizing and support high-density display rendering. +- [x] Provide keyboard-operable state/transition editing and a semantic alternative to the canvas. +- [x] Add associated labels, toolbar/menu semantics, visible focus, and accessible status announcements. +- [x] Make the inspector collapsible and controls usable in narrow windows and at enlarged text/zoom settings. +- [x] Export complete diagrams with intentional bounds, scale, background, and editing-decoration options. +- [x] Benchmark representative small and large diagrams and long simulations. +- [x] Address idle redraws, repeated graph scans, geometry recalculation, and trace retention based on results. +- [x] Introduce background execution and viewport culling where justified by measurements. + +**Acceptance criteria:** Diagrams remain discoverable and editable across supported input methods, window sizes, and agreed performance benchmarks. Exports include the intended complete diagram. + +### 7. Make desktop builds and delivery dependable + +**Priority:** P2 overall; clean-build and native-command failures are release blockers +**Dependencies:** CI foundation from step 1; stable document commands from step 3 + +- [x] Centralize shared application commands to reduce web/desktop behavior drift. +- [x] Configure necessary native event capabilities and ensure listeners are cleaned up. +- [x] Verify native menus, accelerators, document close protection, and file dialogs. +- [x] Build workspace dependencies from clean checkouts before desktop packaging. +- [x] Gate releases on conformance tests, lint, type checking, frontend builds, and native checks. +- [x] Smoke-test installed Windows and macOS applications. +- [x] Update affected PostCSS/nanoid dependency paths and assess advisory reachability. +- [x] Review production CSP and keep native permissions scoped to required functionality. +- [x] Align version numbers, toolchain requirements, release notes, and setup documentation. +- [x] Review stale dependency/configuration remnants after checking actual usage. +- [ ] Complete signing/notarization before a stable distribution. + +**Acceptance criteria:** Clean CI produces installers that pass platform smoke tests. Native commands work as documented, and dependency advisories are fixed or explicitly assessed. + +### 8. Expand toward full JFLAP parity + +**Priority:** P3 +**Dependencies:** Dependable compatible automata milestone + +- [x] Add multi-tape TMs and building-block machines with import, preservation, and execution support together. +- [x] Add regular-expression documents and tooling. +- [x] Add NFA-to-DFA conversion, DFA minimization, and automaton/regular-expression conversions. +- [x] Add grammars and parsing workflows. +- [x] Add Mealy and Moore machines. +- [x] Add L-systems and pumping-lemma activities. +- [x] Extend the compatibility matrix and independent fixture suite for every new feature before advertising support. + +**Acceptance criteria:** Each feature is a separately verified product milestone. Full JFLAP replacement claims reflect demonstrated coverage rather than file-extension support alone. + +## Execution order and release criteria + +1. Establish the compatibility contract and regression foundation. +2. Prioritize steps 2-4: file preservation, document protection, and simulation correctness. Document protection can proceed independently alongside the other two. +3. Build trustworthy traces and educational views on the corrected engines. +4. Complete editor usability and platform reliability work, measuring performance before optimizing. +5. Expand to additional JFLAP features after the first compatibility milestone. + +Before calling the automata milestone dependable: + +- [ ] All P1 findings have regression coverage and are resolved. +- [ ] Supported JFLAP files preserve their meaning through import, edit, export, and reopening in JFLAP. +- [ ] Official examples and declared edge cases execute correctly. +- [ ] Unsupported constructs cannot be silently corrupted or simulated with misleading results. +- [ ] Save, cancellation, recovery, and undo workflows protect user work. +- [ ] Vue/UI/file-service checks run in CI, and releases build from clean checkouts. +- [ ] Installed applications pass the declared platform smoke tests. + +## Primary references + +- [Official JFLAP download page](https://www.jflap.org/jflaptmp/) +- [JFLAP 7.1 source archive](https://www.jflap.org/jflaptmp/july27-18/JFLAP7.1_With_Source.jar): integer IDs, document families, and XML persistence behavior. +- [JFLAP PDA tutorial](https://jflap.org/tutorial/pda/construct/index.html): initial stack and transition-string semantics. +- [Official PDA example](https://www.jflap.org/tutorial/pda/construct/pdaexample.jff): corpus-backed simulation reproduction. +- [JFLAP book](https://www.jflap.org/jflapbook/jflapbook2006.pdf): finite-automaton string transitions and educational workflows. +- [Single-tape TM tutorial](https://www.jflap.org/tutorial/turing/one/index.html): nondeterminism and shortcut syntax. +- [JFLAP preferences](https://www.jflap.org/tutorial/guiChanges/index.html): TM acceptance policies. +- [Official multi-tape example](https://www.jflap.org/tutorial/turing/multi/turingAnBnCnMulti.jff): per-tape XML structure. +- [JFLAP 7.1 TM format changes](https://www.jflap.org/tutorial/turing/changes7.1/index.html) +- [Finite-automaton tutorial](https://www.jflap.org/tutorial/fa/createfa/fa.html): annotations and editor behavior. +- [Tauri capabilities](https://v2.tauri.app/security/capabilities/): native API permissions. + +## Implementation log + +- Compatibility contract: added `docs/COMPATIBILITY.md` with an honest baseline matrix, first-release semantics, unsupported-feature policy and verification requirements. Validated against the audit's official JFLAP references and current implementation. No application behavior changed. +- Test and CI foundation: enabled Vue linting, added UI/history and file-service tests, retained the official PDA fixture with provenance, replaced obsolete Vitest workspace configuration, and added PR/release checks. Validation: 86 tests passed; lint, type checking and both frontend builds passed; Turbo task graph verified. Full simulator conformance and installed-platform checks remain outstanding. +- Document identity: made machine kinds discriminated, allocated IDs against the open document, rejected duplicate additions and introduced structural diagnostics for damaged graphs. Validation: 40 core tests passed; all workspace type checks and lint passed. Structural diagnostics will be connected to file opening/export in the next feature. +- Safe JFF exchange: added strict XML/document validation, loss-preventing rejection for unsupported constructs, numeric state-ID mapping, semantic XML entity/whitespace preservation, notes and transition control-point round trips, and visible import notices. Validation: 39 JFF tests and 3 UI tests passed; workspace type checks and lint passed. Independent XML checks cover generated IDs and references. Reopening generated files in the JFLAP application remains an external conformance gate. +- Keyboard safety: centralized editable-target, default-prevention and IME-composition guards for canvas commands and application undo/redo shortcuts. Validation: 8 UI tests passed; workspace type checks and lint passed. +- NFA editor execution: routed nondeterministic finite automata to the NFA runner, exposed epsilon-closure branch states in the canvas highlights, and derived the initial status from the runner so empty-input acceptance is immediate. Validation: 11 UI tests passed; workspace type checks and lint passed. +- Bounded simulation outcomes: added an explicit `step-limit` run outcome, preserved the current configuration for zero-step runs, and removed the shared `run(0)` crash from all four runners. Validation: 30 simulator tests passed; workspace type checks and lint passed. +- Vendor conformance corpus: retained official JFLAP NFA, PDA, and TM examples with provenance and independent language expectations; added execution and graph-preservation checks. A four-state Jauto export with colliding-style internal IDs was reopened successfully by JFLAP 7.1's own XML decoder. Validation: 44 JFF tests passed; JFLAP returned `automata.fsa.FiniteStateAutomaton` for the generated export. +- Transition-semantics regressions: implemented complete FA/PDA string reads, prefix-aware NFA branching, PDA stack-string operations with JFLAP's initial `Z`, and idempotent initial acceptance. Added regressions for string labels, epsilon cycles, nondeterminism, malformed documents, zero-step/resource limits, and vendor PDA languages. Validation: 41 core, 35 simulator, 11 UI, and 46 JFF tests passed; workspace type checks and lint passed. +- Revision-based document state: replaced the manual dirty flag with document identity plus current/saved revisions, preserved revisions across undo/redo, kept drag previews outside history, and bound asynchronous save completion to the captured document revision. Validation: 12 UI tests passed; workspace type checks and lint passed. +- Protected document lifecycle: routed New/Open through a shared Save/Discard/Cancel decision, retained work when saving fails or the user cancels, added browser reload/close protection, persisted unsaved recovery drafts, and exposed Resume on Home. Home navigation retains the current document rather than discarding it. Validation: 19 UI tests passed; workspace type checks and lint passed. +- File identity and save behavior: carried desktop paths through open/save, made Save overwrite the current path while Save As opens the chooser, adopted the filename actually selected, retained dirty state on cancellation/failure, and surfaced save/export errors to users. Validation: 4 file-service and 20 UI tests passed; Rust check/format, workspace type checks and lint passed. +- Exact structural undo: removal commands now capture and restore original state and transition indices, including connected edges, while revision history returns to the saved revision. Validation: 43 core tests passed; core type checks and lint passed. +- Inspector transaction boundary: registered the active inspector draft with the document store and flush it before selection changes, save, New/Open, simulation start, undo, and redo. Validation: 21 UI tests passed; workspace type checks and lint passed. +- Fair bounded exploration: deduplicated NFA/PDA configurations during breadth-first stepping, replaced PDA's silent 1,000-branch truncation with an `incomplete` result and `configuration-limit` reason, validated run budgets, and made terminal stepping idempotent. Validation: 43 simulator tests passed; simulator type checks and lint passed. +- Execution profiles and outcomes: added terminal cancellation across runners, surfaced invalid-machine errors in the editor, implemented configurable TM final-state/halting acceptance, and reject nondeterministic TMs, disabled stay moves, and JFLAP shortcut syntax before execution when unsupported. Validation: 49 simulator and 21 UI tests passed; workspace type checks and lint passed. +- Machine analysis: added separate input, stack, and tape alphabet helpers; made PDA determinism account for overlapping read/pop prefixes and equivalent blank spellings; implemented symbol-level FA, conservative PDA, and literal-TM completeness checks; and updated legacy PDA tests to start with JFLAP's `Z`. Validation: 51 core and 49 simulator tests passed; full workspace tests, type checks, lint, Rust format, and Rust check passed. +- Educational simulation traces: runners now emit exact transition IDs, complete active configurations, stable branch identities, and accepting witnesses. Replay includes the initial snapshot and keeps its cursor independent from the execution head; semantic edits invalidate execution while layout edits remain safe. The controls expose input progress, PDA stacks, TM tape/head positions, branches, witnesses, and batch results. Validation: 52 simulator and 24 UI tests passed; simulator/UI builds passed. +- Pointer and viewport interaction: canvas gestures now use Pointer Events and capture, preserve drag offsets, commit one undo command, and restore previews on cancellation, Escape, blur, capture loss, and document changes. Visible Fit/Zoom controls, automatic import fitting, `ResizeObserver`, high-density rendering, and change-driven drawing were added. Validation: 27 UI tests and UI type checking passed. +- Accessible editor and complete export: added a native-control semantic diagram editor, associated labels and status announcements, toolbar semantics and focus indicators, a collapsible inspector, narrow-window layouts, and full-bounds offscreen PNG rendering with explicit scale, background, grid, and editing-decoration options. Web and desktop use the shared exporter. Validation: 29 UI tests and the complete seven-package build, including MSI and NSIS installers, passed. +- Measured performance: added a repeatable 500-state/4,000-transition and 10,000-step benchmark, indexed runner lookups and render graph data, cached per-frame styles, culled offscreen elements, discarded batch trace snapshots, and capped interactive replay at 10,000 steps. The measured render pass fell from 129.20 ms to 23.82 ms and the batch run from 481 ms to 74.13 ms; worker coordination was not justified at this workload. Validation: benchmark, 52 simulator tests, 29 UI tests, all workspace type checks, and all lint tasks passed. +- Desktop commands and native lifecycle: centralized web/desktop New, Open, Save, Save As, Home, export, and menu behavior; scoped Tauri capabilities; cleaned up native listeners; protected native close; and removed remote desktop fonts. Validation: 31 UI tests, frontend builds, Rust format/check, and lint passed. +- Dependency and release baseline: resolved the production PostCSS/nanoid advisories, removed stale dependencies and Electron overrides, aligned every package at 0.2.0, and added version, changelog, and release checks. Validation: the production dependency audit reported no vulnerabilities and all tests/type checks passed. +- Signed release publishing: added gated GitHub Actions jobs for clean workspace builds, conformance checks, Windows Authenticode signing, Apple Developer ID signing/notarization, installed MSI/DMG smoke tests, checksums, and GitHub Release publication. The workflow refuses publication without every signing secret. Validation: workflow formatting, release-version checks, local Windows installers, production audit, and native checks passed; a hosted macOS release run still requires repository credentials. +- Multi-tape Turing machines: imported, edited, rendered, serialized, and executed one-to-eight-tape machines with complete action vectors. Validation: the official three-tape `a^n b^n c^n` fixture round-trips and accepts/rejects its representative language cases; 51 core, 47 JFF, 52 simulator, and 31 UI tests passed. +- Regular languages and conversions: added the JFLAP regular-expression parser/formatter, Thompson construction, epsilon-aware subset construction, DFA minimization, GNFA state elimination, JFF `re` documents, and accessible editor conversion controls with undo. Validation: transformation equivalence tests and the official `regExprToNfa.jff` fixture passed; affected builds, type checks, and lint passed. +- Grammars and parsing: added ordered grammar JFF exchange, Chomsky-hierarchy classification, bounded Earley recognition with epsilon productions, and CYK recognition for CNF exercises. Validation: the official right-linear grammar fixture round-trips; 58 core and 52 JFF tests passed with type checks and lint. +- Mealy and Moore machines: added typed models, deterministic output traces, legacy/nested JFF exchange, and JFLAP's Moore initial-output convention. Validation: official Mealy and Moore NOT fixtures produce the independently expected outputs and survive export/reimport; 61 core and 54 JFF tests passed with type checks and lint. +- L-systems and pumping activities: added space-delimited parallel/stochastic derivation, regular/context-free pumping decomposition validators and generators, and JFF preservation for the three document families. Validation: official L-system and pumping fixtures round-trip; 65 core and 57 JFF tests passed with type checks and lint. +- Turing building blocks: added recursive embedded-machine import/export and deterministic execution with JFLAP identity, negation, and variable-assignment shortcuts. Validation: the official `asfirst.jff` machine produces `aaabb` from `ababa` and `aabbb` from `bbbaa` before and after round-trip; 54 simulator and 59 JFF tests passed with builds, type checks, and lint. + +Unchecked items remain planned work. Checked items have been implemented and validated as described in the implementation log. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..db0f408 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## 0.2.0 - 2026-09-06 + +- Added strict JFLAP automata import/export validation and vendor-backed conformance fixtures. +- Corrected DFA, NFA, PDA, and single-tape Turing-machine execution semantics and outcomes. +- Added protected save/recovery workflows, structural undo, complete replay traces, and batch testing. +- Added pointer-safe editing, a keyboard-accessible semantic editor, responsive high-DPI rendering, and full-diagram PNG export. +- Added Windows and macOS release automation with quality, signing, notarization, and checksum gates. diff --git a/README.md b/README.md index 4bc55a5..816d24d 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ ## Features (MVP) +Compatibility is under active development. See the [JFLAP 7.1 compatibility contract](docs/COMPATIBILITY.md) for current limitations and the [action plan](ACTION_PLAN.md) for progress. + - **DFA / NFA** — create, edit, and simulate finite automata - **PDA** — pushdown automata with stack visualization - **Turing Machine** — single-tape Turing machine editor and simulator @@ -25,7 +27,7 @@ ### Prerequisites - [Node.js](https://nodejs.org/) >= 22 -- [pnpm](https://pnpm.io/) >= 10 +- [pnpm](https://pnpm.io/) 11.x (the repository pins 11.5.2) - [Rust](https://www.rust-lang.org/tools/install) with Cargo for native desktop builds ### Setup @@ -100,12 +102,16 @@ The `Desktop native releases` workflow builds: - Windows x64 installers on `windows-latest` - macOS universal installers for Intel and Apple Silicon on `macos-latest` -The generated `.msi`, `.exe`, `.dmg`, and `.app.tar.gz` files are attached to +The generated `.msi`, `.exe`, and `.dmg` files are attached to the GitHub Release for that tag. The workflow can also be run manually from GitHub Actions with a `release_tag` value. -The macOS installer is currently unsigned. Users may need to approve it manually -from macOS security settings until Apple Developer ID signing is configured. +See [the release runbook](docs/RELEASING.md) for required signing secrets, +quality gates, checksums, and signature verification. + +Stable desktop releases require Windows signing and Apple Developer ID signing/notarization +credentials in GitHub Actions. The release workflow refuses to publish stable installers when +those credentials are unavailable. ## Project Structure diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 120d2fd..1e782a1 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -12,17 +12,17 @@ }, "dependencies": { "@jauto/core": "workspace:*", - "@jauto/ui": "workspace:*", "@jauto/file-io": "workspace:*", - "@tauri-apps/api": "^2", - "vue": "^3", - "pinia": "^3" + "@jauto/ui": "workspace:*", + "@tauri-apps/api": "^2.11.1", + "pinia": "^3.0.4", + "vue": "^3.5.35" }, "devDependencies": { - "@tauri-apps/cli": "^2", - "@vitejs/plugin-vue": "^5", - "vite": "^6", - "typescript": "^5.8", - "vue-tsc": "^2" + "@tauri-apps/cli": "^2.11.4", + "@vitejs/plugin-vue": "^6.0.7", + "typescript": "^6.0.3", + "vite": "^8.0.16", + "vue-tsc": "^3.3.3" } } diff --git a/apps/desktop/src-tauri/Cargo.lock b/apps/desktop/src-tauri/Cargo.lock index 59b22a3..7250c10 100644 --- a/apps/desktop/src-tauri/Cargo.lock +++ b/apps/desktop/src-tauri/Cargo.lock @@ -253,9 +253,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" @@ -292,9 +292,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ "serde_core", ] @@ -332,9 +332,9 @@ dependencies = [ [[package]] name = "brotli" -version = "8.0.2" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -343,9 +343,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -362,9 +362,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytemuck" @@ -393,7 +393,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cairo-sys-rs", "glib", "libc", @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.62" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "shlex", @@ -499,9 +499,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "num-traits", @@ -560,7 +560,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation", "core-graphics-types", "foreign-types", @@ -573,7 +573,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation", "libc", ] @@ -773,7 +773,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -781,9 +781,9 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", @@ -1351,7 +1351,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "futures-channel", "futures-core", "futures-executor", @@ -1518,9 +1518,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" dependencies = [ "bytes", "itoa", @@ -1557,9 +1557,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -1870,9 +1870,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.98" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ "cfg-if", "futures-util", @@ -1908,7 +1908,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "serde", "unicode-segmentation", ] @@ -1980,9 +1980,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ "libc", ] @@ -2010,9 +2010,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" [[package]] name = "markup5ever" @@ -2027,9 +2027,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memoffset" @@ -2058,9 +2058,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "wasi", @@ -2069,9 +2069,9 @@ dependencies = [ [[package]] name = "muda" -version = "0.19.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae8844f63b5b118e334e205585b8c5c17b984121dbdb179d44aeb087ffad3cb" +checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" dependencies = [ "crossbeam-channel", "dpi", @@ -2094,7 +2094,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "jni-sys 0.3.1", "log", "ndk-sys", @@ -2171,7 +2171,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-core-foundation", @@ -2184,7 +2184,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-foundation", ] @@ -2205,7 +2205,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2", ] @@ -2216,7 +2216,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2", "objc2-core-foundation", @@ -2249,7 +2249,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -2276,7 +2276,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-core-foundation", @@ -2288,7 +2288,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", ] @@ -2299,7 +2299,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -2311,7 +2311,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-cloud-kit", @@ -2342,7 +2342,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "objc2", "objc2-app-kit", @@ -2540,7 +2540,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crc32fast", "fdeflate", "flate2", @@ -2633,7 +2633,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -2740,7 +2740,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -2805,9 +2805,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64 0.22.1", "bytes", @@ -2882,7 +2882,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys", @@ -2973,7 +2973,7 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cssparser", "derive_more", "log", @@ -3051,9 +3051,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -3093,9 +3093,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" dependencies = [ "base64 0.22.1", "bs58", @@ -3113,9 +3113,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ "darling", "proc-macro2", @@ -3167,9 +3167,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook-registry" @@ -3207,9 +3207,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", "windows-sys 0.61.2", @@ -3366,11 +3366,11 @@ dependencies = [ [[package]] name = "tao" -version = "0.35.2" +version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33f7f9e486ade65fcf1e45c440f9236c904f5c1002cdc7fc6ae582777345ce4" +checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "core-foundation", "core-graphics", @@ -3875,9 +3875,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.11+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", @@ -3921,7 +3921,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "bytes", "futures-util", "http", @@ -4012,9 +4012,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "uds_windows" @@ -4076,9 +4076,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-xid" @@ -4131,9 +4131,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" dependencies = [ "getrandom 0.4.2", "js-sys", @@ -4218,9 +4218,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -4231,9 +4231,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.71" +version = "0.4.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" dependencies = [ "js-sys", "wasm-bindgen", @@ -4241,9 +4241,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4251,9 +4251,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", @@ -4264,9 +4264,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.121" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] @@ -4312,7 +4312,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "hashbrown 0.15.5", "indexmap 2.14.0", "semver", @@ -4338,7 +4338,7 @@ version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "rustix", "wayland-backend", "wayland-scanner", @@ -4350,7 +4350,7 @@ version = "0.32.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -4380,9 +4380,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.98" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" dependencies = [ "js-sys", "wasm-bindgen", @@ -4929,7 +4929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.1", + "bitflags 2.13.0", "indexmap 2.14.0", "log", "serde", @@ -5032,9 +5032,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -5055,9 +5055,9 @@ dependencies = [ [[package]] name = "zbus" -version = "5.15.0" +version = "5.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bcbf15c8708d7fc1be0c993622e0a5cbd5e8b52bfa40afa4c3e0cd8d724ac1" +checksum = "eee682d202a77e4a9f3b2c2bdf48a7b28af5c08c34ddf66f98c93e5e39464285" dependencies = [ "async-broadcast", "async-executor", @@ -5090,9 +5090,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.15.0" +version = "5.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51fa5406ad9175a8c825a931f8cf347116b531b3634fcb0b627c290f1f2516ff" +checksum = "adf1bd45a81a103745b1757754762a26e8cd01e4532e4d6c8ec431624b80d1d6" dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", @@ -5116,18 +5116,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" dependencies = [ "proc-macro2", "quote", @@ -5196,9 +5196,9 @@ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zvariant" -version = "5.11.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee" +checksum = "a192a0bde63360d77a7523c833d4b4ce6070a927e2c53246e4c540b1a3e27be0" dependencies = [ "endi", "enumflags2", @@ -5211,9 +5211,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "5.11.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda" +checksum = "90bc6cde9c01c511074be97f7ccb6c19d0da89e3f8662e812e999dcfd4638737" dependencies = [ "proc-macro-crate 3.5.0", "proc-macro2", @@ -5224,9 +5224,9 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d464f5733ffa07a3164d656f18533caace9d0638596721355d73256a410d691" +checksum = "1e8535915cfa75547e559d8c68e8139909a4aeee076831e4ef7fc59d8172c4d6" dependencies = [ "proc-macro2", "quote", diff --git a/apps/desktop/src-tauri/capabilities/main.json b/apps/desktop/src-tauri/capabilities/main.json new file mode 100644 index 0000000..1305f42 --- /dev/null +++ b/apps/desktop/src-tauri/capabilities/main.json @@ -0,0 +1,11 @@ +{ + "$schema": "../gen/schemas/desktop-schema.json", + "identifier": "main-window", + "description": "Core event and close APIs used by the main editor window.", + "windows": ["main"], + "permissions": [ + "core:event:default", + "core:window:default", + "core:window:allow-close" + ] +} diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index 7e51708..c445976 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -12,6 +12,12 @@ struct FileOpenResult { path: String, } +#[derive(Serialize)] +struct FileSaveResult { + name: String, + path: String, +} + #[tauri::command] async fn open_file() -> Result, String> { let Some(file) = rfd::AsyncFileDialog::new() @@ -33,7 +39,20 @@ async fn open_file() -> Result, String> { } #[tauri::command] -async fn save_file(content: String, default_name: String) -> Result, String> { +async fn save_file( + content: String, + default_name: String, + current_path: Option, +) -> Result, String> { + if let Some(current_path) = current_path { + let path = std::path::PathBuf::from(current_path); + fs::write(&path, content).map_err(|err| err.to_string())?; + return Ok(Some(FileSaveResult { + name: file_name(&path, &default_name), + path: path.to_string_lossy().into_owned(), + })); + } + let Some(file) = rfd::AsyncFileDialog::new() .add_filter("JFLAP Files", &["jff"]) .set_file_name(&default_name) @@ -45,7 +64,10 @@ async fn save_file(content: String, default_name: String) -> Result String { fn build_menu(app: &mut tauri::App) -> tauri::Result<()> { let home = MenuItem::with_id(app, "menu:home", "Back to Home", true, Some("Alt+Left"))?; let new_fa = MenuItem::with_id(app, "menu:new-fa", "New DFA/NFA", true, Some("CmdOrCtrl+N"))?; - let new_pda = - MenuItem::with_id(app, "menu:new-pda", "New PDA", true, Some("CmdOrCtrl+Shift+N"))?; + let new_pda = MenuItem::with_id( + app, + "menu:new-pda", + "New PDA", + true, + Some("CmdOrCtrl+Shift+N"), + )?; let new_tm = MenuItem::with_id( app, "menu:new-tm", @@ -83,8 +110,16 @@ fn build_menu(app: &mut tauri::App) -> tauri::Result<()> { Some("CmdOrCtrl+Alt+N"), )?; let open = MenuItem::with_id(app, "menu:open", "Open...", true, Some("CmdOrCtrl+O"))?; - let save = MenuItem::with_id(app, "menu:save", "Save As...", true, Some("CmdOrCtrl+S"))?; - let export_png = MenuItem::with_id(app, "menu:export-png", "Export PNG...", true, None::<&str>)?; + let save = MenuItem::with_id(app, "menu:save", "Save", true, Some("CmdOrCtrl+S"))?; + let save_as = MenuItem::with_id( + app, + "menu:save-as", + "Save As...", + true, + Some("CmdOrCtrl+Shift+S"), + )?; + let export_png = + MenuItem::with_id(app, "menu:export-png", "Export PNG...", true, None::<&str>)?; let undo = MenuItem::with_id(app, "menu:undo", "Undo", true, Some("CmdOrCtrl+Z"))?; let redo = MenuItem::with_id(app, "menu:redo", "Redo", true, Some("CmdOrCtrl+Shift+Z"))?; let reload = MenuItem::with_id(app, "menu:reload", "Reload", true, Some("CmdOrCtrl+R"))?; @@ -103,6 +138,7 @@ fn build_menu(app: &mut tauri::App) -> tauri::Result<()> { .separator() .item(&open) .item(&save) + .item(&save_as) .separator() .item(&export_png) .separator() diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index b7fea8e..77fe1f0 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -18,7 +18,7 @@ } ], "security": { - "csp": null + "csp": "default-src 'self'; img-src 'self' asset: data:; style-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src ipc: http://ipc.localhost; script-src 'self'" } }, "bundle": { diff --git a/apps/desktop/src/renderer/index.html b/apps/desktop/src/renderer/index.html index 87ec91b..2c18200 100644 --- a/apps/desktop/src/renderer/index.html +++ b/apps/desktop/src/renderer/index.html @@ -3,12 +3,6 @@ - - - Jauto diff --git a/apps/desktop/src/renderer/src/App.vue b/apps/desktop/src/renderer/src/App.vue index 2c02cbc..e950dae 100644 --- a/apps/desktop/src/renderer/src/App.vue +++ b/apps/desktop/src/renderer/src/App.vue @@ -1,113 +1,71 @@