min_version = "2024.1.0"
[tasks.help]
description = "Show available tasks"
run = """
#!/usr/bin/env bash
set -euo pipefail
mise tasks ls
"""
[tasks.setup]
description = "Set up development environment (git hooks, dependencies, etc.)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ง Setting up development environment..."
if [ ! -d ".githooks" ]; then mkdir -p .githooks; fi
if [ -f ".githooks/commit-msg" ]; then chmod +x .githooks/commit-msg; fi
echo "๐ Configuring git hooks..."
git config --local core.hooksPath .githooks
if [ -f ".gitmessage" ]; then
echo "๐ Setting commit message template..."
git config --local commit.template .gitmessage
fi
if ! command -v committed >/dev/null 2>&1; then
echo "๐ฆ Installing committed (Conventional Commits linter)..."
if command -v cargo-binstall >/dev/null 2>&1; then
cargo binstall -y committed
else
cargo install committed
fi
fi
echo "๐ฆ Checking Rust components..."
if ! rustup component list --installed | grep -q rustfmt; then rustup component add rustfmt; fi
if ! rustup component list --installed | grep -q clippy; then rustup component add clippy; fi
echo "๐ง Git hooks configuration..."
if command -v pre-commit >/dev/null 2>&1; then
echo "๐ก Pre-commit is available. Choose your hook system:"
echo " โข Manual hooks (current): Already configured in .githooks/"
echo " โข Enterprise pre-commit: Run 'mise run pre-commit-install'"
echo "โ
Manual git hooks remain active"
else
echo "โ
Manual git hooks configured in .githooks/"
echo "๐ก For enterprise-grade hooks: brew install pre-commit && mise run pre-commit-install"
fi
echo "โ
Development environment setup complete"
"""
[tasks.dev-setup]
description = "Alias for setup"
depends = ["setup"]
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "Development setup complete. Run 'mise tasks' for available commands."
"""
[tasks.clean]
description = "Clean build artifacts and temporary files"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งน Cleaning build artifacts..."
cargo clean
rm -f debug_*
rm -f test_*
rm -f lcov.info cobertura.xml
rm -rf target/tarpaulin target/llvm-cov
find . -name "*.tmp" -delete
echo "โ
Clean complete"
"""
[tasks.test]
description = "Run all tests"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running tests..."
timeout 30s cargo test --lib --verbose
"""
[tasks.test-release]
description = "Run tests in release mode"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running tests in release mode..."
timeout 30s cargo test --lib --release --verbose
"""
[tasks.test-all-features]
description = "Run tests with all features"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running tests with all features..."
timeout 30s cargo test --lib --all-features --verbose || [ $? -eq 124 ]
"""
[tasks.test-no-default]
description = "Run tests without default features"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running tests without default features..."
timeout 30s cargo test --lib --no-default-features --verbose || [ $? -eq 124 ]
"""
[tasks.test-nocapture]
description = "Run tests with output capture disabled"
alias = "test-verbose"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running tests with output visible..."
timeout 30s cargo test -- --nocapture
"""
[tasks.test-lib]
description = "Run library tests only"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running library tests..."
timeout 30s cargo test --lib
"""
[tasks.test-integration]
description = "Run integration tests"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running integration tests..."
# `--tests` auto-discovers every `tests/*.rs` binary, so newly added test
# files (e.g. `tests/directives.rs`) get picked up here without being
# enumerated. Matches what CI / nextest sees end-to-end.
timeout 300s cargo test --tests
"""
[tasks.test-security]
description = "Run security-specific tests"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running security tests..."
timeout 60s cargo test --test security_limits
timeout 60s cargo test --test security_limits test_nested_alias_expansion_limit
"""
[tasks.yaml-test-suite]
description = "Run upstream yaml-test-suite conformance harness"
alias = "test-yaml-suite"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งช Running yaml/yaml-test-suite conformance harness..."
git submodule update --init --recursive yaml-test-suite/data
timeout 300s cargo test -p yaml-test-suite -- --nocapture
"""
[tasks.format]
description = "Format code"
alias = "fmt"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐จ Formatting code..."
cargo fmt
"""
[tasks.format-check]
description = "Check code formatting"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐จ Checking code formatting..."
cargo fmt --all -- --check
"""
[tasks.lint]
description = "Run clippy lints"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running clippy..."
timeout 30s cargo clippy --all-targets --all-features -- -D warnings
"""
[tasks.lint-fix]
description = "Run clippy with automatic fixes"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running clippy with fixes..."
timeout 30s cargo clippy --all-targets --all-features --fix -- -D warnings
"""
[tasks.clippy-strict]
description = "Run clippy with strict CI settings"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running clippy with strict CI settings..."
timeout 180s cargo clippy --all-targets --all-features -- -D warnings -D clippy::all -D clippy::pedantic -W clippy::nursery \
-A clippy::needless_raw_string_hashes \
-A clippy::format_push_string \
-A clippy::single_char_pattern \
-A clippy::unreadable_literal \
-A clippy::manual_string_new \
-A clippy::write_with_newline \
-A clippy::uninlined_format_args \
-A clippy::semicolon_if_nothing_returned \
-A clippy::explicit_iter_loop \
-A clippy::inefficient_to_string \
-A clippy::match_same_arms \
-A clippy::doc_markdown \
-A clippy::too_many_lines
"""
[tasks.audit]
description = "Run security audit"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running security audit..."
if ! command -v cargo-audit >/dev/null; then cargo install cargo-audit; fi
cargo audit
"""
[tasks.deny]
description = "Run cargo deny checks"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running cargo deny checks..."
if ! command -v cargo-deny >/dev/null; then cargo install cargo-deny; fi
timeout 15s cargo deny check
"""
[tasks.doc]
description = "Build documentation (treats rustdoc warnings as errors)"
alias = "docs"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Building documentation..."
RUSTDOCFLAGS="-D warnings" cargo doc --all-features --no-deps
"""
[tasks.doc-open]
description = "Build and open documentation"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Building and opening documentation..."
cargo doc --all-features --no-deps --open
"""
[tasks.doc-private]
description = "Build documentation including private items"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Building documentation with private items..."
cargo doc --all-features --no-deps --document-private-items
"""
[tasks.bench]
description = "Run benchmarks"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "โก Running benchmarks..."
cargo bench
"""
[tasks.bench-compile]
description = "Compile benchmarks only"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "โก Compiling benchmarks..."
cargo bench --no-run
"""
[tasks.coverage]
description = "Generate test coverage report (same as CI)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Generating coverage report (CI-compatible)..."
if ! command -v cargo-tarpaulin >/dev/null; then
echo "Installing cargo-tarpaulin..."
cargo install cargo-tarpaulin
fi
cargo tarpaulin --lib --tests --out lcov --output-dir . --verbose --workspace --timeout 120 --exclude-files examples/* benches/*
echo "โ
Coverage report generated: lcov.info"
echo "๐ Coverage summary:"
cargo tarpaulin --lib --tests --print-summary --workspace --timeout 120 --exclude-files examples/* benches/*
"""
[tasks.coverage-html]
description = "Generate HTML coverage report"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Generating HTML coverage report..."
if ! command -v cargo-tarpaulin >/dev/null; then
echo "Installing cargo-tarpaulin..."
cargo install cargo-tarpaulin
fi
cargo tarpaulin --lib --tests --out html --output-dir target/tarpaulin --verbose --workspace --timeout 120 --exclude-files examples/* benches/*
echo "โ
HTML coverage report generated in target/tarpaulin/"
echo "๐ Open target/tarpaulin/tarpaulin-report.html in your browser"
"""
[tasks.coverage-llvm]
description = "Generate coverage using llvm-cov (alternative)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Generating coverage with llvm-cov..."
if ! command -v cargo-llvm-cov >/dev/null; then
echo "Installing cargo-llvm-cov..."
cargo install cargo-llvm-cov
fi
cargo llvm-cov --lib --lcov --output-path lcov.info
echo "โ
Coverage report generated: lcov.info"
"""
[tasks.coverage-llvm-html]
description = "Generate HTML coverage with llvm-cov"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Generating HTML coverage with llvm-cov..."
if ! command -v cargo-llvm-cov >/dev/null; then
echo "Installing cargo-llvm-cov..."
cargo install cargo-llvm-cov
fi
cargo llvm-cov --lib --html
echo "โ
HTML coverage report generated in target/llvm-cov/html/"
"""
[tasks.coverage-clean]
description = "Clean coverage artifacts"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งน Cleaning coverage artifacts..."
rm -f lcov.info cobertura.xml
rm -rf target/tarpaulin target/llvm-cov
echo "โ
Coverage artifacts cleaned"
"""
[tasks.coverage-view]
description = "Generate and open HTML coverage report"
depends = ["coverage-html"]
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Opening coverage report in browser..."
if [ -f target/tarpaulin/tarpaulin-report.html ]; then
open target/tarpaulin/tarpaulin-report.html 2>/dev/null \
|| xdg-open target/tarpaulin/tarpaulin-report.html 2>/dev/null \
|| echo "Please open target/tarpaulin/tarpaulin-report.html manually"
fi
"""
[tasks.coverage-install-tools]
description = "Install coverage tools"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ฆ Installing coverage tools..."
cargo install cargo-tarpaulin cargo-llvm-cov
echo "โ
Coverage tools installed"
"""
[tasks.build]
description = "Build the project"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐จ Building project..."
cargo build
"""
[tasks.build-release]
description = "Build in release mode"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐จ Building project in release mode..."
timeout 30s cargo build --release
"""
[tasks.build-all-features]
description = "Build with all features"
alias = "build-all"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐จ Building project with all features..."
cargo build --all-features
"""
[tasks.examples]
description = "Run examples"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ก Running examples..."
cargo run --example library_comparison
"""
[tasks.package]
description = "Package the crate"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ฆ Packaging crate..."
cargo package
"""
[tasks.package-list]
description = "List files that would be packaged"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ฆ Listing package contents..."
cargo package --list
"""
[tasks.check]
description = "Run basic checks (build, test, format, lint)"
alias = "checks"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "โ
Running basic checks..."
mise run format-check
mise run lint
mise run test
echo "โ
All basic checks passed"
"""
[tasks.check-all]
description = "Run all checks including audit and coverage"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "โ
Running comprehensive checks..."
mise run format-check
mise run lint
mise run test-all-features
mise run test-no-default
mise run audit
mise run doc
mise run bench-compile
mise run check-markdown
echo "โ
All comprehensive checks passed"
"""
[tasks.ci]
description = "Run CI pipeline locally (same as GitHub Actions)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running CI pipeline locally..."
mise run format-check
mise run clippy-strict
echo "๐๏ธ Pre-compiling test artifacts (warms dev-deps for subsequent steps)..."
timeout 300s cargo test --no-run --tests --quiet
mise run test-lib
mise run test-integration
mise run test-security
mise run deny
echo "โ
CI pipeline completed successfully!"
"""
[tasks.quick-check]
description = "Quick development checks (format, clippy, test)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "โก Running quick checks..."
mise run format
mise run lint
mise run test-lib
echo "โ
Quick checks passed!"
"""
[tasks.release-check]
description = "Check if ready for release"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Checking release readiness..."
mise run check-all
echo "Checking version consistency..."
CARGO_VERSION=$(grep '^version = ' Cargo.toml | sed 's/version = "\\(.*\\)"/\\1/')
if [ -f GitVersion.yml ]; then
GITVERSION_VERSION=$(grep 'next-version:' GitVersion.yml | sed 's/next-version: "\\?\\(.*\\)"\\?/\\1/' | sed 's/-.*//')
if [ "$CARGO_VERSION" != "$GITVERSION_VERSION" ]; then
echo "โ Version mismatch: Cargo.toml=$CARGO_VERSION, GitVersion.yml=$GITVERSION_VERSION"
exit 1
fi
fi
echo "โ
Release check passed"
"""
[tasks.release]
description = "Interactive release (manual process)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Manual Release Process"
echo ""
echo "๐ Release Steps:"
echo " 1. Update version in Cargo.toml"
echo " 2. Update version in GitVersion.yml"
echo " 3. Run: mise run release-check"
echo " 4. Commit changes with: git commit -m 'chore: release version X.Y.Z [skip ci]'"
echo " 5. Create tag: git tag vX.Y.Z"
echo " 6. Push: git push origin main && git push origin vX.Y.Z"
echo ""
echo "๐ก Or use GitHub Actions 'Manual Version Bump' workflow"
"""
[tasks.release-patch]
description = "Guide for patch release"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Patch Release Guide"
mise run release
"""
[tasks.release-minor]
description = "Guide for minor release"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Minor Release Guide"
mise run release
"""
[tasks.release-major]
description = "Guide for major release"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Major Release Guide"
mise run release
"""
[tasks.pre-commit]
description = "Run pre-commit checks"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running pre-commit checks..."
mise run format
mise run lint
mise run test
echo "โ
Pre-commit checks passed"
"""
[tasks.pre-push]
description = "Run pre-push checks"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running pre-push checks..."
mise run check-all
echo "โ
Pre-push checks passed"
"""
[tasks.commit-lint]
description = "Test commit message format (via committed). Usage: MSG='feat: x' mise run commit-lint (or: mise run commit-lint -- 'feat: x')"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Testing commit message format..."
msg="${MSG:-}"
if [ -z "$msg" ] && [ "$#" -gt 0 ]; then msg="$1"; fi
if [ -z "$msg" ]; then
echo "Usage: MSG='feat: add new feature' mise run commit-lint"
echo " or: mise run commit-lint -- 'feat: add new feature'"
exit 1
fi
if ! command -v committed >/dev/null 2>&1; then
echo "โ committed not found. Install with: cargo install committed"
exit 1
fi
printf '%s\\n' "$msg" | committed --commit-file -
echo "โ
Commit message format is valid"
"""
[tasks.git-status]
description = "Show git status with helpful formatting"
run = """
#!/usr/bin/env bash
set -euo pipefail
if [ -z "$(git status --porcelain)" ]; then
echo "โ
Working directory clean"
else
echo "๐ Working directory changes:"
git status --short
fi
"""
[tasks.pre-commit-install]
description = "Install pre-commit hooks (replaces manual git hooks)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ง Installing pre-commit hooks..."
if ! command -v pre-commit >/dev/null; then
echo "โ pre-commit not found. Install with: brew install pre-commit"
exit 1
fi
echo "๐ Switching from manual git hooks to pre-commit..."
git config --unset-all core.hooksPath || true
pre-commit install --install-hooks
pre-commit install --hook-type commit-msg
echo "โ
Pre-commit hooks installed (manual .githooks disabled)"
"""
[tasks.pre-commit-run]
description = "Run pre-commit hooks on all files"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running pre-commit hooks on all files..."
timeout 120s pre-commit run --all-files
"""
[tasks.pre-commit-dev]
description = "Run pre-commit hooks (without timeout for development)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running pre-commit hooks..."
pre-commit run --all-files
"""
[tasks.pre-commit-update]
description = "Update pre-commit hooks to latest versions"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "โฌ๏ธ Updating pre-commit hooks..."
pre-commit autoupdate
"""
[tasks.pre-commit-clean]
description = "Clean pre-commit cache"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐งน Cleaning pre-commit cache..."
pre-commit clean
"""
[tasks.pre-commit-rust]
description = "Run only Rust-specific pre-commit hooks"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ฆ Running Rust-specific pre-commit hooks..."
pre-commit run rust-fmt rust-clippy rust-check rust-test rust-doc
"""
[tasks.pre-commit-quick]
description = "Run quick pre-commit hooks (skip tests and audits)"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "โก Running quick pre-commit hooks..."
SKIP=rust-test,rust-coverage,rust-audit,rust-deny pre-commit run --all-files
"""
[tasks.pre-commit-security]
description = "Run security-focused pre-commit hooks"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Running security-focused pre-commit hooks..."
pre-commit run detect-private-key detect-secrets rust-audit rust-deny
"""
[tasks.install-tools]
description = "Install additional development tools"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ง Installing development tools..."
if ! command -v cargo-audit >/dev/null; then cargo install cargo-audit; fi
if ! command -v cargo-llvm-cov >/dev/null; then cargo install cargo-llvm-cov; fi
if ! command -v cargo-criterion >/dev/null; then cargo install cargo-criterion; fi
if ! command -v cargo-flamegraph >/dev/null; then cargo install flamegraph; fi
echo "โ
Development tools installed"
"""
[tasks.version]
description = "Show version information"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Version Information:"
echo "Cargo version: $(grep '^version = ' Cargo.toml | sed 's/version = "\\(.*\\)"/\\1/')"
if [ -f GitVersion.yml ]; then
echo "GitVersion next: $(grep 'next-version:' GitVersion.yml | sed 's/next-version: "\\?\\(.*\\)"\\?/\\1/')"
fi
if command -v git >/dev/null && git rev-parse --git-dir >/dev/null 2>&1; then
echo "Git commit: $(git rev-parse --short HEAD)"
echo "Git branch: $(git branch --show-current)"
fi
"""
[tasks.debug-env]
description = "Show development environment information"
run = """
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Development Environment:"
echo "Rust version: $(rustc --version)"
echo "Cargo version: $(cargo --version)"
if command -v committed >/dev/null; then echo "committed version: $(committed --version)"; fi
echo "Git hooks path: $(git config --get core.hooksPath || echo 'default')"
echo "Commit template: $(git config --get commit.template || echo 'none')"
"""
[tasks.check-markdown]
description = "Check markdown formatting (strict โ any warning fails the target)"
run = '''
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Checking markdown formatting..."
fail=0
for file in *.md; do
if [ -f "$file" ]; then
echo "Checking $file..."
echo "=== MD022 (blank line before heading) ==="
awk 'BEGIN { in_fence = 0; prev = ""; issues = 0 }
/^```/ { in_fence = !in_fence; prev = $0; next }
in_fence { prev = $0; next }
NR > 1 && /^#{1,6} / && prev != "" { print " Line " NR ": " $0; issues++ }
{ prev = $0 }
END { exit (issues > 0 ? 1 : 0) }' "$file" || fail=1
echo "=== MD032 (blank line before list) ==="
awk 'BEGIN { in_fence = 0; prev = ""; issues = 0 }
/^```/ { in_fence = !in_fence; prev = $0; next }
in_fence { prev = $0; next }
NR > 1 && (/^[-*+] / || /^[0-9]+\. /) && prev != "" \
&& prev !~ /^[-*+] / && prev !~ /^[0-9]+\. / \
&& prev !~ /^[ \t]/ { print " Line " NR ": " $0; issues++ }
{ prev = $0 }
END { exit (issues > 0 ? 1 : 0) }' "$file" || fail=1
echo ""
fi
done
if [ $fail -ne 0 ]; then
echo "โ Markdown checks failed โ fix the listed lines or update the source files"
exit 1
fi
echo "โ
Markdown checks passed"
'''
[tasks.fix-markdown]
description = "Fix common markdown formatting issues"
run = '''
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Fixing markdown issues (MD022: blanks around headings, MD031: blanks around fences, MD032: blanks around lists, bold-as-headings)..."
for file in *.md docs/*.md; do
if [ -f "$file" ]; then
echo "Processing $file..."
awk 'BEGIN { prev_line = ""; in_code_block = 0; last_was_blank = 0; need_blank_after = 0 }
/^```/ {
if (!in_code_block) {
if (NR > 1 && !last_was_blank) { print "" }
in_code_block = 1; print; need_blank_after = 0
} else {
in_code_block = 0; print; need_blank_after = 1
}
prev_line = $0; last_was_blank = 0; next
}
in_code_block { print; prev_line = $0; last_was_blank = 0; next }
/^#{1,6} \*\*.*\*\*/ { gsub(/\*\*/, "", $0) }
/^#{1,6} / {
if (need_blank_after) { print ""; need_blank_after = 0 }
if (NR > 1 && !last_was_blank && prev_line !~ /^#{1,6} /) { print "" }
print; prev_line = $0; last_was_blank = 0; next
}
/^[-*+] / || /^[0-9]+\. / {
if (need_blank_after) { print ""; need_blank_after = 0 }
if (NR > 1 && !last_was_blank && prev_line !~ /^[-*+] / && prev_line !~ /^[0-9]+\. / && prev_line !~ /^ /) { print "" }
print; prev_line = $0; last_was_blank = 0; next
}
/^$/ {
if (need_blank_after) { need_blank_after = 0 }
print; prev_line = $0; last_was_blank = 1; next
}
{
if (need_blank_after) { print ""; need_blank_after = 0 }
if (prev_line ~ /^#{1,6} / && !last_was_blank) { print "" }
if ((prev_line ~ /^[-*+] / || prev_line ~ /^[0-9]+\. /) && $0 !~ /^[-*+] / && $0 !~ /^[0-9]+\. / && $0 !~ /^ / && !last_was_blank) { print "" }
print; prev_line = $0; last_was_blank = 0
}' "$file" > "$file.tmp" && mv "$file.tmp" "$file"
echo "Fixed $file"
fi
done
echo "โ
Markdown formatting completed!"
'''
[tasks.check-markdown-detailed]
description = "Check markdown with detailed line numbers"
run = '''
#!/usr/bin/env bash
set -euo pipefail
echo "๐ Detailed markdown check..."
for file in *.md; do
if [ -f "$file" ]; then
echo "=== Analyzing $file ==="
awk 'BEGIN { prev_line = ""; line_num = 0; issues = 0 }
{ line_num++ }
/^#{1,6} / {
if (line_num > 1 && prev_line !~ /^$/) {
print "MD022 - Line " line_num ": Missing blank line before heading: " $0; issues++
}
}
/^[-*+] / || /^[0-9]+\. / {
if (line_num > 1 && prev_line !~ /^$/ && prev_line !~ /^[-*+] / && prev_line !~ /^[0-9]+\. / && prev_line !~ /^ /) {
print "MD032 - Line " line_num ": Missing blank line before list: " $0; issues++
}
}
{ prev_line = $0 }
END {
if (issues == 0) print "โ
No issues found";
else print "โ Found " issues " issues"
}' "$file"
echo ""
fi
done
'''