prax-orm 0.11.0

A next-generation, type-safe ORM for Rust inspired by Prisma
Documentation
---
import Prism from '../lib/prism';

interface Props {
  code: string;
  lang?: string;
  filename?: string;
}

const { code, lang = '', filename = '' } = Astro.props;

function escapeHtml(text: string): string {
  return text
    .replace(/&/g, '&')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

function highlight(code: string, lang: string): string {
  if (lang && Prism.languages[lang]) {
    return Prism.highlight(code, Prism.languages[lang], lang);
  }

  // Try to auto-detect based on content
  if (code.includes('model ') && code.includes('@')) {
    return Prism.highlight(code, Prism.languages['prax'], 'prax');
  }
  if (code.includes('fn ') || code.includes('let ') || code.includes('impl ')) {
    return Prism.highlight(code, Prism.languages['rust'], 'rust');
  }

  return escapeHtml(code);
}

const highlightedCode = highlight(code, lang);
---

<div class="code-block group">
  <!-- Header bar -->
  <div class="code-header">
    {filename && <span class="filename">{filename}</span>}
    <div class="header-actions">
      {lang && <span class="language-badge">{lang}</span>}
      <button type="button" class="copy-button" title="Copy code" aria-label="Copy code">
        <svg class="icon icon-copy" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="2"
            d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
          ></path>
        </svg>
        <svg class="icon icon-check hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"
          ></path>
        </svg>
      </button>
    </div>
  </div>

  <!-- Code content -->
  <pre class="code-pre"><code class="code-content" set:html={highlightedCode} /></pre>
</div>

<script>
  // Copy-to-clipboard for all code blocks (event delegation, registered once).
  if (!(window as any).__praxCopyBound) {
    (window as any).__praxCopyBound = true;
    document.addEventListener('click', async (event) => {
      const button = (event.target as HTMLElement).closest<HTMLButtonElement>('.copy-button');
      if (!button) return;

      const block = button.closest('.code-block');
      const code = block?.querySelector('.code-content')?.textContent ?? '';

      try {
        await navigator.clipboard.writeText(code);
      } catch (err) {
        console.error('Failed to copy code:', err);
        return;
      }

      button.classList.add('copied');
      button.title = 'Copied!';
      button.querySelector('.icon-copy')?.classList.add('hidden');
      button.querySelector('.icon-check')?.classList.remove('hidden');

      setTimeout(() => {
        button.classList.remove('copied');
        button.title = 'Copy code';
        button.querySelector('.icon-copy')?.classList.remove('hidden');
        button.querySelector('.icon-check')?.classList.add('hidden');
      }, 2000);
    });
  }
</script>