Skip to content

feat(website): add URL query string parameter support#775

Merged
yamadashy merged 13 commits intomainfrom
feature/website-url-query-parameters
Aug 17, 2025
Merged

feat(website): add URL query string parameter support#775
yamadashy merged 13 commits intomainfrom
feature/website-url-query-parameters

Conversation

@yamadashy
Copy link
Owner

@yamadashy yamadashy commented Aug 12, 2025

Implements URL query string parameter support for the Repomix web interface.

related:

This allows users to bookmark or share links with preset options and automatically load configurations.

image

Copilot AI review requested due to automatic review settings August 12, 2025 15:45
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 12, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds a URL-parameter utilities module and integrates URL parsing/updating across TryIt.vue and pack composables. Initializes input and options from URL, updates URL on submit with only non-default options, adds reset UI/logic, and auto-submits when a repo URL is present. Minor whitespace tweaks.

Changes

Cohort / File(s) Summary
TryIt UI & behavior
website/client/components/Home/TryIt.vue, website/client/components/Home/TryItPackOptions.vue
TryIt.vue: consume parseUrlParameters/updateUrlParameters, prefill input/options from URL, auto-submit on repo param, compute shouldShowReset, add reset button (calls resetOptions, clears inputUrl and URL params), submit only diffs from DEFAULT_PACK_OPTIONS, UI/CSS tweaks, import RotateCcw, expand composition API usage. TryItPackOptions.vue: whitespace-only edits.
Pack composables
website/client/composables/usePackOptions.ts, website/client/composables/usePackRequest.ts
usePackOptions: initialize packOptions from parseUrlParameters merged over DEFAULT_PACK_OPTIONS and now returns DEFAULT_PACK_OPTIONS; usePackRequest: prefill inputUrl from URL params, expose resetOptions and DEFAULT_PACK_OPTIONS in public API, and use url params for initialization.
URL parameter utilities
website/client/utils/urlParams.ts
New module adding parseUrlParameters, updateUrlParameters, validateUrlParameters, and hasNonDefaultValues. Handles repo, format/style, include/ignore mapping, boolean flags, SSR guards, conservative URL length checks, and uses history.replaceState to update the URL without reload.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TryIt.vue
  participant usePackRequest
  participant urlParams.ts
  participant Backend

  Note over TryIt.vue: Mount
  TryIt.vue->>urlParams.ts: parseUrlParameters()
  urlParams.ts-->>TryIt.vue: { repo?, options... }
  TryIt.vue->>usePackRequest: initialize with URL-derived input/options
  alt repo present and valid
    TryIt.vue->>TryIt.vue: handleSubmit()
    TryIt.vue->>urlParams.ts: updateUrlParameters(diff from defaults + repo)
    TryIt.vue->>Backend: submit pack request
    Backend-->>TryIt.vue: response
  end
Loading
sequenceDiagram
  participant User
  participant TryIt.vue
  participant urlParams.ts
  participant Backend

  Note over TryIt.vue: User actions
  User->>TryIt.vue: Click "Pack"
  TryIt.vue->>urlParams.ts: updateUrlParameters(diff from defaults + repo if remote)
  TryIt.vue->>Backend: submit pack request
  Backend-->>TryIt.vue: response

  User->>TryIt.vue: Click "Reset"
  TryIt.vue->>TryIt.vue: resetOptions(), clear inputUrl
  TryIt.vue->>urlParams.ts: updateUrlParameters({ clear related params })
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/website-url-query-parameters

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@claude
Copy link
Contributor

claude bot commented Aug 12, 2025

Claude finished @yamadashy's task —— View job


PR Review: URL Query String Parameter Support

Review Tasks

  • Analyze new URL parameter utility (urlParams.ts)
  • Review Vue component changes (TryIt.vue, TryItPackOptions.vue)
  • Review composable modifications (usePackOptions.ts, usePackRequest.ts)
  • Assess overall architecture and design decisions
  • Check for potential bugs and security issues
  • Provide specific feedback and recommendations

Code Quality Analysis

✅ Strengths

Architecture & Design:

  • Clean separation of concerns with dedicated urlParams.ts utility
  • Proper use of Vue 3 Composition API patterns
  • Smart URL parameter filtering to exclude default values, keeping URLs clean
  • Backwards compatibility with style parameter (aliased to format)
  • Non-intrusive URL updates using replaceState instead of pushState

Implementation Quality:

  • Robust boolean parameter parsing accepting multiple formats (true, 1, yes, on)
  • Proper SSR safety checks with typeof window === 'undefined'
  • Auto-execution when valid repo parameter is present
  • Clean reset functionality that clears both state and URL

🔍 Areas for Improvement

1. Type Safety in URL Parameter Parsing (usePackOptions.ts:36-39)

// Current approach uses type casting which bypasses type safety
(initialOptions as Record<string, unknown>)[key] = urlParams[key as keyof PackOptions];

Suggestion: Consider a more type-safe approach:

for (const [key, value] of Object.entries(urlParams)) {
  if (key in initialOptions && value !== undefined) {
    // Type-safe assignment with proper validation
    (initialOptions as any)[key] = value;
  }
}

2. Magic String Duplication
The parameter names are hardcoded in multiple places (urlParams.ts:72-85, urlParams.ts:42-50). Consider extracting to a constant:

const URL_PARAMETERS = [
  'repo', 'format', 'style', 'include', 'ignore',
  'removeComments', 'removeEmptyLines', 'showLineNumbers',
  // ... etc
] as const;

3. URL Parameter Validation
Currently accepts any string value for text parameters. Consider adding validation for:

  • Maximum length limits to prevent excessively long URLs
  • Pattern validation for include/ignore patterns
  • Sanitization of repo URLs

4. Reset Button Logic Complexity (TryIt.vue:144-172)
The shouldShowReset computed has complex nested logic. Consider extracting to a separate function:

function hasNonDefaultValues(): boolean {
  // Extract the complex comparison logic here
}
const shouldShowReset = computed(() => hasExecuted.value && hasNonDefaultValues());

🐛 Potential Issues

1. Missing Error Handling (TryIt.vue:221-225)
Auto-execution on mount could fail, but errors aren't handled:

nextTick(() => {
  handleSubmit(); // Could throw or reject
});

Suggestion: Add try-catch or error boundary handling.

2. URL Length Concerns
No validation for maximum URL length. Very long include/ignore patterns could create URLs exceeding browser limits (~2000 chars).

3. Race Condition Potential
If users rapidly change options, the URL could be updated multiple times. Consider debouncing URL updates.

4. Inconsistent Parameter Handling
The style parameter is accepted but then converted to format. This could be confusing. Consider either:

  • Documenting this clearly, or
  • Deprecating style in favor of format

💡 Enhancement Suggestions

1. URL Validation Utility

export function validateUrlParameters(params: Record<string, unknown>): ValidationResult {
  // Validate parameter values and URL length
}

2. Debounced URL Updates
For better UX when users change multiple options quickly:

const debouncedUpdateUrl = debounce(updateUrlParameters, 300);

3. Parameter Documentation
Consider adding JSDoc comments to document expected parameter formats and valid values.

Security Assessment

No security issues detected

  • Proper input sanitization with .trim()
  • No XSS vulnerabilities in URL parameter handling
  • Safe use of window.history.replaceState

Performance Considerations

  • Minimal performance impact from URL parsing/updating
  • SSR-safe implementation
  • Efficient parameter filtering logic

Architecture Assessment

Well-structured implementation

  • Clear separation between URL utilities and component logic
  • Proper Vue composable patterns
  • Maintains existing component interfaces
  • Clean integration with existing state management

Final Recommendation

This is a solid implementation that successfully addresses the requirements. The code is well-structured, follows Vue best practices, and provides a clean user experience. The suggestions above are primarily for further enhancement and robustness rather than critical issues.

Approval recommended with consideration for the improvement suggestions in future iterations.


Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @yamadashy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces comprehensive support for URL query string parameters within the Repomix web interface. This enhancement allows users to pre-configure various options, such as the repository URL and packing settings, directly through the URL. This functionality significantly improves user experience by enabling easy sharing of pre-set configurations, bookmarking specific setups, and automatically loading desired options upon page access, streamlining workflows for different projects and team collaborations.

Highlights

  • URL Parameter Management: A new utility (urlParams.ts) has been created to efficiently parse incoming URL query parameters and update them dynamically.
  • Option Initialization: The application's packing options (usePackOptions.ts) now initialize their values directly from URL parameters when the page loads, ensuring a consistent state.
  • Dynamic URL Updates: The TryIt.vue component has been enhanced to automatically update the browser's URL with current packing options and the repository URL when the "Pack" button is clicked, making configurations shareable.
  • Reset Functionality: A new "Reset" button has been added, providing a quick way to revert all options and the repository URL to their default states.
  • Intelligent Reset Visibility: The "Reset" button intelligently appears only when the pack operation has been executed and there are non-default values set, preventing unnecessary clutter.
  • Clean URLs: URL parameters are designed to exclude default values, ensuring that generated URLs remain concise and readable.
  • Informative Tooltip: A hover tooltip has been added to the "Reset" button, clearly explaining its purpose to the user.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Aug 12, 2025

Deploying repomix with  Cloudflare Pages  Cloudflare Pages

Latest commit: 11211a7
Status: ✅  Deploy successful!
Preview URL: https://7be20ffd.repomix.pages.dev
Branch Preview URL: https://feature-website-url-query-pa.repomix.pages.dev

View logs

@codecov
Copy link

codecov bot commented Aug 12, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.59%. Comparing base (86f3012) to head (1e08cbb).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #775   +/-   ##
=======================================
  Coverage   88.59%   88.59%           
=======================================
  Files         110      110           
  Lines        6192     6192           
  Branches     1282     1282           
=======================================
  Hits         5486     5486           
  Misses        706      706           

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This comment was marked as outdated.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces URL query string parameter support, which is a great enhancement for usability and sharing. The implementation is solid, covering parsing, updating, and resetting parameters. I've identified a couple of functional bugs related to option comparison and URL parameter key mapping, as well as some opportunities to improve maintainability and UI consistency. My feedback includes specific code suggestions to address these points.

yamadashy and others added 6 commits August 17, 2025 13:48
Implement comprehensive URL query parameter functionality for Repomix web interface
to enable easy sharing and bookmarking of configurations.

Features:
- Parse URL parameters on page load and apply settings automatically
- Update URL only when Pack button is pressed (not real-time)
- Exclude default values from URL parameters to keep URLs clean
- Reset functionality with icon-only button next to Pack button
- Hover tooltip for reset button explaining functionality
- Support for all pack options: format, patterns, boolean flags
- Auto-pack when valid repository URL is provided via parameters

Changes:
- Add urlParams.ts utility for parsing and updating URL parameters
- Update usePackOptions to initialize from URL parameters
- Modify usePackRequest to handle URL parameter logic
- Add reset button with tooltip next to Pack button (appears after Pack execution)
- Remove previous reset button from options panel
- Implement smart URL generation (only non-default values included)

Examples:
- Basic: ?repo=https://github.com/user/repo&format=markdown
- Advanced: ?repo=https://github.com/user/repo&include=**/*.cs&compress=true

Resolves #764

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add smart visibility control for reset button to only show when reset is actually needed.

Changes:
- Add shouldShowReset computed property with detailed logic
- Show reset button only when:
  - Pack has been executed AND
  - Input URL exists OR pack options differ from defaults
- Hide reset button when in default state (no input, default options)

This creates a cleaner UI that only shows the reset functionality when it's
meaningful to the user.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add satisfying visual feedback when reset button is clicked with a 360-degree
rotation animation of the RotateCcw icon.

Changes:
- Add isResetting ref to manage animation state
- Update handleReset to trigger animation on click
- Add rotating CSS class with 0.5s spin animation
- Use setTimeout to reset animation state after completion
- Apply dynamic class binding to icon based on isResetting state

The animation provides immediate visual feedback and makes the reset action
feel more responsive and engaging for users.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Change rotation duration from 0.5s to 0.3s for faster animation
- Update timeout to match animation duration

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove isResetting state and rotation animation
- Simplify reset button to static icon
- Remove animation-related CSS classes and keyframes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Map includePatterns -> include in URL parameters
- Map ignorePatterns -> ignore in URL parameters
- Fixes URL parameter reflection for include/ignore patterns

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@yamadashy yamadashy force-pushed the feature/website-url-query-parameters branch from 1e08cbb to 7289f20 Compare August 17, 2025 04:48
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 (4)
website/client/composables/usePackOptions.ts (1)

31-43: Make URL → options merge type-safe (avoid Record<string, unknown> cast).

The current assignment bypasses type safety. Use a typed key iteration to constrain values to PackOptions keys.

Apply:

-  // Apply URL parameters to initial options
-  for (const key of Object.keys(initialOptions)) {
-    if (key in urlParams && urlParams[key as keyof PackOptions] !== undefined) {
-      (initialOptions as Record<string, unknown>)[key] = urlParams[key as keyof PackOptions];
-    }
-  }
+  // Apply URL parameters to initial options (type-safe)
+  (Object.keys(initialOptions) as (keyof PackOptions)[]).forEach((key) => {
+    const val = urlParams[key];
+    if (val !== undefined) {
+      initialOptions[key] = val as PackOptions[typeof key];
+    }
+  });
website/client/utils/urlParams.ts (1)

23-27: Prefer 'format' over legacy 'style' when both are present.

Currently, style overrides format. For backward compatibility, format should take precedence.

-  // Style parameter (alternative to format for backward compatibility)
-  const style = urlParams.get('style');
-  if (style && ['xml', 'markdown', 'plain'].includes(style)) {
-    params.format = style as 'xml' | 'markdown' | 'plain';
-  }
+  // Style parameter (legacy alias for 'format'); prefer 'format' if both are provided
+  const style = urlParams.get('style');
+  if (!params.format && style && ['xml', 'markdown', 'plain'].includes(style)) {
+    params.format = style as 'xml' | 'markdown' | 'plain';
+  }
+  if (params.format && style && ['xml', 'markdown', 'plain'].includes(style)) {
+    // Optional: warn in dev
+    console.warn("Both 'format' and legacy 'style' URL parameters are present. Using 'format'.");
+  }
website/client/components/Home/TryIt.vue (2)

143-173: Simplify shouldShowReset logic (trim-aware string comparison).

The current logic is a bit convoluted and repeats comparisons. A simpler version is easier to read and maintain.

-const shouldShowReset = computed(() => {
-  // Don't show if pack hasn't been executed yet
-  if (!hasExecuted.value) {
-    return false;
-  }
-
-  // Show if there's input URL
-  if (inputUrl.value && inputUrl.value.trim() !== '') {
-    return true;
-  }
-
-  // Show if any pack option differs from default
-  for (const [key, value] of Object.entries(packOptions)) {
-    const defaultValue = DEFAULT_PACK_OPTIONS[key as keyof typeof DEFAULT_PACK_OPTIONS];
-    if (value !== defaultValue) {
-      // For string values, also check if they're not empty
-      if (typeof value === 'string' && typeof defaultValue === 'string') {
-        if (value.trim() !== defaultValue.trim()) {
-          return true;
-        }
-      } else if (value !== defaultValue) {
-        return true;
-      }
-    }
-  }
-
-  return false;
-});
+const shouldShowReset = computed(() => {
+  if (!hasExecuted.value) return false;
+  if (inputUrl.value && inputUrl.value.trim() !== '') return true;
+  for (const [key, value] of Object.entries(packOptions)) {
+    const def = DEFAULT_PACK_OPTIONS[key as keyof typeof DEFAULT_PACK_OPTIONS];
+    if (typeof value === 'string' && typeof def === 'string') {
+      if (value.trim() !== def.trim()) return true;
+    } else if (value !== def) {
+      return true;
+    }
+  }
+  return false;
+});

381-412: Use theme variables for tooltip colors (avoid hardcoded #333/white).

This keeps tooltips consistent across light/dark themes.

 .tooltip-content {
   position: absolute;
   bottom: 100%;
   left: 50%;
   transform: translateX(-50%);
   margin-bottom: 8px;
   padding: 8px 12px;
-  background: #333;
-  color: white;
+  background: var(--vp-c-bg-inverse, #333);
+  color: var(--vp-c-text-inverse-1, #fff);
   font-size: 0.875rem;
   white-space: nowrap;
   border-radius: 4px;
   opacity: 0;
   visibility: hidden;
   transition: opacity 0.2s, visibility 0.2s;
   z-index: 10;
 }
@@
 .tooltip-arrow {
   position: absolute;
   top: 100%;
   left: 50%;
   transform: translateX(-50%);
   border-width: 8px;
   border-style: solid;
-  border-color: #333 transparent transparent transparent;
+  border-color: var(--vp-c-bg-inverse, #333) transparent transparent transparent;
 }
🧹 Nitpick comments (5)
website/client/composables/usePackRequest.ts (1)

138-141: Remove duplicate re-exports from return object.

resetOptions and DEFAULT_PACK_OPTIONS are already included via spread (...packOptionsComposable). The duplicates are redundant.

-    // Pack option actions
-    resetOptions,
-    DEFAULT_PACK_OPTIONS,
website/client/utils/urlParams.ts (1)

63-104: Unify parse/update key mapping and fix type surface for updateUrlParameters.

  • updateUrlParameters accepts PackOptions keys, but parseUrlParameters reads include/ignore. This asymmetry forces callers to hand-roll mapping and weakens typing (e.g., TryIt.vue uses Record<string, unknown>).
  • Centralize the mapping logic inside updateUrlParameters and expose a typed UrlParamOptions that includes { include, ignore }.

This improves maintainability and prevents subtle bugs if new params are added.

-export function updateUrlParameters(options: Partial<PackOptions & { repo?: string }>): void {
+// Public type for updating URL params (keys as they appear in the URL)
+export type UrlParamOptions = Partial<
+  Pick<
+    PackOptions,
+    | 'format'
+    | 'removeComments'
+    | 'removeEmptyLines'
+    | 'showLineNumbers'
+    | 'fileSummary'
+    | 'directoryStructure'
+    | 'outputParsable'
+    | 'compress'
+  > & {
+    repo?: string;
+    include?: string; // URL key
+    ignore?: string;  // URL key
+    // Accept internal keys as well; they will be mapped below
+    includePatterns?: string;
+    ignorePatterns?: string;
+  }
+>;
+
+export function updateUrlParameters(options: UrlParamOptions): void {
   if (typeof window === 'undefined') {
     return;
   }
 
   const url = new URL(window.location.href);
   const params = url.searchParams;
 
   // Clear existing repomix-related parameters
-  const keysToRemove = [
+  const keysToRemove = [
     'repo',
     'format',
     'style',
     'include',
     'ignore',
     'removeComments',
     'removeEmptyLines',
     'showLineNumbers',
     'fileSummary',
     'directoryStructure',
     'outputParsable',
     'compress',
-  ];
+  ] as const;
 
   for (const key of keysToRemove) {
     params.delete(key);
   }
 
   // Add new parameters
-  for (const [key, value] of Object.entries(options)) {
+  const keyMap: Record<string, string> = {
+    includePatterns: 'include',
+    ignorePatterns: 'ignore',
+  };
+  for (const [rawKey, value] of Object.entries(options)) {
+    const key = keyMap[rawKey] ?? rawKey;
     if (value !== undefined && value !== null) {
       if (typeof value === 'boolean') {
         params.set(key, value.toString());
       } else if (typeof value === 'string' && value.trim() !== '') {
         params.set(key, value.trim());
       }
     }
   }
 
   // Update URL without reloading the page
   window.history.replaceState({}, '', url.toString());
 }

Optionally, consider hoisting the list of boolean keys/keysToRemove as module-level constants to be reused by both parseUrlParameters and updateUrlParameters for easier maintenance.

website/client/components/Home/TryIt.vue (3)

57-72: Add accessible label to reset button.

The button has only an icon; add an aria-label for screen readers.

-            <button
+            <button
               class="reset-button"
               @click="handleReset"
               type="button"
+              aria-label="Reset all options to default values"
             >
               <RotateCcw :size="20" />
             </button>

175-206: Let urlParams.ts handle key mapping; use typed UrlParamOptions.

Mapping includePatterns/ignorePatterns in the component scatters responsibility and forces a weakly-typed Record<string, unknown>. Move the mapping into updateUrlParameters (see urlParams.ts comment) and use a typed UrlParamOptions here.

-  const urlParamsToUpdate: Record<string, unknown> = {};
+  const urlParamsToUpdate: import('../../utils/urlParams').UrlParamOptions = {};
@@
-  // Only add pack options that differ from defaults
+  // Only add pack options that differ from defaults
   for (const [key, value] of Object.entries(packOptions)) {
     const defaultValue = DEFAULT_PACK_OPTIONS[key as keyof typeof DEFAULT_PACK_OPTIONS];
     if (value !== defaultValue) {
       // For string values, also check if they're not empty
       if (typeof value === 'string' && value.trim() === '' && defaultValue === '') {
         continue; // Skip empty strings that match default empty strings
       }
-      
-      // Map internal option names to URL parameter names
-      let urlParamKey = key;
-      if (key === 'includePatterns') {
-        urlParamKey = 'include';
-      } else if (key === 'ignorePatterns') {
-        urlParamKey = 'ignore';
-      }
-      
-      urlParamsToUpdate[urlParamKey] = value;
+      // Pass internal key; updateUrlParameters will map include*/ignore* to URL keys
+      // @ts-expect-error: type narrowing for dynamic key assignment
+      (urlParamsToUpdate as any)[key] = value;
     }
   }
 
   updateUrlParameters(urlParamsToUpdate);

216-223: Consider clearing previous result on reset (optional).

If the intent is a full reset, also reset result/error/hasExecuted. Reuse resetRequest from the composable.

-  resetOptions();
-  inputUrl.value = '';
+  resetOptions();
+  inputUrl.value = '';
+  // Also clear previous request state
+  resetRequest();

And include resetRequest in the destructured composable return:

-  submitRequest,
-  resetOptions,
+  submitRequest,
+  resetOptions,
+  resetRequest,
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5cd37d6 and 7289f20.

📒 Files selected for processing (5)
  • website/client/components/Home/TryIt.vue (8 hunks)
  • website/client/components/Home/TryItPackOptions.vue (2 hunks)
  • website/client/composables/usePackOptions.ts (3 hunks)
  • website/client/composables/usePackRequest.ts (2 hunks)
  • website/client/utils/urlParams.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
website/client/utils/urlParams.ts (1)
website/client/composables/usePackOptions.ts (1)
  • PackOptions (4-15)
website/client/composables/usePackOptions.ts (1)
website/client/utils/urlParams.ts (1)
  • parseUrlParameters (3-61)
website/client/composables/usePackRequest.ts (2)
website/client/composables/usePackOptions.ts (1)
  • usePackOptions (30-71)
website/client/utils/urlParams.ts (1)
  • parseUrlParameters (3-61)
🔇 Additional comments (4)
website/client/components/Home/TryItPackOptions.vue (1)

147-147: Whitespace-only change — LGTM

Only blank lines were added. No functional impact.

Also applies to: 440-440

website/client/composables/usePackRequest.ts (1)

18-18: Nice touch: prefill from URL params.

Seeding inputUrl from urlParams.repo improves shareability/bookmarking UX.

website/client/utils/urlParams.ts (1)

91-100: All calls to updateUrlParameters are safe

I’ve checked the entire codebase and found only two invocations of updateUrlParameters (both in TryIt.vue):

  • In handleSubmit(), where includePatterns and ignorePatterns are explicitly remapped to include and ignore before calling.
  • In handleReset(), where an empty object is passed to clear all URL params.

No other callers pass raw internal keys, so there’s no risk of unrecognised URL parameters being emitted. No changes needed.

website/client/components/Home/TryIt.vue (1)

224-235: Auto-submit on valid repo URL — nice UX.

Parsing URL params on mount and triggering submit when repo is valid makes deep links actionable.

yamadashy and others added 3 commits August 17, 2025 14:38
- Simplify shouldShowReset string comparison logic
- Use CSS variables for tooltip colors instead of hardcoded values
- Improve type safety in URL parameter parsing with proper type casting
- Remove redundant conditional in pack option comparison

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Extract URL parameter constants to eliminate duplication
- Create centralized key mapping for include/ignore patterns
- Extract shouldShowReset logic to reusable utility function
- Add URL parameter validation with length limits and format checks
- Improve error handling for URL operations with try-catch
- Add proper return types and error reporting for updateUrlParameters
- Enhance auto-execution error handling with async/await

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace 'any' with 'unknown' for better type safety
- Convert forEach to for...of loop for better performance
- Use proper type casting with unknown intermediate step
- Revert tooltip colors back to original styling (#333 background, white text)
- Fix all biome lint warnings

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@yamadashy yamadashy requested a review from Copilot August 17, 2025 07:49
@yamadashy
Copy link
Owner Author

/gemini review

@yamadashy
Copy link
Owner Author

@coderabbitai review

@yamadashy
Copy link
Owner Author

@claude review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 17, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@claude
Copy link
Contributor

claude bot commented Aug 17, 2025

Claude finished @yamadashy's task —— View job


Code Review: URL Query Parameter Support

Review Tasks

  • Read repository guidelines and setup
  • Analyze new URL parameter utility (urlParams.ts)
  • Review Vue component changes (TryIt.vue, TryItPackOptions.vue)
  • Review composable modifications (usePackOptions.ts, usePackRequest.ts)
  • Assess overall architecture and design decisions
  • Check for potential bugs and security issues
  • Provide specific feedback and recommendations

Code Quality Analysis

✅ Strengths

Architecture & Design:

  • Clean separation of concerns with dedicated urlParams.ts utility
  • Proper use of Vue 3 Composition API patterns
  • Smart URL parameter filtering to exclude default values, keeping URLs clean
  • Backwards compatibility with style parameter (aliased to format)
  • Non-intrusive URL updates using replaceState instead of pushState

Implementation Quality:

  • Robust boolean parameter parsing accepting multiple formats (true, 1, yes, on)
  • Proper SSR safety checks with typeof window === 'undefined'
  • Auto-execution when valid repo parameter is present
  • Clean reset functionality that clears both state and URL

🔍 Areas for Improvement

1. Type Safety in URL Parameter Parsing (usePackOptions.ts:36-39)

// Current approach uses type casting which bypasses type safety
for (const key of Object.keys(initialOptions) as Array<keyof PackOptions>) {
  if (key in urlParams && urlParams[key] !== undefined) {
    initialOptions[key] = urlParams[key] as PackOptions[typeof key];
  }
}

Suggestion: The current type assertion is acceptable, but consider adding runtime validation for critical parameters like format to ensure only valid values are accepted.

2. Potential Style vs Format Conflict (urlParams.ts:105-109)

// Style parameter (alternative to format for backward compatibility)
const style = urlParams.get('style');
if (style && (VALID_FORMATS as readonly string[]).includes(style)) {
  params.format = style as (typeof VALID_FORMATS)[number];
}

Issue: If both format and style are present, style overwrites format. Consider giving format priority for consistency.

3. URL Length Validation (urlParams.ts:30-57)
The validation function is good but only warns rather than prevents long URLs. Consider:

// In updateUrlParameters, check before setting
const validation = validateUrlParameters(options);
if (!validation.isValid) {
  return { success: false, error: validation.errors.join(', ') };
}

4. Reset Button Logic Complexity (TryIt.vue:144-156)
The logic using hasNonDefaultValues utility is clean, but the type casting could be improved:

// Instead of casting to unknown, define a proper interface
return hasNonDefaultValues(
  inputUrl.value,
  packOptions,
  DEFAULT_PACK_OPTIONS,
);

🐛 Potential Issues

1. Missing Error Handling (TryIt.vue:206-212)
Auto-execution on mount could fail, but errors aren't handled gracefully:

nextTick(async () => {
  try {
    await handleSubmit();
  } catch (error) {
    console.error('Auto-execution failed:', error);
    // Consider showing user-friendly error message
  }
});

Status: ✅ Already implemented - good error handling present.

2. URL Parameter Consistency
The implementation properly maps internal option names (includePatterns, ignorePatterns) to URL parameter names (include, ignore) both in parsing and updating.

💡 Enhancement Suggestions

1. Add Accessibility (TryIt.vue:62-67)
The reset button lacks an accessible label:

<button
  class="reset-button"
  @click="handleReset"
  type="button"
  aria-label="Reset all options to default values"
>
  <RotateCcw :size="20" />
</button>

2. Theme-Aware Tooltip Colors (TryIt.vue:367-391)
Hardcoded colors (#333, white) don't adapt to theme changes:

.tooltip-content {
  background: var(--vp-c-bg-inverse, #333);
  color: var(--vp-c-text-inverse-1, white);
}

.tooltip-arrow {
  border-color: var(--vp-c-bg-inverse, #333) transparent transparent transparent;
}

3. Debounced URL Updates
For better UX when users change multiple options quickly, consider debouncing URL updates.

Security Assessment

No security issues detected

  • Proper input sanitization with .trim()
  • No XSS vulnerabilities in URL parameter handling
  • Safe use of window.history.replaceState
  • URL length validation prevents potential issues

Performance Considerations

  • ✅ Minimal performance impact from URL parsing/updating
  • ✅ SSR-safe implementation with proper window checks
  • ✅ Efficient parameter filtering logic

Architecture Assessment

Well-structured implementation

  • Clear separation between URL utilities and component logic
  • Proper Vue composable patterns
  • Maintains existing component interfaces
  • Clean integration with existing state management
  • Good use of TypeScript for type safety

Specific Code Comments

File: urlParams.ts

  • Excellent utility design with proper validation and error handling
  • Good use of constants to avoid magic strings
  • Comprehensive boolean parameter parsing

File: TryIt.vue

  • Clean integration of URL parameter functionality
  • Smart reset button visibility logic
  • Proper handling of auto-execution on mount

File: usePackOptions.ts & usePackRequest.ts

  • Good composable design maintaining single responsibility
  • Proper initialization from URL parameters
  • Clean state management

Final Recommendation

This is a solid, well-implemented feature that successfully addresses the requirements. The code follows Vue 3 best practices, maintains good separation of concerns, and provides excellent user experience through URL parameter support.

Approval recommended

The suggestions above are primarily for further enhancement and robustness rather than critical issues. The implementation demonstrates good understanding of Vue 3 patterns, TypeScript usage, and web standards.


Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements URL query string parameter support for the Repomix web interface, allowing users to bookmark or share links with preset options that automatically load configurations.

  • Adds URL parameter parsing and validation utilities for form configurations
  • Initializes form options from URL parameters on page load
  • Updates URL parameters when submitting requests to maintain state in the browser

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
website/client/utils/urlParams.ts New utility module for parsing, validating, and updating URL query parameters
website/client/composables/usePackRequest.ts Integrates URL parameter parsing to initialize repository URL from query string
website/client/composables/usePackOptions.ts Applies URL parameters to pack options during initialization
website/client/components/Home/TryItPackOptions.vue Minor formatting changes (whitespace additions)
website/client/components/Home/TryIt.vue Adds reset functionality, URL parameter synchronization, and tooltip UI elements

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for URL query string parameters, allowing users to share and bookmark configurations. The implementation is well-structured, with new utility functions for parsing and updating URL parameters, and updates to Vue components and composables to integrate this functionality. My review includes a couple of suggestions to improve code correctness and maintainability. One is a high-severity fix for a type-related issue in parameter validation, and the other is a medium-severity suggestion to simplify redundant logic.

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: 2

♻️ Duplicate comments (2)
website/client/utils/urlParams.ts (2)

99-110: Prefer 'format' over 'style' when both are present; optionally warn and normalize case

Currently, 'style' silently overrides 'format'. Prefer 'format' for clarity and backward-compatibility, warn if both present, and accept case-insensitive values.

-  // Format parameter
-  const format = urlParams.get('format');
-  if (format && (VALID_FORMATS as readonly string[]).includes(format)) {
-    params.format = format as (typeof VALID_FORMATS)[number];
-  }
-
-  // Style parameter (alternative to format for backward compatibility)
-  const style = urlParams.get('style');
-  if (style && (VALID_FORMATS as readonly string[]).includes(style)) {
-    params.format = style as (typeof VALID_FORMATS)[number];
-  }
+  // Format (preferred) and style (legacy alias) parameters
+  const rawFormat = urlParams.get('format');
+  const rawStyle = urlParams.get('style');
+  const normFormat = rawFormat?.toLowerCase() ?? null;
+  const normStyle = rawStyle?.toLowerCase() ?? null;
+  const isValid = (v: string | null) => !!v && (VALID_FORMATS as readonly string[]).includes(v);
+
+  if (isValid(normFormat)) {
+    params.format = normFormat as (typeof VALID_FORMATS)[number];
+    if (isValid(normStyle) && normStyle !== normFormat) {
+      console.warn("Both 'format' and 'style' URL parameters are present. 'format' takes precedence.");
+    }
+  } else if (isValid(normStyle)) {
+    params.format = normStyle as (typeof VALID_FORMATS)[number];
+  }

154-158: Derive keys-to-clear from mappings to avoid maintenance drift

Hardcoding the list is easy to forget as options evolve. Build it from KEY_MAPPING + BOOLEAN_PARAMS.

-    // Clear existing repomix-related parameters
-    for (const key of URL_PARAM_KEYS) {
-      params.delete(key);
-    }
+    // Clear existing repomix-related parameters (derived)
+    const keysToClear = new Set<string>([
+      'repo',
+      'format',
+      'style',
+      ...Object.values(KEY_MAPPING),
+      ...BOOLEAN_PARAMS,
+    ]);
+    for (const key of keysToClear) {
+      params.delete(key);
+    }
🧹 Nitpick comments (3)
website/client/utils/urlParams.ts (3)

60-84: Optional: compare only known option keys to defaults

Iterating packOptions can yield true if unknown keys are present (e.g., repo). Safer to diff only keys from defaultOptions to avoid false positives.

-  for (const [key, value] of Object.entries(packOptions)) {
-    const defaultValue = defaultOptions[key];
+  for (const key of Object.keys(defaultOptions)) {
+    const value = (packOptions as Record<string, unknown>)[key];
+    const defaultValue = (defaultOptions as Record<string, unknown>)[key];
     if (typeof value === 'string' && typeof defaultValue === 'string') {
       if (value.trim() !== defaultValue.trim()) {
         return true;
       }
     } else if (value !== defaultValue) {
       return true;
     }
   }

111-121: DRY parsing of include/ignore via KEY_MAPPING

Use KEY_MAPPING to avoid duplicating knowledge and reduce drift.

-  // Include patterns
-  const include = urlParams.get('include');
-  if (include) {
-    params.includePatterns = include;
-  }
-
-  // Ignore patterns
-  const ignore = urlParams.get('ignore');
-  if (ignore) {
-    params.ignorePatterns = ignore;
-  }
+  // Include/Ignore patterns via mapping
+  for (const [internalKey, urlKey] of Object.entries(KEY_MAPPING)) {
+    const v = urlParams.get(urlKey);
+    if (v) {
+      (params as Record<string, unknown>)[internalKey] = v;
+    }
+  }

171-173: Preserve existing history.state when replacing URL

Some apps rely on history.state. Preserve it instead of replacing with an empty object.

-    window.history.replaceState({}, '', url.toString());
+    window.history.replaceState(window.history.state, '', url.toString());
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7289f20 and 853be1f.

📒 Files selected for processing (3)
  • website/client/components/Home/TryIt.vue (8 hunks)
  • website/client/composables/usePackOptions.ts (3 hunks)
  • website/client/utils/urlParams.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/client/components/Home/TryIt.vue
  • website/client/composables/usePackOptions.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
website/client/utils/urlParams.ts (1)
website/client/composables/usePackOptions.ts (1)
  • PackOptions (4-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
website/client/utils/urlParams.ts (3)

18-27: Good fix: explicit key mapping resolves include/ignore mismatch

The KEY_MAPPING + getUrlParamKey abstraction cleanly addresses the earlier mismatch between internal keys and URL param names. This removes a class of bugs and improves maintainability.


85-90: SSR guard is correct

Returning an empty object when window is unavailable prevents SSR crashes and keeps the helper pure for server contexts.


124-130: Boolean parsing is tolerant and explicit

Accepting multiple truthy values and leaving others as false is practical for URL consumption. This is a solid, predictable approach.

- Add console warning when both 'format' and 'style' are specified
- Prefer 'format' parameter over 'style' for consistency
- Improve user experience by clearly indicating parameter precedence

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
yamadashy and others added 2 commits August 17, 2025 17:20
- Fix type error in validateUrlParameters format validation
- Add proper error handling for URL length limit violations
- Add comprehensive JSDoc documentation for public functions
- Improve user experience with better error reporting

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Owner Author

@yamadashy yamadashy left a comment

Choose a reason for hiding this comment

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

Review Comment Responses

✅ All Major Issues Addressed

@copilot - Hardcoded parameter lists: Fixed with centralized constants (URL_PARAM_KEYS, BOOLEAN_PARAMS, VALID_FORMATS)

@copilot - Type safety bypass: Fixed with for...of loops and proper type casting

@copilot - Complex shouldShowReset logic: Extracted to hasNonDefaultValues() utility function

@gemini-code-assist - URL parameter key mismatch: Fixed with KEY_MAPPING and centralized mapping

@gemini-code-assist - String comparison bug: Simplified logic to handle trimming correctly

@copilot - Format/style conflict: Added warning when both parameters present

🎯 Additional Improvements

  • URL length validation (2000 char limit)
  • Enhanced error handling with user-friendly messages
  • JSDoc documentation for public functions
  • Improved type safety throughout

🎨 User Preference Maintained

  • Tooltip colors kept as #333/white per user request

Thanks for the thorough review! All critical suggestions have been implemented.

@yamadashy yamadashy merged commit 217baa7 into main Aug 17, 2025
52 checks passed
@yamadashy yamadashy deleted the feature/website-url-query-parameters branch August 17, 2025 09:03
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.

2 participants