Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(website): Improve performance of large repository output using Ace Editor #313

Merged
merged 5 commits into from
Jan 25, 2025

Conversation

yamadashy
Copy link
Owner

related: #312

Checklist

  • Run npm run test
  • Run npm run lint

Copy link

cloudflare-workers-and-pages bot commented Jan 25, 2025

Deploying repomix with  Cloudflare Pages  Cloudflare Pages

Latest commit: 10b1f39
Status: ✅  Deploy successful!
Preview URL: https://447033bb.repomix.pages.dev
Branch Preview URL: https://feat-website-ace.repomix.pages.dev

View logs

Copy link

codecov bot commented Jan 25, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.12%. Comparing base (ad93f85) to head (10b1f39).
Report is 6 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #313   +/-   ##
=======================================
  Coverage   90.12%   90.12%           
=======================================
  Files          48       48           
  Lines        2471     2471           
  Branches      514      514           
=======================================
  Hits         2227     2227           
  Misses        244      244           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

coderabbitai bot commented Jan 25, 2025

📝 Walkthrough

Walkthrough

This pull request introduces a comprehensive refactoring of the repository packing and result viewing functionality in the client-side application. The changes focus on modularizing the TryIt.vue component by breaking it down into smaller, more focused components: TryItUrlInput, TryItPackOptions, and TryItResultViewer.

The request handling logic has been centralized in the handlePackRequest function, which now manages repository packing with improved error handling and analytics tracking. URL validation has been simplified and moved to a separate utility function isValidRemoteValue. The analytics tracking has been streamlined, removing specific method tracking for format and pattern changes while adding a new action for output parsability.

Additional utility functions have been introduced in resultViewer.ts to support clipboard copying, result downloading, and timestamp formatting. The package dependencies have been updated, including the addition of a Vue Ace Editor component and an update to the repomix dependency.

Sequence Diagram

sequenceDiagram
    participant User
    participant TryItUrlInput
    participant TryItPackOptions
    participant RequestHandlers
    participant PackService
    participant TryItResultViewer

    User->>TryItUrlInput: Enter Repository URL
    TryItUrlInput->>RequestHandlers: Validate URL
    RequestHandlers-->>TryItUrlInput: Validation Result
    User->>TryItPackOptions: Configure Packing Options
    TryItPackOptions->>RequestHandlers: Track Option Changes
    User->>TryItUrlInput: Submit URL
    TryItUrlInput->>RequestHandlers: Handle Pack Request
    RequestHandlers->>PackService: Pack Repository
    PackService-->>RequestHandlers: Return Pack Result
    RequestHandlers->>TryItResultViewer: Display Result
    TryItResultViewer->>User: Show Packed Repository Content
Loading

Possibly related PRs


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (14)
website/client/components/utils/resultViewer.ts (4)

6-8: Add input validation and consistent date formatting.

The current implementation might throw for invalid dates and produce inconsistent formats across different locales.

Consider this implementation:

 export function formatTimestamp(timestamp: string): string {
+  if (!timestamp || isNaN(Date.parse(timestamp))) {
+    return '';
+  }
-  return new Date(timestamp).toLocaleString();
+  return new Date(timestamp).toLocaleString('en-US', {
+    year: 'numeric',
+    month: 'short',
+    day: 'numeric',
+    hour: '2-digit',
+    minute: '2-digit'
+  });
 }

13-22: Add type annotation for error handling.

The implementation looks good with proper error handling and analytics integration.

Consider adding error type annotation:

-  } catch (err) {
+  } catch (err: unknown) {

27-41: Improve MIME type handling and extension mapping.

While the implementation works, it could be more maintainable and accurate with proper MIME types.

Consider this enhancement:

+const FORMAT_CONFIG = {
+  markdown: { ext: 'md', mime: 'text/markdown' },
+  xml: { ext: 'xml', mime: 'application/xml' },
+  text: { ext: 'txt', mime: 'text/plain' }
+} as const;
+
 export function downloadResult(content: string, format: string): void {
-  const blob = new Blob([content], { type: 'text/plain' });
+  const config = FORMAT_CONFIG[format as keyof typeof FORMAT_CONFIG] || FORMAT_CONFIG.text;
+  const blob = new Blob([content], { type: config.mime });
   const url = window.URL.createObjectURL(blob);
   const a = document.createElement('a');
-  const extension = format === 'markdown' ? 'md' : format === 'xml' ? 'xml' : 'txt';
 
   a.href = url;
-  a.download = `repomix-output.${extension}`;
+  a.download = `repomix-output.${config.ext}`;

46-54: Add return type annotation for better type safety.

The editor options look good for handling large repository output.

Consider adding type annotation:

-export function getEditorOptions() {
+export function getEditorOptions(): {
+  readOnly: boolean;
+  wrap: boolean;
+  showPrintMargin: boolean;
+  fontSize: string;
+  useWorker: boolean;
+} {
website/client/components/ResultViewer.vue (3)

22-32: Add type safety to event handling.

The copy functionality looks good but could benefit from stronger typing.

Consider this enhancement:

-async function handleCopy(event: Event) {
+async function handleCopy(event: MouseEvent) {

35-40: Add type safety to download event handling.

Similar to the copy handler, the download functionality could benefit from stronger typing.

Consider this enhancement:

-function handleDownload(event: Event) {
+function handleDownload(event: MouseEvent) {

111-118: Enhance accessibility for the editor component.

The Ace Editor integration looks good, but could benefit from accessibility improvements.

Consider adding ARIA attributes:

 <div class="editor-container">
   <VAceEditor
       v-model:value="result.content"
       :lang="'text'"
       :style="{ height: '100%', width: '100%' }"
       :options="editorOptions"
+      aria-label="Repository content viewer"
+      role="textbox"
+      aria-readonly="true"
   />
 </div>
website/client/components/utils/validation.ts (2)

3-3: Consider creating an issue to track the TODO.

The TODO comment indicates a need to share validation logic with the core module. This could prevent logic duplication and ensure consistency.

Would you like me to create an issue to track sharing the validation logic with src/cli/actions/remoteAction.ts?


7-11: Consider adding test cases for edge cases in the shorthand format.

The regex pattern correctly validates the GitHub repository shorthand format. However, consider adding validation for:

  • Maximum length of username and repository names
  • Reserved GitHub usernames
  • Special characters that GitHub doesn't allow
website/client/components/utils/requestHandlers.ts (2)

5-9: Consider adding validation for handler options.

The RequestHandlerOptions interface could benefit from runtime validation to ensure callback functions are properly typed.

+function isValidHandlerOptions(options: unknown): options is RequestHandlerOptions {
+  if (typeof options !== 'object' || options === null) return false;
+  const { onSuccess, onError, signal } = options as RequestHandlerOptions;
+  return (
+    (onSuccess === undefined || typeof onSuccess === 'function') &&
+    (onError === undefined || typeof onError === 'function') &&
+    (signal === undefined || signal instanceof AbortSignal)
+  );
+}

63-68: Consider adding type validation for analytics action.

The handleOptionChange function should validate that the provided analyticsAction is a valid enum value.

 export function handleOptionChange(value: boolean | string, analyticsAction: AnalyticsActionType): void {
+  if (!Object.values(AnalyticsAction).includes(analyticsAction)) {
+    console.warn(`Invalid analytics action: ${analyticsAction}`);
+    return;
+  }
   if (typeof value === 'boolean') {
website/client/components/TryIt.vue (3)

Line range hint 134-143: Add debouncing to URL input handler.

The URL input handler could benefit from debouncing to prevent excessive validation checks during rapid typing.

+import { debounce } from 'lodash-es';
+
+const debouncedValidation = debounce((value: string) => {
+  url.value = value;
+}, 300);
+
 function handleUrlInput(event: Event) {
   const input = event.target as HTMLInputElement;
-  url.value = input.value;
+  debouncedValidation(input.value);
 }

Line range hint 144-149: Add keyboard accessibility for form submission.

The keyboard event handler should also handle the Space key for better accessibility.

 function handleKeydown(event: KeyboardEvent) {
-  if (event.key === 'Enter' && isValidUrl.value && !loading.value) {
+  if ((event.key === 'Enter' || event.key === ' ') && isValidUrl.value && !loading.value) {
+    event.preventDefault();
     handleSubmit();
   }
 }

Line range hint 156-167: Enhance accessibility for URL input field.

The URL input field could benefit from additional ARIA attributes and validation feedback.

 <input
     :value="url"
     @input="handleUrlInput"
     @keydown="handleKeydown"
     type="text"
     placeholder="GitHub repository URL or user/repo (e.g., yamadashy/repomix)"
     class="repository-input"
     :class="{ 'invalid': url && !isValidUrl }"
     aria-label="GitHub repository URL"
+    aria-invalid="url && !isValidUrl"
+    aria-describedby="url-error"
+    autocomplete="off"
 />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad93f85 and 90a0f55.

⛔ Files ignored due to path filters (2)
  • website/client/package-lock.json is excluded by !**/package-lock.json
  • website/server/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • website/client/components/ResultViewer.vue (4 hunks)
  • website/client/components/TryIt.vue (3 hunks)
  • website/client/components/api/client.ts (0 hunks)
  • website/client/components/utils/analytics.ts (0 hunks)
  • website/client/components/utils/requestHandlers.ts (1 hunks)
  • website/client/components/utils/resultViewer.ts (1 hunks)
  • website/client/components/utils/validation.ts (1 hunks)
  • website/client/package.json (1 hunks)
  • website/server/package.json (1 hunks)
💤 Files with no reviewable changes (2)
  • website/client/components/api/client.ts
  • website/client/components/utils/analytics.ts
✅ Files skipped from review due to trivial changes (1)
  • website/server/package.json
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Test (windows-latest, 23.x)
  • GitHub Check: Test (windows-latest, 22.x)
  • GitHub Check: Test (windows-latest, 21.x)
  • GitHub Check: Test (windows-latest, 20.x)
  • GitHub Check: Test (windows-latest, 19.x)
  • GitHub Check: Test (windows-latest, 18.x)
  • GitHub Check: Test (windows-latest, 18.0.0)
  • GitHub Check: Build and run (windows-latest, 22.x)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
website/client/components/ResultViewer.vue (1)

268-272: LGTM! Good responsive styling.

The editor container styling is well-implemented with proper use of CSS variables and responsive design considerations.

website/client/package.json (2)

14-15: LGTM! Dependencies are properly ordered.

The dependencies are correctly ordered alphabetically, and the versions are specified using the caret notation for flexible minor version updates.


15-15: Verify vue3-ace-editor version and dependencies.

The addition of vue3-ace-editor aligns with the PR objective of improving large repository output performance.

Let's verify the package version and check for any security advisories:

✅ Verification successful

✅ vue3-ace-editor dependency is verified and secure

The package version (2.2.4) is the latest available, and both vue3-ace-editor and its peer dependency ace-builds show no security vulnerabilities. The package is actively maintained with recent updates.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check vue3-ace-editor package information and dependencies

# Check latest version and release date
echo "Checking vue3-ace-editor package info..."
npm view vue3-ace-editor time.modified versions dist-tags

# Check for any security advisories
echo "Checking for security advisories..."
npm audit vue3-ace-editor

# Check peer dependencies
echo "Checking peer dependencies..."
npm view vue3-ace-editor peerDependencies

Length of output: 963


Script:

#!/bin/bash
# Check ace-builds security advisories and version
echo "Checking ace-builds package info..."
npm view ace-builds time.modified versions dist-tags

echo "Checking for ace-builds in package.json..."
cat website/client/package.json | grep -A 2 -B 2 "ace-builds"

echo "Checking for security advisories for ace-builds..."
npm audit ace-builds

Length of output: 1811

website/client/components/utils/validation.ts Show resolved Hide resolved
website/client/components/TryIt.vue Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
website/client/components/ResultViewer.vue (3)

15-15: Consider memoizing editor options.

Since editorOptions is static configuration, consider using computed() or moving it outside the component setup to prevent unnecessary recalculation.

-const editorOptions = getEditorOptions();
+const editorOptions = computed(() => getEditorOptions());

111-118: Consider dynamic language mode for syntax highlighting.

The editor's language mode is hardcoded to 'text', which might not provide optimal syntax highlighting for different content formats (e.g., JSON, YAML, etc.).

-          <VAceEditor
-              v-model:value="result.content"
-              :lang="'text'"
-              :style="{ height: '100%', width: '100%' }"
-              :options="editorOptions"
-          />
+          <VAceEditor
+              v-model:value="result.content"
+              :lang="result.format.toLowerCase()"
+              :style="{ height: '100%', width: '100%' }"
+              :options="editorOptions"
+          />

Line range hint 1-286: Consider lazy-loading the Ace Editor for performance.

The component shows good architecture and implementation. For further optimization, consider lazy-loading the Ace Editor to reduce the initial bundle size, especially since it's only needed when results are available.

-import { VAceEditor } from 'vue3-ace-editor';
+const VAceEditor = defineAsyncComponent(() =>
+  import('vue3-ace-editor').then(mod => mod.VAceEditor)
+);

Don't forget to import defineAsyncComponent:

-import { computed, ref } from 'vue';
+import { computed, ref, defineAsyncComponent } from 'vue';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90a0f55 and 14aaf98.

⛔ Files ignored due to path filters (1)
  • website/client/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • website/client/components/ResultViewer.vue (4 hunks)
  • website/client/components/TryIt.vue (2 hunks)
  • website/client/components/api/client.ts (0 hunks)
  • website/client/components/utils/analytics.ts (0 hunks)
  • website/client/components/utils/requestHandlers.ts (1 hunks)
  • website/client/components/utils/resultViewer.ts (1 hunks)
  • website/client/components/utils/validation.ts (1 hunks)
  • website/client/package.json (1 hunks)
💤 Files with no reviewable changes (2)
  • website/client/components/api/client.ts
  • website/client/components/utils/analytics.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • website/client/package.json
  • website/client/components/utils/validation.ts
  • website/client/components/utils/resultViewer.ts
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Test (windows-latest, 23.x)
  • GitHub Check: Test (windows-latest, 22.x)
  • GitHub Check: Test (windows-latest, 21.x)
  • GitHub Check: Test (windows-latest, 20.x)
  • GitHub Check: Test (windows-latest, 19.x)
  • GitHub Check: Test (windows-latest, 18.x)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (11)
website/client/components/ResultViewer.vue (4)

22-32: LGTM! Well-structured copy handler.

The copy handler follows best practices:

  • Prevents default event behavior
  • Includes null checks
  • Provides user feedback
  • Uses extracted utility function

35-40: LGTM! Well-structured download handler.

The download handler follows similar good practices as the copy handler.


268-272: LGTM! Well-structured styles.

The editor container styles maintain consistency with the design system and provide proper containment for the Ace Editor.


4-4: LGTM! Good separation of concerns.

The extraction of utility functions and integration of the Ace Editor shows good architectural decisions for maintainability.

Let's verify the package dependency:

Also applies to: 6-6

✅ Verification successful

Import statement is properly configured with required dependency ✓

The vue3-ace-editor package is correctly added as a dependency in website/client/package.json, validating the import statement.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if vue3-ace-editor is properly added to package.json
grep -r "vue3-ace-editor" website/package.json

Length of output: 100


Script:

#!/bin/bash
# Find all package.json files and search for vue3-ace-editor
fd package.json --type f --exec grep -l "vue3-ace-editor" {} \;

Length of output: 96

website/client/components/utils/requestHandlers.ts (3)

1-10: LGTM! Well-structured interface definition.

The RequestHandlerOptions interface is well-designed with clear optional properties for success/error callbacks and abort signal.


63-69: LGTM! Clean and focused implementation.

The function handles both boolean and string values appropriately, with consistent analytics tracking.


47-52: 🛠️ Refactor suggestion

Improve error handling for AbortError.

The current error handling for AbortError could be more robust.

Apply this diff to improve the error handling:

-    const errorMessage = err instanceof Error ? err.message : 'An unexpected error occurred';
-
-    if (errorMessage === 'AbortError') {
+    let errorMessage: string;
+    if (err instanceof Error) {
+      if (err.name === 'AbortError') {
+        errorMessage = 'Request was cancelled';
+      } else {
+        errorMessage = err.message;
+      }
+    } else {
+      errorMessage = 'An unexpected error occurred';
+    }
+
+    if (err instanceof Error && err.name === 'AbortError') {
       onError?.('Request was cancelled');
       return;
     }

Likely invalid or redundant comment.

website/client/components/TryIt.vue (4)

1-8: LGTM! Well-organized imports and modern Vue setup.

Using Vue 3's script setup syntax with proper imports organization.


89-131: LGTM! Consistent event handling implementation.

The event handlers are well-structured with:

  • Clear separation of concerns
  • Consistent analytics tracking
  • Proper state management

Line range hint 144-669: LGTM! Well-structured template with proper accessibility.

The template implementation shows:

  • Good attention to accessibility with proper ARIA labels
  • Responsive design with appropriate breakpoints
  • Clear visual feedback for user interactions

51-56: ⚠️ Potential issue

Fix the timeout implementation to properly handle errors.

The current timeout implementation has two issues:

  1. Throwing an error in a setTimeout callback won't be caught by try-catch
  2. The error won't be properly propagated to the UI

Apply this diff to fix the timeout handling:

-  const timeoutId = setTimeout(() => {
-    if (requestController) {
-      requestController.abort('Request timed out');
-      throw new Error('Request timed out');
-    }
-  }, TIMEOUT_MS);
+  const timeoutPromise = new Promise((_, reject) => {
+    setTimeout(() => {
+      if (requestController) {
+        requestController.abort();
+        reject(new Error('Request timed out'));
+      }
+    }, TIMEOUT_MS);
+  });
+
+  try {
+    await Promise.race([
+      handlePackRequest(
+        url.value,
+        format.value,
+        {
+          removeComments: removeComments.value,
+          removeEmptyLines: removeEmptyLines.value,
+          showLineNumbers: showLineNumbers.value,
+          fileSummary: fileSummary.value,
+          directoryStructure: directoryStructure.value,
+          includePatterns: includePatterns.value ? includePatterns.value.trim() : undefined,
+          ignorePatterns: ignorePatterns.value ? ignorePatterns.value.trim() : undefined,
+          outputParsable: outputParsable.value,
+        },
+        {
+          onSuccess: (response) => {
+            result.value = response;
+          },
+          onError: (errorMessage) => {
+            error.value = errorMessage;
+          },
+          signal: requestController.signal,
+        },
+      ),
+      timeoutPromise
+    ]);
+  } catch (err) {
+    error.value = err instanceof Error ? err.message : 'An unexpected error occurred';
+  }

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 14aaf98 and 963ffa0.

📒 Files selected for processing (1)
  • .npmignore (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Test (windows-latest, 23.x)
  • GitHub Check: Test (windows-latest, 22.x)
  • GitHub Check: Test (windows-latest, 21.x)
  • GitHub Check: Test (windows-latest, 19.x)
  • GitHub Check: Test (windows-latest, 18.x)
  • GitHub Check: Test (windows-latest, 18.0.0)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages

.npmignore Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (3)
website/client/components/TryIt.vue (3)

44-49: ⚠️ Potential issue

Fix timeout handling mechanism.

The current timeout implementation has potential issues:

  1. The error is thrown but not caught in the try-catch block
  2. The timeout error might not be properly propagated to the UI

Apply this diff to fix the timeout handling:

-  const timeoutId = setTimeout(() => {
-    if (requestController) {
-      requestController.abort('Request timed out');
-      throw new Error('Request timed out');
-    }
-  }, TIMEOUT_MS);
+  const timeoutPromise = new Promise((_, reject) => {
+    setTimeout(() => {
+      if (requestController) {
+        requestController.abort();
+        reject(new Error('Request timed out'));
+      }
+    }, TIMEOUT_MS);
+  });
+
+  try {
+    await Promise.race([
+      handlePackRequest(
+        url.value,
+        format.value,
+        {
+          removeComments: removeComments.value,
+          removeEmptyLines: removeEmptyLines.value,
+          showLineNumbers: showLineNumbers.value,
+          fileSummary: fileSummary.value,
+          directoryStructure: directoryStructure.value,
+          includePatterns: includePatterns.value ? includePatterns.value.trim() : undefined,
+          ignorePatterns: ignorePatterns.value ? ignorePatterns.value.trim() : undefined,
+          outputParsable: outputParsable.value,
+        },
+        {
+          onSuccess: (response) => {
+            result.value = response;
+          },
+          onError: (errorMessage) => {
+            error.value = errorMessage;
+          },
+          signal: requestController.signal,
+        },
+      ),
+      timeoutPromise
+    ]);
+  } catch (err) {
+    error.value = err instanceof Error ? err.message : 'An error occurred';
+  }

44-49: ⚠️ Potential issue

Fix timeout handling mechanism.

The timeout implementation has potential issues:

  1. The error is thrown but not caught in the try-catch block
  2. The timeout error might not be properly propagated to the UI
-  const timeoutId = setTimeout(() => {
-    if (requestController) {
-      requestController.abort('Request timed out');
-      throw new Error('Request timed out');
-    }
-  }, TIMEOUT_MS);
+  const timeoutPromise = new Promise((_, reject) => {
+    setTimeout(() => {
+      if (requestController) {
+        requestController.abort();
+        reject(new Error('Request timed out'));
+      }
+    }, TIMEOUT_MS);
+  });
+
+  try {
+    await Promise.race([
+      handlePackRequest(
+        url.value,
+        format.value,
+        {
+          removeComments: removeComments.value,
+          removeEmptyLines: removeEmptyLines.value,
+          showLineNumbers: showLineNumbers.value,
+          fileSummary: fileSummary.value,
+          directoryStructure: directoryStructure.value,
+          includePatterns: includePatterns.value ? includePatterns.value.trim() : undefined,
+          ignorePatterns: ignorePatterns.value ? ignorePatterns.value.trim() : undefined,
+          outputParsable: outputParsable.value,
+        },
+        {
+          onSuccess: (response) => {
+            result.value = response;
+          },
+          onError: (errorMessage) => {
+            error.value = errorMessage;
+          },
+          signal: requestController.signal,
+        },
+      ),
+      timeoutPromise
+    ]);
+  } catch (err) {
+    error.value = err instanceof Error ? err.message : 'An error occurred';
+  }

44-49: ⚠️ Potential issue

Improve timeout handling mechanism.

The timeout implementation has potential issues that were previously identified.

🧹 Nitpick comments (9)
website/client/components/TryItUrlInput.vue (4)

32-72: Consider enhancing keyboard accessibility.

While the component has good accessibility features like ARIA labels, consider adding role="search" to the input group and handling the Escape key to clear the input.

-  <div class="input-group">
+  <div class="input-group" role="search">
     <div class="url-input-container">
       <input
         :value="url"
         @input="handleUrlInput"
-        @keydown="handleKeydown"
+        @keydown="(e) => {
+          handleKeydown(e);
+          if (e.key === 'Escape') emit('update:url', '');
+        }"
         type="text"

35-44: Consider adding debounce to URL input validation.

The URL validation runs on every input change, which could be performance-intensive for rapid typing.

+import { debounce } from 'lodash-es';
+
 function handleUrlInput(event: Event) {
   const input = event.target as HTMLInputElement;
-  emit('update:url', input.value);
+  debouncedEmit(input.value);
 }
+
+const debouncedEmit = debounce((value: string) => {
+  emit('update:url', value);
+}, 300);

149-154: Consider adding a min-width for mobile responsiveness.

The current mobile layout might become too cramped for very small screens.

 @media (max-width: 640px) {
   .url-input-container {
     flex-direction: column;
+    min-width: 280px;
   }
 }

22-25: Consider debouncing the URL input handler.

For better performance, consider debouncing the URL input handler to reduce the number of validation calls and re-renders.

+import { debounce } from 'lodash-es';
+
+const debouncedHandleUrlInput = debounce((value: string) => {
+  emit('update:url', value);
+}, 300);
+
 function handleUrlInput(event: Event) {
   const input = event.target as HTMLInputElement;
-  emit('update:url', input.value);
+  debouncedHandleUrlInput(input.value);
 }
website/client/components/TryItPackOptions.vue (3)

30-73: Consider extracting analytics tracking logic.

The event handlers mix UI updates with analytics tracking. Consider using a composable for analytics:

// useAnalytics.ts
export function useAnalytics() {
  return {
    trackOptionChange: (value: unknown, action: AnalyticsAction) => {
      handleOptionChange(value, action);
    }
  };
}

// In component:
const { trackOptionChange } = useAnalytics();
function handleFormatChange(newFormat: 'xml' | 'markdown' | 'plain') {
  emit('update:format', newFormat);
  trackOptionChange(newFormat, AnalyticsAction.FORMAT_CHANGE);
}

30-73: Consider grouping related handlers using a factory function.

The current implementation has repetitive handler functions that follow the same pattern.

+function createOptionHandler(emitName: string, action: AnalyticsAction) {
+  return (value: boolean | string) => {
+    emit(`update:${emitName}`, value);
+    handleOptionChange(value, action);
+  };
+}
+
-function handleFormatChange(newFormat: 'xml' | 'markdown' | 'plain') {
-  emit('update:format', newFormat);
-  handleOptionChange(newFormat, AnalyticsAction.FORMAT_CHANGE);
-}
+const handleFormatChange = createOptionHandler('format', AnalyticsAction.FORMAT_CHANGE);

35-38: Add validation for include/ignore patterns.

Consider validating the glob patterns to ensure they are properly formatted.

+import { isValidGlobPattern } from './utils/validation';
+
 function handleIncludePatternsUpdate(patterns: string) {
+  const validPatterns = patterns.split(',')
+    .map(p => p.trim())
+    .filter(p => p && isValidGlobPattern(p))
+    .join(',');
-  emit('update:includePatterns', patterns);
+  emit('update:includePatterns', validPatterns);
   handleOptionChange(patterns, AnalyticsAction.UPDATE_INCLUDE_PATTERNS);
 }

Also applies to: 40-43

website/client/components/TryItResultViewer.vue (2)

268-270: Consider adding loading state for the editor.

Large files might take time to load in the editor.

 .editor-container {
   height: 100%;
   width: 100%;
   font-family: var(--vp-font-family-mono);
+  position: relative;
 }
+
+.editor-loading {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}

111-118: Consider adding error boundary for editor crashes.

Large files might cause the editor to crash. Consider adding an error boundary component to gracefully handle such cases.

+<script setup lang="ts">
+import { onErrorCaptured, ref } from 'vue';
+
+const editorError = ref<Error | null>(null);
+
+onErrorCaptured((err) => {
+  editorError.value = err;
+  return false;
+});
+</script>

 <div class="editor-container">
+  <div v-if="editorError" class="editor-error">
+    <p>Failed to load editor. Falling back to plain text.</p>
+    <pre><code>{{ result.content }}</code></pre>
+  </div>
+  <div v-else>
     <VAceEditor
       v-model:value="result.content"
       :lang="'text'"
       :style="{ height: '100%', width: '100%' }"
       :options="editorOptions"
     />
+  </div>
 </div>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 963ffa0 and 2db6c0f.

📒 Files selected for processing (4)
  • website/client/components/TryIt.vue (2 hunks)
  • website/client/components/TryItPackOptions.vue (1 hunks)
  • website/client/components/TryItResultViewer.vue (4 hunks)
  • website/client/components/TryItUrlInput.vue (1 hunks)
👮 Files not reviewed due to content moderation or server errors (4)
  • website/client/components/TryItUrlInput.vue
  • website/client/components/TryItResultViewer.vue
  • website/client/components/TryItPackOptions.vue
  • website/client/components/TryIt.vue
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Test (windows-latest, 23.x)
  • GitHub Check: Test (windows-latest, 22.x)
  • GitHub Check: Test (windows-latest, 21.x)
  • GitHub Check: Test (windows-latest, 20.x)
  • GitHub Check: Test (windows-latest, 19.x)
  • GitHub Check: Test coverage
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (11)
website/client/components/TryItUrlInput.vue (4)

1-30: LGTM! Well-structured component setup.

The component follows Vue.js best practices:

  • Uses TypeScript for type safety
  • Properly defines props and emits
  • Implements clean validation logic
  • Follows the single responsibility principle

149-154: LGTM! Responsive design implementation.

The mobile-first approach with proper breakpoints is well implemented.


1-30: LGTM! Well-structured component setup with TypeScript.

The component follows Vue.js best practices:

  • Strong typing with TypeScript
  • Clear prop and emit definitions
  • Proper validation using computed properties
  • Clean event handling

1-74: LGTM! Well-structured component with proper TypeScript integration.

The component is well-organized with proper type definitions, computed properties, and event handling.

website/client/components/TryItResultViewer.vue (4)

4-6: LGTM! Clean dependency management.

The imports are well-organized and properly typed.


268-270: LGTM! Proper editor container styling.

The container styles ensure the editor fills the available space while maintaining the monospace font.


4-6: LGTM! Good separation of concerns.

Clean imports with proper file extensions and type imports.


111-118: LGTM! Good integration of Ace Editor for improved performance.

The Ace Editor integration with proper styling and options setup will help improve performance for large repository outputs.

website/client/components/TryIt.vue (2)

90-107: LGTM! Clean component composition.

The refactoring to use separate components for URL input, pack options, and result viewing improves code organization and maintainability.


90-107: LGTM! Well-structured component composition.

Good separation of concerns using child components with proper prop bindings.

website/client/components/TryItPackOptions.vue (1)

1-74: LGTM! Well-organized component with proper analytics tracking.

The component is well-structured with proper type definitions and analytics integration.

website/client/components/TryIt.vue Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
website/client/components/TryIt.vue (1)

44-49: ⚠️ Potential issue

Improve timeout handling mechanism.

The current timeout implementation has potential issues:

  1. The error is thrown but not caught in the try-catch block
  2. The timeout error might not be properly propagated to the UI

Apply this diff to improve the timeout handling:

-  const timeoutId = setTimeout(() => {
-    if (requestController) {
-      requestController.abort('Request timed out');
-      throw new Error('Request timed out');
-    }
-  }, TIMEOUT_MS);
+  const timeoutPromise = new Promise((_, reject) => {
+    setTimeout(() => {
+      if (requestController) {
+        currentRequest.abort();
+        reject(new Error('Request timed out'));
+      }
+    }, TIMEOUT_MS);
+  });
+
+  try {
+    await Promise.race([
+      handlePackRequest(/*...*/),
+      timeoutPromise
+    ]);
+  } catch (err) {
+    // Error handling
+  }
🧹 Nitpick comments (2)
website/client/components/TryItUrlInput.vue (2)

68-71: Enhance accessibility for validation messages.

Add aria-live to announce validation messages to screen readers.

-    <div v-if="url && !isValidUrl" class="url-warning">
+    <div v-if="url && !isValidUrl" class="url-warning" aria-live="polite">

35-44: Add autocomplete attribute for better UX.

Consider adding autocomplete="off" to prevent unwanted suggestions for repository URLs.

       type="text"
+      autocomplete="off"
       placeholder="GitHub repository URL or user/repo (e.g., yamadashy/repomix)"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2db6c0f and 59f31bf.

📒 Files selected for processing (5)
  • website/client/components/TryIt.vue (2 hunks)
  • website/client/components/TryItPackOptions.vue (1 hunks)
  • website/client/components/TryItResultViewer.vue (4 hunks)
  • website/client/components/TryItUrlInput.vue (1 hunks)
  • website/client/components/utils/resultViewer.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/client/components/utils/resultViewer.ts
👮 Files not reviewed due to content moderation or server errors (4)
  • website/client/components/TryItPackOptions.vue
  • website/client/components/TryIt.vue
  • website/client/components/TryItUrlInput.vue
  • website/client/components/TryItResultViewer.vue
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Test (windows-latest, 23.x)
  • GitHub Check: Test (windows-latest, 22.x)
  • GitHub Check: Test (windows-latest, 21.x)
  • GitHub Check: Test (windows-latest, 20.x)
  • GitHub Check: Test (windows-latest, 19.x)
  • GitHub Check: Test (windows-latest, 18.x)
  • GitHub Check: Test (windows-latest, 18.0.0)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (23)
website/client/components/TryItPackOptions.vue (9)

1-74: LGTM! Well-structured script setup.

The implementation follows Vue's best practices with proper TypeScript types and consistent handler patterns.


190-203: Consider improving tooltip accessibility.

The tooltip implementation could be enhanced for better accessibility.


211-371: LGTM! Well-organized styles.

The styles follow best practices with proper use of CSS variables and responsive design.


1-74: LGTM! Well-structured script setup.

The implementation follows Vue's best practices with proper TypeScript types, clear prop definitions, and consistent analytics tracking.


190-203: Improve tooltip accessibility.

The tooltip implementation could be enhanced for better accessibility.

Apply this diff to improve accessibility:

 <div class="parsable-option">
   <span>Output Parsable Format</span>
   <div class="tooltip-container">
     <HelpCircle
       :size="16"
       class="help-icon"
+      role="button"
+      tabindex="0"
+      @keydown.enter="() => {}"
       aria-label="More information about parsable format"
     />
-    <div class="tooltip-content">
+    <div
+      class="tooltip-content"
+      role="tooltip"
+      aria-hidden="true"
+    >
       Whether to escape the output based on the chosen style schema. Note that this can increase token count.
       <div class="tooltip-arrow"></div>
     </div>
   </div>
 </div>

211-371: LGTM! Well-organized styles.

The styles are well-structured with proper use of CSS variables, clear organization, and responsive design considerations.


1-74: LGTM! Well-structured script section.

The script section demonstrates good practices:

  • Props and emits are properly typed
  • Handlers follow a consistent pattern
  • Analytics tracking is integrated

190-203: Improve tooltip accessibility.

The tooltip implementation could be enhanced for better accessibility.

Apply this diff to improve accessibility:

 <div class="parsable-option">
   <span>Output Parsable Format</span>
   <div class="tooltip-container">
     <HelpCircle
       :size="16"
       class="help-icon"
+      role="button"
+      tabindex="0"
+      @keydown.enter="() => {}"
       aria-label="More information about parsable format"
     />
-    <div class="tooltip-content">
+    <div
+      class="tooltip-content"
+      role="tooltip"
+      aria-hidden="true"
+    >
       Whether to escape the output based on the chosen style schema. Note that this can increase token count.
       <div class="tooltip-arrow"></div>
     </div>
   </div>
 </div>

211-371: LGTM! Well-structured styles.

The styles demonstrate good practices:

  • Scoped to the component
  • Proper use of CSS variables
  • Responsive design implementation
website/client/components/TryIt.vue (6)

44-49: Improve timeout handling mechanism.

The current timeout implementation has potential issues:

  1. The error is thrown but not caught in the try-catch block
  2. The timeout error might not be properly propagated to the UI

28-28: Add cleanup for request controller.

Consider cleaning up the request controller when the component is unmounted.


28-28: Add cleanup for request controller.

Consider cleaning up the request controller when the component is unmounted.

Apply this diff:

+import { onUnmounted } from 'vue';
+
 let requestController: AbortController | null = null;
+
+onUnmounted(() => {
+  if (requestController) {
+    requestController.abort();
+    requestController = null;
+  }
+});

28-28: Add cleanup for request controller.

Consider cleaning up the request controller when the component is unmounted.

Apply this diff to add cleanup:

+import { onUnmounted } from 'vue';
+
 let requestController: AbortController | null = null;
+
+onUnmounted(() => {
+  if (requestController) {
+    requestController.abort();
+    requestController = null;
+  }
+});

90-114: LGTM! Well-structured template.

The template demonstrates good practices:

  • Components are properly integrated
  • Props and events are correctly bound

44-49: ⚠️ Potential issue

Improve timeout handling mechanism.

The current timeout implementation has potential issues:

  1. The error is thrown but not caught in the try-catch block
  2. The timeout error might not be properly propagated to the UI

Apply this diff to improve the timeout handling:

-  const timeoutId = setTimeout(() => {
-    if (requestController) {
-      requestController.abort('Request timed out');
-      throw new Error('Request timed out');
-    }
-  }, TIMEOUT_MS);
+  const timeoutPromise = new Promise((_, reject) => {
+    setTimeout(() => {
+      if (requestController) {
+        requestController.abort();
+        reject(new Error('Request timed out'));
+      }
+    }, TIMEOUT_MS);
+  });
+
+  try {
+    await Promise.race([
+      handlePackRequest(/*...*/),
+      timeoutPromise
+    ]);
+  } catch (err) {
+    // Error handling
+  }

Likely invalid or redundant comment.

website/client/components/TryItResultViewer.vue (5)

111-118: Consider configuring Ace Editor for large files.

While Ace Editor is a good choice for performance, consider adding these configurations for better handling of large files.


111-118: Consider adding error boundary for editor initialization.

The Ace Editor initialization might fail in certain environments.


111-118: Consider configuring Ace Editor for large files and adding error boundary.

The Ace Editor implementation could be improved for better handling of large files and error cases.

Apply these diffs:

  1. Configure Ace Editor for large files:
 <VAceEditor
   v-model:value="result.content"
   :lang="'text'"
   :style="{ height: '100%', width: '100%' }"
-  :options="editorOptions"
+  :options="{
+    ...editorOptions,
+    maxLines: 5000,
+    minLines: 10,
+    wrap: true,
+    useWorker: false,
+    showPrintMargin: false
+  }"
 />
  1. Add error boundary for editor initialization:
 <div class="editor-container">
+  <ErrorBoundary v-slot="{ error }">
+    <div v-if="error" class="editor-error">
+      Failed to load editor: {{ error }}
+    </div>
     <VAceEditor
         v-model:value="result.content"
         :lang="'text'"
         :style="{ height: '100%', width: '100%' }"
         :options="editorOptions"
     />
+  </ErrorBoundary>
 </div>

111-118: Consider configuring Ace Editor for large files.

While Ace Editor is a good choice for performance, consider adding these configurations for better handling of large files.

Apply this diff to improve the editor configuration:

 <VAceEditor
   v-model:value="result.content"
   :lang="'text'"
   :style="{ height: '100%', width: '100%' }"
-  :options="editorOptions"
+  :options="{
+    ...editorOptions,
+    maxLines: 5000,
+    minLines: 10,
+    wrap: true,
+    useWorker: false,
+    showPrintMargin: false
+  }"
 />

Consider adding error boundary for editor initialization.

The Ace Editor initialization might fail in certain environments.

Apply this diff to add error handling:

 <div class="editor-container">
+  <ErrorBoundary v-slot="{ error }">
+    <div v-if="error" class="editor-error">
+      Failed to load editor: {{ error }}
+    </div>
     <VAceEditor
         v-model:value="result.content"
         :lang="'text'"
         :style="{ height: '100%', width: '100%' }"
         :options="editorOptions"
     />
+  </ErrorBoundary>
 </div>

268-270: LGTM! Well-structured editor container styles.

The styles demonstrate good practices:

  • Proper dimensions
  • Font family configuration
website/client/components/TryItUrlInput.vue (3)

1-154: LGTM! Well-implemented URL input component.

The implementation follows best practices with:

  • Strong TypeScript typing
  • Clear validation logic
  • Good error handling and user feedback
  • Proper accessibility attributes

1-73: LGTM! Well-implemented URL input component.

The implementation demonstrates good practices:

  • Proper URL validation
  • Clear error handling
  • Good user feedback

75-154: LGTM! Well-structured styles.

The styles demonstrate good practices:

  • Proper use of CSS variables
  • Responsive design implementation

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
README.md (2)

721-731: Consider adding information about data persistence.

The privacy policy clearly outlines data collection and network usage. However, it could be beneficial to explicitly mention whether any data is cached or temporarily stored during remote repository processing.

 ### Network Usage
 Repomix operates fully offline after installation. The only cases where an internet connection is needed are:
 - Installation via npm/yarn.
 - Using the `--remote` flag to process remote repositories.
 - Checking for updates (manually triggered).
+
+When processing remote repositories, files are temporarily cloned to a system temporary directory and are automatically cleaned up after processing.

732-734: Consider expanding security considerations.

While the security section is clear, it could be enhanced by mentioning the built-in security checks that prevent sensitive information leakage.

 ### Security Considerations
 Since all processing is local, Repomix is safe to use with private and internal repositories.
+Additionally, Repomix includes built-in security checks using Secretlint to prevent accidental exposure of sensitive information in the generated output.
website/client/components/TryItPackOptions.vue (1)

111-118: Add pattern validation for include/ignore inputs.

Consider adding real-time validation for glob patterns to provide immediate feedback to users.

+import { isValidGlobPattern } from './utils/validation.js';
+
+const includePatternError = ref<string | null>(null);
+const ignorePatternError = ref<string | null>(null);
+
+function validatePattern(pattern: string): string | null {
+  if (!pattern) return null;
+  return isValidGlobPattern(pattern) ? null : 'Invalid glob pattern';
+}

 <input
   :value="includePatterns"
-  @input="event => handleIncludePatternsUpdate((event.target as HTMLInputElement).value)"
+  @input="event => {
+    const value = (event.target as HTMLInputElement).value;
+    includePatternError.value = validatePattern(value);
+    handleIncludePatternsUpdate(value);
+  }"
   type="text"
   class="repository-input"
   placeholder="Comma-separated patterns to include. e.g., src/**/*.ts"
   aria-label="Include patterns"
+  :aria-invalid="!!includePatternError.value"
+  :aria-errormessage="includePatternError.value || undefined"
 />
+<span v-if="includePatternError" class="error-message">{{ includePatternError }}</span>

Also applies to: 123-130

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59f31bf and 10b1f39.

📒 Files selected for processing (6)
  • README.md (2 hunks)
  • website/client/components/TryIt.vue (2 hunks)
  • website/client/components/TryItPackOptions.vue (1 hunks)
  • website/client/components/TryItResultViewer.vue (4 hunks)
  • website/client/components/TryItUrlInput.vue (1 hunks)
  • website/client/components/utils/resultViewer.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/client/components/TryItUrlInput.vue
  • website/client/components/utils/resultViewer.ts
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Test (windows-latest, 23.x)
  • GitHub Check: Test (windows-latest, 22.x)
  • GitHub Check: Test (windows-latest, 21.x)
  • GitHub Check: Test (windows-latest, 20.x)
  • GitHub Check: Test (windows-latest, 19.x)
  • GitHub Check: Test (windows-latest, 18.x)
  • GitHub Check: Test (windows-latest, 18.0.0)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
README.md (2)

Line range hint 706-719: LGTM! Well-structured contribution section.

The contribution section effectively encourages community involvement and includes a nice visual representation of contributors.


735-738: LGTM! Clear liability disclaimer.

The liability disclaimer is well-written and covers the necessary aspects of warranty and responsibility.

website/client/components/TryIt.vue (2)

28-28: 🛠️ Refactor suggestion

Add cleanup for request controller.

Consider cleaning up the request controller when the component is unmounted.

+import { onUnmounted } from 'vue';
+
 let requestController: AbortController | null = null;
+
+onUnmounted(() => {
+  if (requestController) {
+    requestController.abort();
+    requestController = null;
+  }
+});

Likely invalid or redundant comment.


44-49: ⚠️ Potential issue

Improve timeout handling mechanism.

The current timeout implementation has potential issues:

  1. The error is thrown but not caught in the try-catch block
  2. The timeout error might not be properly propagated to the UI

Consider using Promise.race for better timeout handling:

-  const timeoutId = setTimeout(() => {
-    if (requestController) {
-      requestController.abort('Request timed out');
-      throw new Error('Request timed out');
-    }
-  }, TIMEOUT_MS);
+  const timeoutPromise = new Promise((_, reject) => {
+    setTimeout(() => {
+      if (requestController) {
+        requestController.abort();
+        reject(new Error('Request timed out'));
+      }
+    }, TIMEOUT_MS);
+  });
+
+  try {
+    await Promise.race([
+      handlePackRequest(
+        url.value,
+        format.value,
+        {
+          removeComments: removeComments.value,
+          removeEmptyLines: removeEmptyLines.value,
+          showLineNumbers: showLineNumbers.value,
+          fileSummary: fileSummary.value,
+          directoryStructure: directoryStructure.value,
+          includePatterns: includePatterns.value ? includePatterns.value.trim() : undefined,
+          ignorePatterns: ignorePatterns.value ? ignorePatterns.value.trim() : undefined,
+          outputParsable: outputParsable.value,
+        },
+        {
+          onSuccess,
+          onError,
+          signal: requestController.signal,
+        }
+      ),
+      timeoutPromise
+    ]);
+  } catch (err) {
+    onError(err.message);
+  }

Likely invalid or redundant comment.

website/client/components/TryItResultViewer.vue (1)

111-118: 🛠️ Refactor suggestion

Optimize Ace Editor for large files.

While Ace Editor is a good choice for performance, consider these optimizations for better handling of large files:

  1. Configure editor for large files:
 <VAceEditor
   v-model:value="result.content"
   :lang="'text'"
   :style="{ height: '100%', width: '100%' }"
-  :options="editorOptions"
+  :options="{
+    ...editorOptions,
+    maxLines: 5000,
+    minLines: 10,
+    wrap: true,
+    useWorker: false,
+    showPrintMargin: false
+  }"
 />
  1. Add error boundary for editor initialization:
 <div class="editor-container">
+  <ErrorBoundary v-slot="{ error }">
+    <div v-if="error" class="editor-error">
+      Failed to load editor: {{ error }}
+    </div>
     <VAceEditor
       v-model:value="result.content"
       :lang="'text'"
       :style="{ height: '100%', width: '100%' }"
       :options="editorOptions"
     />
+  </ErrorBoundary>
 </div>

Likely invalid or redundant comment.

website/client/components/TryItPackOptions.vue (1)

190-203: 🛠️ Refactor suggestion

Improve tooltip accessibility.

The tooltip implementation should be enhanced for better accessibility.

 <div class="parsable-option">
   <span>Output Parsable Format</span>
   <div class="tooltip-container">
     <HelpCircle
       :size="16"
       class="help-icon"
+      role="button"
+      tabindex="0"
+      @keydown.enter="() => {}"
       aria-label="More information about parsable format"
     />
-    <div class="tooltip-content">
+    <div
+      class="tooltip-content"
+      role="tooltip"
+      aria-hidden="true"
+    >
       Whether to escape the output based on the chosen style schema. Note that this can increase token count.
       <div class="tooltip-arrow"></div>
     </div>
   </div>
 </div>

Likely invalid or redundant comment.

@yamadashy yamadashy merged commit a06c399 into main Jan 25, 2025
54 checks passed
@yamadashy yamadashy deleted the feat/website-ace branch January 25, 2025 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant