### Initial Project Setup Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Follow these steps to set up the project locally. This includes cloning the repository, installing dependencies, and configuring optional test settings. ```bash git clone https://github.com/YOUR_USERNAME/repo2txt.git cd repo2txt git remote add upstream https://github.com/abinthomasonline/repo2txt.git npm install cp tests/test-config.example.ts tests/test-config.ts # Add your GitHub token to test-config.ts (optional, for E2E tests) npm run dev ``` -------------------------------- ### Clone and Run Repo2txt Locally Source: https://github.com/abinthomasonline/repo2txt/blob/master/README.md Follow these steps to clone the repository, install dependencies, and start the development server for local use. ```bash git clone https://github.com/abinthomasonline/repo2txt.git cd repo2txt npm install npm run dev # Open http://localhost:5173/repo2txt/ ``` -------------------------------- ### Environment Variables Example Source: https://github.com/abinthomasonline/repo2txt/blob/master/IMPLEMENTATION_PLAN.md Example `.env.example` file showing environment variables used for API endpoints and feature flags. ```bash # .env.example VITE_GITHUB_API_URL=https://api.github.com VITE_GITLAB_API_URL=https://gitlab.com/api/v4 VITE_AZURE_API_URL=https://dev.azure.com VITE_ENABLE_ANALYTICS=false VITE_ANALYTICS_ID= VITE_SENTRY_DSN= ``` -------------------------------- ### Quick Contribution Guide Source: https://github.com/abinthomasonline/repo2txt/blob/master/README.md Steps to fork, clone, branch, make changes, test, commit, and push for contributing to the project. ```bash # Fork and clone git clone https://github.com/YOUR_USERNAME/repo2txt.git # Create branch git checkout -b feature/amazing-feature # Make changes and test npm run test:unit npm run test:e2e # Commit and push git commit -m "Add amazing feature" git push origin feature/amazing-feature # Open pull request ``` -------------------------------- ### Tree Building Process Example Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Illustrates the three-step process of building a hierarchical tree structure from a flat list of FileNodes, including flattening for virtual scrolling. ```typescript // 1. Provider returns flat FileNode[] const fileNodes: FileNode[] = await provider.fetchTree(url); // [{ path: 'src', type: 'tree' }, { path: 'src/App.tsx', type: 'blob' }] // 2. Build hierarchical TreeNode[] const tree: TreeNode[] = buildTree(fileNodes, { selectedPaths: new Set(['src/App.tsx']), excludedPaths: new Set([]), expandedPaths: new Set(['src']), }); // [{ path: 'src', type: 'tree', expanded: true, children: [ // { path: 'src/App.tsx', type: 'blob', selected: true } // ]}] // 3. Flatten for virtual scrolling const flatTree = flattenTree(tree); // [{ node: { path: 'src', ... }, depth: 0 }, // { node: { path: 'src/App.tsx', ... }, depth: 1 }] ``` -------------------------------- ### TypeScript Import Order Example Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Shows the recommended order for imports in TypeScript files to improve readability and organization. ```typescript // 1. React/external libraries import { useState, useEffect } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; // 2. Internal imports (@/ aliases) import { BaseProvider } from '@/lib/providers/BaseProvider'; import { FileTree } from '@/components/file-tree/FileTree'; // 3. Types import type { FileNode, ProviderType } from '@/types'; // 4. Relative imports import { formatTree } from './utils'; // 5. Styles (if any) import './styles.css'; ``` -------------------------------- ### GitHubProvider Concrete Implementation Example Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Demonstrates a concrete implementation of the BaseProvider for GitHub. Shows how to implement abstract methods and utilize shared utilities like fetchMultiple for streaming file content. ```typescript // Concrete implementation class GitHubProvider extends BaseProvider { getType(): ProviderType { return 'github'; } async fetchTree(url: string): Promise { const parsed = this.parseUrl(url); // GitHub-specific tree fetching return this.normalizeTree(rawTree); } // Use base class utilities async loadMultipleFiles(nodes: FileNode[]) { for await (const content of this.fetchMultiple(nodes)) { // Process each file as it arrives (streaming) } } } ``` -------------------------------- ### Configure E2E Test Token Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Steps to set up the GitHub token for E2E tests. Involves copying an example configuration file and adding your token, either manually or via an environment variable. ```bash # Copy template cp tests/test-config.example.ts tests/test-config.ts # Add your token to test-config.ts export const testConfig = { githubToken: process.env.GITHUB_TOKEN || 'your_token_here', }; ``` -------------------------------- ### Unit Test Example for Formatter Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Tests the formatting of a directory tree and token counting functionality using Vitest and React Testing Library. Ensure the Formatter utility is imported. ```typescript describe('Formatter', () => { it('should format directory tree', () => { const tree = [ { path: 'src', type: 'tree' }, { path: 'src/index.ts', type: 'blob' }, ]; const formatted = Formatter.formatTree(tree); expect(formatted).toContain('β”œβ”€β”€ πŸ“ src'); expect(formatted).toContain('└── πŸ“„ index.ts'); }); it('should count tokens accurately', () => { const text = 'Hello world'; const count = Formatter.countTokens(text); expect(count).toBeGreaterThan(0); }); }); ``` -------------------------------- ### GitHub Actions Deployment Workflow Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Defines the CI/CD pipeline for deploying the project to GitHub Pages. It includes steps for dependency installation, quality checks, building, and deployment. ```yaml name: Deploy to GitHub Pages on: push: branches: [master, main] workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' # Quality checks - run: npm ci - run: npm run typecheck - run: npm run lint - run: npm run test:unit # Build - run: npm run build env: NODE_ENV: production # Deploy - uses: actions/upload-pages-artifact@v3 with: path: './dist' deploy: needs: build runs-on: ubuntu-latest steps: - uses: actions/deploy-pages@v4 ``` -------------------------------- ### Integration Test Example for GitHub Provider Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Tests the integration between the GitHub Provider and the FileTree component. Renders the FileTree component with fetched data and asserts the presence of expected elements. Requires 'render' and 'screen' from '@testing-library/react'. ```typescript describe('GitHub Provider Integration', () => { it('should load and display file tree', async () => { const provider = new GitHubProvider(); const tree = await provider.fetchTree('https://github.com/facebook/react'); render(); expect(screen.getByText('package.json')).toBeInTheDocument(); }); }); ``` -------------------------------- ### Conventional Commits Message Examples Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Examples of valid commit messages following the Conventional Commits specification. These demonstrate the correct usage of type, scope, and subject. ```bash git commit -m "feat(github): support branch names with slashes" ``` ```bash git commit -m "fix(ui): correct dark mode toggle sequence" ``` ```bash git commit -m "test(e2e): add error dialog tests" ``` ```bash git commit -m "docs: update architecture documentation" ``` -------------------------------- ### Zustand Selector for Computed Values Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Provides an example of a selector function within a Zustand store to derive computed values from the current state. ```typescript // Selector (computed value) getSelectedNodes: () => { const { nodes, selectedPaths } = get(); return nodes.filter(n => selectedPaths.has(n.path)); }; ``` -------------------------------- ### Build Repo2txt for Production Source: https://github.com/abinthomasonline/repo2txt/blob/master/README.md Use this command to build the project for production, with the output located in the ./dist folder. ```bash npm run build # Output in ./dist folder ``` -------------------------------- ### Production Build Output Structure Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Illustrates the typical file structure of the production build output in the dist/ folder. ```bash # Output structure: dist/ β”œβ”€β”€ index.html # Entry point β”œβ”€β”€ assets/ β”‚ β”œβ”€β”€ index-[hash].js # Main bundle (330KB) β”‚ β”œβ”€β”€ index-[hash].css # Styles (50KB) β”‚ β”œβ”€β”€ react-[hash].js # React vendor (140KB) β”‚ β”œβ”€β”€ zustand-[hash].js # Zustand (3KB) β”‚ β”œβ”€β”€ tokenizer-[hash].js # GPT tokenizer (1.7MB) β”‚ └── [provider]-[hash].js # Lazy loaded providers └── vite.svg # Favicon ``` -------------------------------- ### GitHub Actions Workflow for Beta Deployment Source: https://github.com/abinthomasonline/repo2txt/blob/master/IMPLEMENTATION_PLAN.md This workflow automates testing, building, and deploying the application to a beta environment upon pushes to the 'v2-development' branch. It includes steps for linting, unit, integration, and end-to-end tests, followed by a build and analysis phase. ```yaml # .github/workflows/deploy-beta.yml name: Deploy Beta on: push: branches: [v2-development] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npm run lint - run: npm run test:unit - run: npm run test:integration e2e: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npx playwright install - run: npm run test:e2e build: needs: [test, e2e] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npm run build - run: npm run analyze-bundle deploy: needs: build runs-on: ubuntu-latest steps: - name: Deploy to Beta # Deploy to beta subdomain ``` -------------------------------- ### Zustand Store Composition with Multiple Slices Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Demonstrates how to compose multiple Zustand slices (ProviderSlice, FileTreeSlice, FilterSlice, UiSlice) into a single store using `create`. It includes middleware for devtools and persistence, with specific fields being persisted. ```typescript // src/store/index.ts const useStore = create()( devtools( persist( (...args) => ({ ...createProviderSlice(...args), ...createFileTreeSlice(...args), ...createFilterSlice(...args), ...createUiSlice(...args), }), { name: 'repo2txt-store', partialize: (state) => ({ // Only persist these fields theme: state.theme, currentProvider: state.currentProvider, }), } ) ) ); ``` -------------------------------- ### Zustand DevTools Integration Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Enable Zustand's devtools integration for debugging state management. This requires the 'devtools' middleware to be applied to the store and the Redux DevTools browser extension to be installed. ```typescript // Zustand DevTools // Enable in store: devtools(...) // Use Redux DevTools browser extension ``` -------------------------------- ### Production Build Command Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Creates an optimized production build using Vite and Rollup, including minification and CSS optimization. The output is placed in the dist/ folder. ```bash # Production build npm run build β”œβ”€β†’ vite build (Rollup under the hood) β”œβ”€β†’ TypeScript compilation (if build:check) β”œβ”€β†’ Code splitting (manual chunks) β”œβ”€β†’ Minification (Terser) β”œβ”€β†’ CSS optimization (Tailwind purge) └─→ Output: dist/ folder ``` -------------------------------- ### Development Commands Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md A collection of npm scripts for managing the development lifecycle, including running the dev server, building for production, and previewing the build. ```bash # Development npm run dev # Start dev server (http://localhost:5173/repo2txt/) npm run build # Production build npm run preview # Preview production build # Testing npm run test:unit # Run unit tests npm run test:e2e # Run E2E tests npm run test:watch # Watch mode for unit tests npm run test:coverage # Generate coverage report # Code Quality npm run typecheck # TypeScript type checking npm run lint # Lint code npm run lint:fix # Auto-fix linting issues npm run format # Format code with Prettier npm run format:check # Check formatting # CI Pipeline (runs all checks) npm run ci # typecheck + lint + test:unit ``` -------------------------------- ### Zustand Persistence Configuration Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Demonstrates how to configure persistence for a Zustand store, specifying which parts of the state to save and the storage name. ```typescript // Only persist non-sensitive, user preferences persist( (set, get) => ({ /* store */ }), { name: 'repo2txt-store', partialize: (state) => ({ theme: state.theme, // Dark mode preference currentProvider: state.currentProvider, // Last used provider // NOT persisted: tokens, file contents, selection }), } ) ``` -------------------------------- ### Development Commands Source: https://github.com/abinthomasonline/repo2txt/blob/master/IMPLEMENTATION_PLAN.md Common npm scripts for development, testing, building, and code quality checks. ```bash # Development npm run dev # Start dev server npm run dev:debug # Start with source maps # Testing npm run test # Run all tests npm run test:unit # Unit tests only npm run test:integration # Integration tests npm run test:e2e # E2E tests npm run test:watch # Watch mode npm run test:coverage # Coverage report # Building npm run build # Production build npm run build:analyze # Bundle analysis npm run preview # Preview production build # Code Quality npm run lint # ESLint npm run lint:fix # Auto-fix issues npm run format # Prettier npm run typecheck # TypeScript check # CI/CD npm run ci # Full CI pipeline locally npm run deploy:beta # Deploy to beta npm run deploy:prod # Deploy to production ``` -------------------------------- ### Run Unit Tests Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Commands to execute unit tests using npm scripts. Supports single runs, watch mode, coverage reports, and targeting specific files. ```bash # Unit tests npm run test:unit # Run once npm run test:watch # Watch mode npm run test:coverage # With coverage ``` ```bash # Test specific file npm run test:unit -- Formatter.test.ts ``` -------------------------------- ### Bundle Analysis Command Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Run this command to generate a bundle analysis visualization. This helps in identifying large chunks and optimizing the application's bundle size. ```bash npm run build:analyze ``` -------------------------------- ### Download File Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Creates a Blob and a temporary URL to enable file downloads. ```javascript Blob + createObjectURL ``` -------------------------------- ### Add and Commit Changes Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Stage all changes and commit them using a message that follows the Conventional Commits format. This ensures a clear and consistent commit history. ```bash git add . git commit -m "feat(scope): your feature description" ``` -------------------------------- ### Pick Directory and Traverse File System Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Uses the File System Access API to allow users to pick a directory and then recursively traverses its contents to build a file tree. This is useful for applications that need to access local files and folders. ```typescript async fetchTree(url: string): Promise { const dirHandle = await window.showDirectoryPicker({ mode: 'read', }); const nodes: FileNode[] = []; async function traverse(handle: FileSystemHandle, path = '') { if (handle.kind === 'file') { nodes.push({ path: path + handle.name, type: 'blob', name: handle.name, url: path + handle.name, // Used as lookup key }); } else { const dirPath = path + handle.name + '/'; nodes.push({ path: dirPath, type: 'tree', name: handle.name }); for await (const entry of handle.values()) { await traverse(entry, dirPath); } } } await traverse(dirHandle); return nodes; } ``` -------------------------------- ### Recursive API Fetching with Batching Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Demonstrates fetching large directory trees using recursive API calls with batching. For GitHub, use the `?recursive=1` parameter. For local file systems, stream entries using the Web Streams API. ```javascript GitHub: Use `?recursive=1` parameter Local: Stream entries with Web Streams API ``` -------------------------------- ### Run Quality Checks Locally Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Execute these commands to ensure code quality, including type checking, linting, and running end-to-end tests locally before committing. ```bash npm run ci # Type check + lint + unit tests ``` ```bash npm run test:e2e # E2E tests ``` -------------------------------- ### Run E2E Tests Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Commands to execute end-to-end tests using npm scripts. Allows running for all browsers, a specific browser project, or in interactive UI mode. Also supports targeting specific test files. ```bash # E2E tests npm run test:e2e # All browsers npm run test:e2e -- --project=chromium # Single browser npm run test:e2e:ui # Interactive UI ``` ```bash npm run test:e2e -- github-flow.spec.ts ``` -------------------------------- ### Development Build Command Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Runs the Vite development server with HMR and TypeScript type checking enabled. ```bash # Development build (with source maps) npm run dev β”œβ”€β†’ Vite dev server (http://localhost:5173/repo2txt/) β”œβ”€β†’ Hot Module Replacement (HMR) β”œβ”€β†’ Fast refresh for React └─→ TypeScript type checking in background ``` -------------------------------- ### Repo2txt Data Flow Diagram Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Illustrates the sequence of operations and data transformations within the Repo2txt application, from user input to output display. ```text User Input β†’ URL Parsing β†’ Provider Selection β†’ Tree Fetch ↓ File Tree (Virtual Scrolling) β†’ User Selection β†’ Filters ↓ Content Fetch β†’ Formatting β†’ Tokenization (Web Worker) ↓ Output Display β†’ Copy/Download ``` -------------------------------- ### E2E Wait Strategies Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Illustrates various strategies for waiting in E2E tests, including waiting for network idle, specific elements to be visible, and dynamic import delays. ```typescript // Wait for network idle (GitHub API complete) await page.waitForLoadState('networkidle'); // Wait for specific element (tree loaded) await expect(page.getByTestId('file-tree-heading')).toBeVisible({ timeout: 30000 }); // Wait for code split bundle (provider loaded) await page.waitForTimeout(1500); // Dynamic import delay ``` -------------------------------- ### Linting and Formatting Commands Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Provides the npm commands to check and fix code style issues using ESLint and Prettier. ```bash npm run lint # Check for issues npm run lint:fix # Auto-fix npm run format # Format with Prettier npm run format:check # Check formatting ``` -------------------------------- ### Compound Component Pattern: FileTree and FileTreeNode Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Demonstrates the compound component pattern where FileTree manages virtualization and FileTreeNode is a pure, memoized component for rendering individual nodes. ```typescript export function FileTree({ nodes }: FileTreeProps) { const flatNodes = useMemo(() => flattenTree(nodes), [nodes]); const virtualizer = useVirtualizer({ /* config */ }); return (
{virtualizer.getVirtualItems().map(virtualRow => ( ))}
); } export const FileTreeNode = React.memo(({ node, depth }: Props) => { const indent = depth * 16; return (
{/* Render node */}
); }); ``` -------------------------------- ### GitHubProvider API Call Sequence Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Illustrates the sequence of API calls made by the GitHubProvider for fetching repository data. ```text 1. fetchTree(url) β”œβ”€β†’ parseUrl(url) β”œβ”€β†’ fetchReferences() β†’ GET /repos/:owner/:repo/git/matching-refs/heads/ β”œβ”€β†’ resolveRefAndPath() β†’ Determine branch vs path β”œβ”€β†’ fetchTreeSha() β†’ GET /repos/:owner/:repo/contents/:path?ref=:ref └─→ fetchTreeRecursive() β†’ GET /repos/:owner/:repo/git/trees/:sha?recursive=1 2. fetchFile(node) └─→ GET /repos/:owner/:repo/git/blobs/:sha 3. fetchMultiple(nodes) └─→ for await (node of nodes) { yield fetchFile(node); } ``` -------------------------------- ### repo2txt Project Structure Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md This snippet outlines the directory and file structure of the repo2txt project. It details the organization of source code, tests, build outputs, and configuration files. ```tree repo2txt/ β”œβ”€β”€ .github/ β”‚ └── workflows/ β”‚ └── deploy.yml # GitHub Actions CI/CD β”‚ β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ features/ # Feature modules (domain-driven) β”‚ β”‚ β”œβ”€β”€ github/ β”‚ β”‚ β”‚ β”œβ”€β”€ GitHubProvider.ts # GitHub API implementation β”‚ β”‚ β”‚ β”œβ”€β”€ components/ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ GitHubAuth.tsx # Token management β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ GitHubForm.tsx # URL input form β”‚ β”‚ β”‚ β”‚ └── GitHubUrlInput.tsx β”‚ β”‚ β”‚ └── __tests__/ # Feature tests β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ local/ β”‚ β”‚ β”‚ β”œβ”€β”€ LocalProvider.ts # File System API β”‚ β”‚ β”‚ └── components/ β”‚ β”‚ β”‚ β”œβ”€β”€ DirectoryPicker.tsx β”‚ β”‚ β”‚ β”œβ”€β”€ ZipUploader.tsx β”‚ β”‚ β”‚ └── LocalForm.tsx β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ gitlab/ # GitLab provider (beta) β”‚ β”‚ └── azure/ # Azure DevOps (beta) β”‚ β”‚ β”‚ β”œβ”€β”€ components/ # Shared UI components β”‚ β”‚ β”œβ”€β”€ ui/ # Base components (buttons, dialogs) β”‚ β”‚ β”‚ β”œβ”€β”€ Button.tsx β”‚ β”‚ β”‚ β”œβ”€β”€ ErrorDialog.tsx β”‚ β”‚ β”‚ └── ThemeToggle.tsx β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ file-tree/ # File tree components β”‚ β”‚ β”‚ β”œβ”€β”€ FileTree.tsx # Virtual scrolling tree β”‚ β”‚ β”‚ └── FileTreeNode.tsx # Individual node β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ filters/ # Filtering components β”‚ β”‚ β”‚ β”œβ”€β”€ AdvancedFilters.tsx β”‚ β”‚ β”‚ β”œβ”€β”€ ExtensionFilter.tsx β”‚ β”‚ β”‚ └── GitignoreEditor.tsx β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ OutputPanel.tsx # Output display & actions β”‚ β”‚ β”œβ”€β”€ FileStats.tsx # Token/line statistics β”‚ β”‚ └── ProviderSelector.tsx # Provider tabs β”‚ β”‚ β”‚ β”œβ”€β”€ lib/ # Core business logic β”‚ β”‚ β”œβ”€β”€ providers/ β”‚ β”‚ β”‚ β”œβ”€β”€ BaseProvider.ts # Abstract base class β”‚ β”‚ β”‚ └── types.ts # Shared provider types β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ formatter/ β”‚ β”‚ β”‚ β”œβ”€β”€ Formatter.ts # Output formatting β”‚ β”‚ β”‚ β”œβ”€β”€ TokenizerWorker.ts # Web Worker wrapper β”‚ β”‚ β”‚ └── __tests__/ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ gitignore/ β”‚ β”‚ β”‚ └── GitignoreParser.ts # .gitignore parsing β”‚ β”‚ β”‚ β”‚ β”‚ └── utils.ts # Shared utilities β”‚ β”‚ β”‚ β”œβ”€β”€ store/ # Zustand state management β”‚ β”‚ β”œβ”€β”€ index.ts # Store composition β”‚ β”‚ └── slices/ β”‚ β”‚ β”œβ”€β”€ providerSlice.ts # Provider state β”‚ β”‚ β”œβ”€β”€ fileTreeSlice.ts # File tree state β”‚ β”‚ β”œβ”€β”€ filterSlice.ts # Filter state β”‚ β”‚ └── uiSlice.ts # UI state (theme, loading) β”‚ β”‚ β”‚ β”œβ”€β”€ hooks/ β”‚ β”‚ β”œβ”€β”€ useFileTree.ts β”‚ β”‚ β”œβ”€β”€ useProvider.ts β”‚ β”‚ └── useTheme.ts β”‚ β”‚ β”‚ β”œβ”€β”€ workers/ β”‚ β”‚ └── tokenizer.worker.ts # GPT tokenizer β”‚ β”‚ β”‚ β”œβ”€β”€ types/ β”‚ β”‚ └── index.ts β”‚ β”‚ β”‚ β”œβ”€β”€ App.tsx # Root component β”‚ β”œβ”€β”€ main.tsx # Entry point β”‚ └── index.css # Global styles β”‚ β”œβ”€β”€ tests/ β”‚ β”œβ”€β”€ e2e/ # End-to-end tests (Playwright) β”‚ β”‚ β”œβ”€β”€ dark-mode.spec.ts β”‚ β”‚ β”œβ”€β”€ error-scenarios.spec.ts β”‚ β”‚ β”œβ”€β”€ github-flow.spec.ts β”‚ β”‚ └── local-flow.spec.ts β”‚ β”‚ β”‚ β”œβ”€β”€ test-config.ts # Test configuration (git-ignored) β”‚ └── test-config.example.ts # Template β”‚ β”œβ”€β”€ public/ # Static assets β”œβ”€β”€ dist/ # Build output (git-ignored) β”‚ β”œβ”€β”€ .eslintrc.cjs # ESLint configuration β”œβ”€β”€ .prettierrc # Prettier configuration β”œβ”€β”€ tsconfig.json # TypeScript configuration β”œβ”€β”€ vite.config.ts # Vite configuration β”œβ”€β”€ playwright.config.ts # Playwright configuration β”œβ”€β”€ vitest.config.ts # Vitest configuration └── package.json # Dependencies & scripts ``` -------------------------------- ### Repo2txt System Architecture Diagram Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Visual representation of the Repo2txt system components and their interactions, including the UI, Store, Workers, Provider Interface, and various data source providers. ```text β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ React App β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ UI β”‚ β”‚ Store β”‚ β”‚ Workers β”‚ β”‚ β”‚ β”‚ Components │◄── (Zustand) │◄── (Tokenizer) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–² β–² β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Provider Interface β”‚ β”‚ β”‚ β”‚ (BaseProvider - Abstract Base Class) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–² β–² β–² β–² β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”¬β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”΄β”€β”€β”€β”€β” β”‚ β”‚ β”‚ GitHub β”‚ Local β”‚ GitLab β”‚ Azure β”‚ β”‚ β”‚ β”‚Providerβ”‚ Providerβ”‚ Provider β”‚Provider β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -------------------------------- ### Enable Vite Debug Mode Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Run the development server with verbose logging enabled by setting the DEBUG environment variable. This helps in diagnosing issues related to Vite's internal processes. ```bash # Enable verbose logging DEBUG=vite:* npm run dev ``` -------------------------------- ### Progressive Loading with Async Generator Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Implements progressive loading using an async generator pattern to fetch multiple files. The generator yields file content as it becomes available, allowing the consumer to update the UI incrementally, improving perceived performance. ```typescript // Fetch multiple files progressively async *fetchMultiple(nodes: FileNode[]): AsyncGenerator { const CONCURRENT = 5; // Fetch 5 files at a time for (let i = 0; i < nodes.length; i += CONCURRENT) { const batch = nodes.slice(i, i + CONCURRENT); const promises = batch.map(node => this.fetchFile(node)); const results = await Promise.allSettled(promises); for (const result of results) { if (result.status === 'fulfilled') { yield result.value; // Yield immediately as each file completes } } } } // Consumer updates UI incrementally const files: FileContent[] = []; for await (const content of provider.fetchMultiple(selectedNodes)) { files.push(content); updateProgress(files.length, selectedNodes.length); // UI updates every file, feels faster } ``` -------------------------------- ### Mocking Fetch for GitHubProvider Unit Tests Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Uses `vi.spyOn` to mock the global `fetch` function, allowing the `GitHubProvider` to be tested in isolation by providing mock responses for API calls. ```typescript describe('GitHubProvider', () => { beforeEach(() => { vi.spyOn(global, 'fetch').mockImplementation((url) => { if (url.includes('/git/trees/')) { return Promise.resolve({ ok: true, json: () => Promise.resolve({ tree: mockTreeData }), }); } }); }); it('should parse URLs with branch slashes', () => { const provider = new GitHubProvider(); const result = provider.parseUrl( 'https://github.com/owner/repo/tree/feature/test/branch' ); expect(result.branch).toBe('feature/test/branch'); }); }); ``` -------------------------------- ### repo2txt System Architecture Diagram Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Visual representation of the repo2txt system architecture, detailing the Browser, Business Logic, and Data layers and their components. ```text β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Browser Layer β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ React Application β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ App β”‚ β”‚ Store β”‚ β”‚ Router β”‚ β”‚ Workers β”‚ β”‚ β”‚ β”‚ β”‚ β”‚Component │◄── (Zustand)│◄── (SPA) │◄── (Async) β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–² β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Component API β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Business Logic Layer β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ Provider Interface (Abstract) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ validateUrl() β€’ parseUrl() β€’ fetchTree() β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ fetchFile() β€’ fetchMultiple() β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β–² β–² β–² β–² β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”΄β”€β”€β” β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”΄β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”΄β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚GitHub β”‚ β”‚ Local β”‚ β”‚ GitLab β”‚ β”‚ Azure β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Impl β”‚ β”‚ Impl β”‚ β”‚ Impl β”‚ β”‚ Impl β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–² β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Data Layer β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ GitHub β”‚ β”‚ File β”‚ β”‚ JSZip β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ API β”‚ β”‚ System β”‚ β”‚ Parser β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ REST β”‚ β”‚ API β”‚ β”‚ (Binary) β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -------------------------------- ### Lazy Loading Components with Suspense Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Illustrates how to implement lazy loading for components using React.lazy and Suspense, with a fallback UI while components are loading. ```typescript const GitHubForm = lazy(() => import('@/features/github/components/GitHubForm')); const LocalForm = lazy(() => import('@/features/local/components/LocalForm')); function ProviderSelector() { return ( }> {currentProvider === 'github' && } {currentProvider === 'local' && } ); } ``` -------------------------------- ### Vite Configuration for Subdirectory Deployment Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Configures Vite for deployment in a subdirectory, enabling code splitting for specific libraries, and setting the build target. ```typescript export default defineConfig({ base: '/repo2txt/', // Subdirectory deployment plugins: [react()], resolve: { alias: { '@': './src' } }, build: { target: 'es2022', sourcemap: true, rollupOptions: { output: { manualChunks: { // Code splitting react: ['react', 'react-dom'], zustand: ['zustand'], jszip: ['jszip'], tokenizer: ['gpt-tokenizer'], }, }, }, }, }); ``` -------------------------------- ### Lazy Loading Provider Implementations Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Demonstrates code splitting for provider modules using dynamic imports. This reduces the initial bundle size by loading provider code only when needed. ```typescript // Provider registry with lazy loading const PROVIDERS = { github: () => import('@/features/github/GitHubProvider'), local: () => import('@/features/local/LocalProvider'), gitlab: () => import('@/features/gitlab/GitLabProvider'), azure: () => import('@/features/azure/AzureDevOpsProvider'), }; // Dynamic provider loading in ProviderSelector const loadProvider = async (type: ProviderType) => { const ProviderModule = await PROVIDERS[type](); const ProviderClass = ProviderModule.default; return new ProviderClass(); }; ``` -------------------------------- ### GitHub Provider Implementation Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md A concrete implementation of the BaseProvider for interacting with GitHub repositories. This class handles GitHub-specific API calls and data normalization. ```typescript // Concrete implementation class GitHubProvider extends BaseProvider { async fetchTree(url: string): Promise { // GitHub-specific implementation const parsed = this.parseUrl(url); const tree = await this.fetchGitHubTree(parsed); return this.normalizeTree(tree); } } ``` -------------------------------- ### Abstract Base Provider Interface Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Defines a common interface for all data source providers, ensuring a unified way to interact with different repositories. Use this as a blueprint for creating new provider implementations. ```typescript abstract class BaseProvider { abstract getType(): ProviderType; abstract validateUrl(url: string): boolean; abstract parseUrl(url: string): ParsedRepoInfo; abstract fetchTree(url: string, options?: FetchOptions): Promise; abstract fetchFile(node: FileNode): Promise; // Shared utilities async *fetchMultiple(nodes: FileNode[]): AsyncGenerator { // Progressive loading implementation } } ``` -------------------------------- ### Zustand Async State Update with Loading and Error Handling Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Shows how to handle asynchronous operations within a Zustand store, including setting loading states and managing errors. ```typescript // Async state update with loading setProvider: async (type) => { set({ isLoading: true, error: null }); try { const provider = await loadProvider(type); set({ currentProvider: type, provider, isLoading: false }); } catch (error) { set({ error: handleError(error), isLoading: false }); } }; ``` -------------------------------- ### Create Feature Branch Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Use this command to create a new branch for your feature development. Ensure the branch name follows the feature/* pattern. ```bash git checkout -b feature/your-feature ``` -------------------------------- ### AsyncGenerator for File Content Fetching Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Fetches file content asynchronously using an AsyncGenerator with concurrency control. It fetches files in parallel (e.g., 5 at a time) and yields them as they complete, providing progress updates for each file. ```javascript Fetch 5 files in parallel, yield as they complete Progress updates every file ``` -------------------------------- ### Good TypeScript Code Style Source: https://github.com/abinthomasonline/repo2txt/blob/master/CONTRIBUTING.md Demonstrates preferred TypeScript practices including interfaces, explicit return types, and functional programming patterns. ```typescript // βœ… Good interface FileNode { path: string; type: 'blob' | 'tree'; children?: FileNode[]; } function filterNodes(nodes: FileNode[], predicate: (node: FileNode) => boolean): FileNode[] { return nodes.filter(predicate).map(node => ({ ...node, children: node.children ? filterNodes(node.children, predicate) : undefined, })); } ``` -------------------------------- ### GitHubProvider Integration Test Source: https://github.com/abinthomasonline/repo2txt/blob/master/IMPLEMENTATION_PLAN.md An integration test for the GitHubProvider, verifying its ability to fetch and build a file tree from a GitHub repository. This test utilizes mocking for external API calls. ```typescript // tests/integration/github-provider.test.ts describe('GitHubProvider Integration', () => { it('fetches and builds file tree', async () => { const provider = new GitHubProvider(); const tree = await provider.fetchTree( 'https://github.com/owner/repo' ); expect(tree).toBeInstanceOf(Array); expect(tree[0]).toHaveProperty('path'); }); }); ``` -------------------------------- ### FileTree Unit Tests Source: https://github.com/abinthomasonline/repo2txt/blob/master/IMPLEMENTATION_PLAN.md Unit tests for the FileTree class, demonstrating filtering by extension and applying gitignore patterns. These tests are written using Vitest and React Testing Library. ```typescript // lib/file-tree/__tests__/FileTree.test.ts describe('FileTree', () => { describe('filter', () => { it('filters by extension', () => { const tree = new FileTree(mockNodes); tree.filter({ extensions: ['.ts', '.tsx'] }); expect(tree.getVisibleNodes()).toHaveLength(5); }); it('applies gitignore patterns', () => { const tree = new FileTree(mockNodes); tree.applyGitignore(['node_modules/**', '*.log']); expect(tree.hasNode('node_modules/package.json')).toBe(false); }); }); }); ``` -------------------------------- ### BaseProvider Abstract Class Definition Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Defines the contract for data source providers, including methods for identity, URL parsing, data fetching, and credential management. It also includes shared utilities like fetchWithRetry and handleFetchError. ```typescript abstract class BaseProvider { // Identity & Validation abstract getType(): ProviderType; abstract getName(): string; abstract requiresAuth(): boolean; abstract validateUrl(url: string): boolean; // URL Parsing abstract parseUrl(url: string): ParsedRepoInfo; // Data Fetching abstract fetchTree(url: string, options?: FetchOptions): Promise; abstract fetchFile(node: FileNode): Promise; // Shared Utilities (Implemented in Base) async *fetchMultiple( nodes: FileNode[] ): AsyncGenerator; protected async fetchWithRetry( url: string, options?: RequestInit, maxRetries = 3 ): Promise; protected handleFetchError(error: unknown, context?: string): ProviderError; // Credential Management setCredentials(credentials: ProviderCredentials): void; clearCredentials(): void; } ``` -------------------------------- ### Copy to Clipboard Source: https://github.com/abinthomasonline/repo2txt/blob/master/AGENT.md Uses the navigator.clipboard API to copy text to the user's clipboard. ```javascript navigator.clipboard.writeText ```