diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a8a7839 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto eol=lf +install.sh text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c17bd0a..e37e204 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,108 +1,108 @@ -name: CI - -on: - pull_request: - branches: - - develop - - main - -permissions: - contents: read - pull-requests: write - -env: - CARGO_TERM_COLOR: always - -jobs: - check: - name: Check, Test & Clippy - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - - - name: Cache cargo registry - uses: actions/cache@v4 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v4 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo build - uses: actions/cache@v4 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} - - - name: Cargo fmt - run: cargo fmt --check - - - name: Cargo build - run: cargo build --release - - - name: Cargo test - run: cargo test - - - name: Cargo clippy - run: cargo clippy --all-targets -- -D warnings - - publish-check: - name: Publish Check (dry-run) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable - - - name: Cache cargo registry - uses: actions/cache@v4 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - - - name: Cache cargo index - uses: actions/cache@v4 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - - - name: Cargo publish dry-run - run: cargo publish --dry-run - - # Validaciones adicionales para PRs a main - main-pr-checks: - name: Main PR Requirements - if: github.base_ref == 'main' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Check version bump - run: | - # Obtener la versión actual - CURRENT_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') - echo "Versión en Cargo.toml: $CURRENT_VERSION" - - # Obtener el último tag - LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - if [ -z "$LAST_TAG" ]; then - echo "✅ Primer release (no hay tags previos)" - else - LAST_VERSION=${LAST_TAG#v} - echo "Última versión en tag: $LAST_VERSION" - if [ "$CURRENT_VERSION" = "$LAST_VERSION" ]; then - echo "❌ Error: La versión en Cargo.toml debe bumpearse en PR a main" - echo "Cambio requerido para PRs a main:" - echo "- develop → main: version DEBE incrementarse" - exit 1 - fi - echo "✅ Versión bumpeada correctamente" - fi +name: CI + +on: + pull_request: + branches: + - develop + - main + +permissions: + contents: read + pull-requests: write + +env: + CARGO_TERM_COLOR: always + +jobs: + check: + name: Check, Test & Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Cargo fmt + run: cargo fmt --check + + - name: Cargo build + run: cargo build --release + + - name: Cargo test + run: cargo test + + - name: Cargo clippy + run: cargo clippy --all-targets -- -D warnings + + publish-check: + name: Publish Check (dry-run) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cargo publish dry-run + run: cargo publish --dry-run + + # Validaciones adicionales para PRs a main + main-pr-checks: + name: Main PR Requirements + if: github.base_ref == 'main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check version bump + run: | + # Obtener la versión actual + CURRENT_VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') + echo "Versión en Cargo.toml: $CURRENT_VERSION" + + # Obtener el último tag + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + if [ -z "$LAST_TAG" ]; then + echo "✅ Primer release (no hay tags previos)" + else + LAST_VERSION=${LAST_TAG#v} + echo "Última versión en tag: $LAST_VERSION" + if [ "$CURRENT_VERSION" = "$LAST_VERSION" ]; then + echo "❌ Error: La versión en Cargo.toml debe bumpearse en PR a main" + echo "Cambio requerido para PRs a main:" + echo "- develop → main: version DEBE incrementarse" + exit 1 + fi + echo "✅ Versión bumpeada correctamente" + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd394a3..0dcc79c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -107,7 +107,7 @@ jobs: if: matrix.archive == 'tar.gz' run: | cd target/${{ matrix.target }}/release - tar czf ../../../task-trigger-mcp-${{ needs.create-tag.outputs.tag }}-${{ matrix.target }}.tar.gz task-trigger-mcp + tar czf ../../../texforge-${{ needs.create-tag.outputs.tag }}-${{ matrix.target }}.tar.gz texforge cd ../../.. - name: Package (windows) @@ -115,14 +115,14 @@ jobs: shell: pwsh run: | cd target/${{ matrix.target }}/release - Compress-Archive -Path task-trigger-mcp.exe -DestinationPath ../../../task-trigger-mcp-${{ needs.create-tag.outputs.tag }}-${{ matrix.target }}.zip + Compress-Archive -Path texforge.exe -DestinationPath ../../../texforge-${{ needs.create-tag.outputs.tag }}-${{ matrix.target }}.zip cd ../../.. - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: task-trigger-mcp-${{ matrix.target }} - path: task-trigger-mcp-${{ needs.create-tag.outputs.tag }}-${{ matrix.target }}.* + name: texforge-${{ matrix.target }} + path: texforge-${{ needs.create-tag.outputs.tag }}-${{ matrix.target }}.* github-release: name: Create GitHub Release @@ -168,4 +168,3 @@ jobs: - name: Cargo publish run: cargo publish --token ${{ secrets.CARGO_TOKEN }} - diff --git a/.gitignore b/.gitignore index 117cab1..bbfa1f0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ Cargo.lock .kiro/ .agents/ .idea/ -texforge-spec.md +skills-lock.json \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 8258f6c..8b1e61a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ clap = { version = "4.6", features = ["derive"] } # Error handling anyhow = "1.0" -thiserror = "2.0" # Serialization (for project.toml, template.toml) serde = { version = "1.0", features = ["derive"] } @@ -31,6 +30,13 @@ walkdir = "2.5" # Home directory resolution dirs = "6.0" +# HTTP client (template downloads) +reqwest = { version = "0.13", features = ["blocking"] } + +# Archive extraction (GitHub tarballs) +flate2 = "1.1" +tar = "0.4" + [dev-dependencies] tempfile = "3.8" diff --git a/README.md b/README.md index 64b36da..06c9a94 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,63 @@ -# TexForge +# texforge -> Self-contained LaTeX to PDF compiler — zero external dependencies +[![CI](https://github.com/JheisonMB/texforge/actions/workflows/ci.yml/badge.svg)](https://github.com/JheisonMB/texforge/actions/workflows/ci.yml) +[![Release](https://github.com/JheisonMB/texforge/actions/workflows/release.yml/badge.svg)](https://github.com/JheisonMB/texforge/actions/workflows/release.yml) +[![Crates.io](https://img.shields.io/crates/v/texforge)](https://crates.io/crates/texforge) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -TexForge is a command-line tool that compiles LaTeX documents to PDF without requiring TeX Live, MiKTeX, or any external LaTeX distribution. +Self-contained LaTeX to PDF compiler — one curl, zero friction. No TeX Live, no MiKTeX, no Perl, no Node. A single install sets up everything you need. -## Features - -- **Self-contained**: Single binary, no external dependencies -- **Clean errors**: Actionable error messages with line numbers and context -- **Template system**: Managed preambles, you only write document content -- **Built-in tools**: Formatter, linter, and build system in one CLI +--- ## Installation +### Quick install (recommended) + +```bash +curl -fsSL https://raw.githubusercontent.com/JheisonMB/texforge/main/install.sh | sh +``` + +This downloads and installs both `texforge` and `tectonic` (the LaTeX engine). Nothing else needed. No Rust toolchain required. + +You can customize the install: + +```bash +# Pin a specific version +VERSION=0.1.0 curl -fsSL https://raw.githubusercontent.com/JheisonMB/texforge/main/install.sh | sh + +# Install to a custom directory +INSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/JheisonMB/texforge/main/install.sh | sh +``` + +### Via cargo + ```bash cargo install texforge ``` +**Note:** This only installs texforge. You also need tectonic for compilation: + +```bash +cargo install tectonic +``` + +Available on [crates.io](https://crates.io/crates/texforge). + +### From source + +```bash +git clone https://github.com/JheisonMB/texforge.git +cd texforge +cargo build --release +# Binary at target/release/texforge +``` + +### GitHub Releases + +Check the [Releases](https://github.com/JheisonMB/texforge/releases) page for precompiled binaries (Linux x86_64, macOS x86_64/ARM64, Windows x86_64). + +--- + ## Quick Start ```bash @@ -33,31 +74,169 @@ texforge fmt texforge build ``` +--- + +## Commands + +| Command | Description | +|---|---| +| `texforge new ` | Create new project from template | +| `texforge new -t