Skip to content

feat(DataMapper): Add XSLT file recovery and rename functionality#3214

Draft
pvillant wants to merge 1 commit into
KaotoIO:mainfrom
pvillant:feat/datamapper-xslt-name-edit
Draft

feat(DataMapper): Add XSLT file recovery and rename functionality#3214
pvillant wants to merge 1 commit into
KaotoIO:mainfrom
pvillant:feat/datamapper-xslt-name-edit

Conversation

@pvillant
Copy link
Copy Markdown
Contributor

@pvillant pvillant commented May 14, 2026

Resolves: #1847

Summary

Enhanced DataMapper to automatically recover missing XSLT files and added the ability to rename XSLT documents directly from the launcher interface.

Changes

1. XSLT File Recovery (DataMapper.tsx)

  • Added automatic creation of empty XSLT files when metadata exists but the file is missing
  • Ensures DataMapper remains functional even if XSLT files are accidentally deleted
  • Users can start fresh with empty mappings when files are lost

2. XSLT Document Renaming (DataMapperLauncher.tsx)

  • Made the XSLT document name field editable (previously read-only)
  • Added real-time validation for filename format (must end with .xsl and be a valid filename)
  • Implemented file renaming with automatic content migration:
    • Copies content from old file to new file
    • Updates metadata with new path
    • Updates step configuration with new filename
    • Deletes old file after successful migration
  • Added file existence check to conditionally show the document field
  • Disabled "Configure" button when filename is invalid

3. Service Layer Enhancements

4. Test Coverage

  • Added tests for XSLT file recovery scenarios
  • Added tests for XSLT path update functionality
  • Added tests for XSLT filename update functionality

Benefits

  • Resilience: DataMapper automatically recovers from missing XSLT files
  • Flexibility: Users can rename XSLT documents without manual file operations
  • User Experience: Clear validation feedback and disabled states prevent errors
  • Data Integrity: Atomic rename operations ensure no data loss during file renaming

Summary by CodeRabbit

  • New Features

    • XSLT document names are now editable in the DataMapper configuration, enabling users to rename files directly from the launcher interface.
    • Automatic creation of empty XSLT files when missing during initialization ensures smooth workflow.
  • Bug Fixes

    • Improved handling of missing XSLT resources with proper validation and error messaging.
  • Tests

    • Expanded test coverage for DataMapper workflows and file management operations.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

📝 Walkthrough

Walkthrough

This PR implements XSLT file renaming from the DataMapper step configuration form. It adds service methods to update metadata and step references, ensures XSLT files exist at initialization, and provides a complete rename workflow in the launcher UI with validation and file management.

Changes

XSLT file rename and edit workflow

Layer / File(s) Summary
Service methods for XSLT path and filename updates
packages/ui/src/services/datamapper-metadata.service.ts, packages/ui/src/services/datamapper-metadata.service.test.ts, packages/ui/src/services/datamapper-step.service.ts, packages/ui/src/services/datamapper-step.service.test.ts
DataMapperMetadataService.updateXsltPath updates the stored XSLT resource path in metadata. DataMapperStepService.updateXsltFileName updates the step's to.uri to reference the new XSLT filename and regenerates source code. Both methods are fully tested.
DataMapper XSLT initialization
packages/ui/src/components/DataMapper/DataMapper.tsx, packages/ui/src/components/DataMapper/DataMapper.test.tsx
DataMapper now checks whether the configured XSLT resource has content during initialization and, if missing, persists EMPTY_XSL before continuing. Two tests verify the behavior when XSLT is missing and when it already exists.
DataMapperLauncher edit and rename workflow
packages/ui/src/components/DataMapper/DataMapperLauncher.tsx, packages/ui/src/components/DataMapper/DataMapperLauncher.test.tsx
DataMapperLauncher now renders an editable XSLT document name field (shown only when the file exists), validates the filename against a .xsl pattern, and implements a rename workflow: load metadata, fetch old content, save to new resource name, update metadata path and step filename, delete old resource, then navigate to the editor. Tests cover file existence detection, filename validation rules, button state, successful rename, graceful no-op cases, and edge scenarios.

Sequence Diagram

sequenceDiagram
  participant User
  participant LauncherUI
  participant MetadataAPI
  participant StepService
  participant ResourceAPI
  participant Router
  User->>LauncherUI: enter new XSLT filename
  LauncherUI->>LauncherUI: validate filename (\.xsl pattern)
  User->>LauncherUI: click Configure button
  LauncherUI->>MetadataAPI: load metadata entry
  LauncherUI->>ResourceAPI: fetch old XSLT content
  LauncherUI->>ResourceAPI: save content to new resource name
  LauncherUI->>MetadataAPI: updateXsltPath (new path)
  LauncherUI->>StepService: updateXsltFileName (new filename)
  LauncherUI->>ResourceAPI: delete old resource
  LauncherUI->>Router: navigate to DataMapper route
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • igarashitm
  • mmelko

Poem

🐰 A rabbit hops through the XSLT maze,
Renaming files in so many ways,
Service by service, step by step so fine,
Metadata updates in perfect line,
The DataMapper dances, validation's bright—
One fluffy feature done just right! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: implementing XSLT file recovery when missing and enabling XSLT document renaming in the launcher.
Linked Issues check ✅ Passed The PR implements the core requirement from #1847 to allow changing XSLT file names from the DataMapper config form and updates metadata accordingly. However, it does not address the collision handling question raised in the issue.
Out of Scope Changes check ✅ Passed The PR includes an additional XSLT file recovery feature (auto-creating empty XSLT files when missing) that extends beyond the core rename requirement from #1847, though it relates to XSLT resilience.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.27%. Comparing base (30f1e35) to head (1c8ad38).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3214      +/-   ##
==========================================
+ Coverage   92.25%   92.27%   +0.01%     
==========================================
  Files         636      636              
  Lines       24614    24673      +59     
  Branches     5639     5652      +13     
==========================================
+ Hits        22707    22766      +59     
  Misses       1905     1905              
  Partials        2        2              

☔ 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.

@pvillant pvillant marked this pull request as ready for review May 14, 2026 11:43
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ui/src/components/DataMapper/DataMapper.tsx`:
- Around line 61-63: Change the recovery condition so an existing empty XSLT
file isn't overwritten: in DataMapper.tsx check specifically for xsltContent ===
undefined (not a falsy check) before calling
ctx.saveResourceContent(meta.xsltPath, EMPTY_XSL), so only truly missing
resources are initialized; keep references to xsltContent,
ctx.saveResourceContent, meta.xsltPath and EMPTY_XSL to locate the code.

In `@packages/ui/src/components/DataMapper/DataMapperLauncher.test.tsx`:
- Around line 111-116: The test's jest.spyOn(console, 'error') mock
implementation calls console.error inside itself causing infinite recursion; fix
by capturing the original console.error before mocking (e.g., const
originalConsoleError = console.error), then replace the mockImplementation on
the jest.spyOn in DataMapperLauncher.test.tsx to check the 'not wrapped in act'
substring and return for those, otherwise call originalConsoleError with the
original arguments; ensure any teardown restores the mock if needed.

In `@packages/ui/src/components/DataMapper/DataMapperLauncher.tsx`:
- Around line 125-129: The rename flow unconditionally writes to newPath which
can silently overwrite an existing mapping file; before calling
metadata.saveResourceContent(newPath, content) check whether the target exists
(e.g., via metadata.hasResource/newResourceExists/getResource or equivalent) and
if it does, abort the operation (throw an error or return a user-facing
validation failure) instead of writing; only proceed to call
metadata.saveResourceContent(newPath, content),
DataMapperMetadataService.updateXsltPath(metadata, metadataId, meta, newPath),
DataMapperStepService.updateXsltFileName(vizNode, newPath, entitiesContext), and
metadata.deleteResource(oldPath) when the path is confirmed absent (or after
safely generating a unique non-conflicting newPath).

In `@packages/ui/src/services/datamapper-step.service.ts`:
- Around line 129-131: The code assumes xsltStep.to is an object and directly
sets xsltStep.to.uri which can throw if to is a string; mirror the defensive
pattern used in setUseJsonBody by checking that xsltStep.to exists and is an
object (e.g., typeof xsltStep.to === 'object' && xsltStep.to !== null) before
assigning xsltStep.to.uri = `${XSLT_COMPONENT_NAME}:${newFileName}`, then call
vizNode.updateModel(model) as before; ensure you do not mutate non-object to
values and handle the absent/invalid case appropriately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 54292916-243d-4bad-bc18-f7d4ffeceb44

📥 Commits

Reviewing files that changed from the base of the PR and between 30f1e35 and 1c8ad38.

📒 Files selected for processing (8)
  • packages/ui/src/components/DataMapper/DataMapper.test.tsx
  • packages/ui/src/components/DataMapper/DataMapper.tsx
  • packages/ui/src/components/DataMapper/DataMapperLauncher.test.tsx
  • packages/ui/src/components/DataMapper/DataMapperLauncher.tsx
  • packages/ui/src/services/datamapper-metadata.service.test.ts
  • packages/ui/src/services/datamapper-metadata.service.ts
  • packages/ui/src/services/datamapper-step.service.test.ts
  • packages/ui/src/services/datamapper-step.service.ts

Comment on lines +61 to +63
if (!xsltContent) {
await ctx.saveResourceContent(meta.xsltPath, EMPTY_XSL);
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 14, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Only recover when the XSLT resource is actually missing

Line 61 uses a falsy check, so an existing empty file ('') is treated as missing and gets overwritten. Recovery should trigger only when content is undefined.

Proposed fix
-        if (!xsltContent) {
+        if (xsltContent === undefined) {
           await ctx.saveResourceContent(meta.xsltPath, EMPTY_XSL);
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!xsltContent) {
await ctx.saveResourceContent(meta.xsltPath, EMPTY_XSL);
}
if (xsltContent === undefined) {
await ctx.saveResourceContent(meta.xsltPath, EMPTY_XSL);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/DataMapper/DataMapper.tsx` around lines 61 - 63,
Change the recovery condition so an existing empty XSLT file isn't overwritten:
in DataMapper.tsx check specifically for xsltContent === undefined (not a falsy
check) before calling ctx.saveResourceContent(meta.xsltPath, EMPTY_XSL), so only
truly missing resources are initialized; keep references to xsltContent,
ctx.saveResourceContent, meta.xsltPath and EMPTY_XSL to locate the code.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IMO empty XSLT file is anyway invalid and we would want to initialize with the template

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@igarashitm, that's a fair point. An empty XSLT file ('') is invalid XML and would break the DataMapper just as much as a missing file, so overwriting it with EMPTY_XSL (the baseline valid template) is the right recovery behaviour. The existing falsy check correctly handles both cases. I'll withdraw the suggestion.


✏️ Learnings added
Learnt from: igarashitm
Repo: KaotoIO/kaoto PR: 3214
File: packages/ui/src/components/DataMapper/DataMapper.tsx:61-63
Timestamp: 2026-05-14T13:59:40.259Z
Learning: In KaotoIO/kaoto DataMapper (`packages/ui/src/components/DataMapper/DataMapper.tsx`), the XSLT recovery check intentionally uses a falsy guard (`!xsltContent`) rather than `=== undefined`. An empty XSLT string is considered equally invalid as a missing file, so both cases should be recovered by writing `EMPTY_XSL` (the baseline valid template) via `ctx.saveResourceContent`. Do not flag this as a bug or suggest changing to a strict `undefined` check.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: PVinaches
Repo: KaotoIO/kaoto PR: 3025
File: packages/ui/src/components/ResizableSplitPanels/SplitPanel.tsx:3-25
Timestamp: 2026-03-10T14:42:13.009Z
Learning: In KaotoIO/kaoto, the UI package is migrating from PatternFly to Carbon (carbon/react, carbon/icons-react). During this migration, both design systems may coexist in packages/ui. Do not flag or block Carbon imports as violations within packages/ui/src/components. Mixing Carbon and PatternFly is expected until the migration is complete. When reviewing files in packages/ui, allow Carbon imports in TSX components; continue to flag true PatternFly-only conventions in other areas or outside this migration scope.

Copy link
Copy Markdown
Contributor Author

@pvillant pvillant May 14, 2026

Choose a reason for hiding this comment

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

Still need to adjust the code here due to Sonar issue. Something like:

if (xsltContent) {
         return;
 }
  await ctx.saveResourceContent(meta.xsltPath, EMPTY_XSL);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines +111 to +116
jest.spyOn(console, 'error').mockImplementation((message) => {
if (typeof message === 'string' && message.includes('not wrapped in act')) {
return;
}
console.error(message);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid recursive console.error mock implementation

The mocked console.error calls console.error again on Line 115, which re-enters the same mock and can recurse indefinitely for non-act() messages.

Proposed fix
   beforeEach(() => {
     jest.clearAllMocks();
+    const originalConsoleError = console.error;
     // Suppress act() warnings for async useEffect in component
     jest.spyOn(console, 'error').mockImplementation((message) => {
       if (typeof message === 'string' && message.includes('not wrapped in act')) {
         return;
       }
-      console.error(message);
+      originalConsoleError(message);
     });
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jest.spyOn(console, 'error').mockImplementation((message) => {
if (typeof message === 'string' && message.includes('not wrapped in act')) {
return;
}
console.error(message);
});
beforeEach(() => {
jest.clearAllMocks();
const originalConsoleError = console.error;
// Suppress act() warnings for async useEffect in component
jest.spyOn(console, 'error').mockImplementation((message) => {
if (typeof message === 'string' && message.includes('not wrapped in act')) {
return;
}
originalConsoleError(message);
});
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/DataMapper/DataMapperLauncher.test.tsx` around
lines 111 - 116, The test's jest.spyOn(console, 'error') mock implementation
calls console.error inside itself causing infinite recursion; fix by capturing
the original console.error before mocking (e.g., const originalConsoleError =
console.error), then replace the mockImplementation on the jest.spyOn in
DataMapperLauncher.test.tsx to check the 'not wrapped in act' substring and
return for those, otherwise call originalConsoleError with the original
arguments; ensure any teardown restores the mock if needed.

Comment on lines +125 to +129
await metadata.saveResourceContent(newPath, content);
await DataMapperMetadataService.updateXsltPath(metadata, metadataId, meta, newPath);
DataMapperStepService.updateXsltFileName(vizNode, newPath, entitiesContext);
await metadata.deleteResource(oldPath);
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 14, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent overwrite when the target XSLT filename already exists

The rename flow writes to newPath unconditionally on Line 125. If that file already exists, this can overwrite another mapping file silently.

Proposed fix
       if (meta) {
         const content = await metadata.getResourceContent(oldPath);
         if (content !== undefined) {
+          const targetContent = await metadata.getResourceContent(newPath);
+          if (targetContent !== undefined) {
+            // TODO: surface a user-facing error/notification
+            return;
+          }
           await metadata.saveResourceContent(newPath, content);
           await DataMapperMetadataService.updateXsltPath(metadata, metadataId, meta, newPath);
           DataMapperStepService.updateXsltFileName(vizNode, newPath, entitiesContext);
           await metadata.deleteResource(oldPath);
         }
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/DataMapper/DataMapperLauncher.tsx` around lines
125 - 129, The rename flow unconditionally writes to newPath which can silently
overwrite an existing mapping file; before calling
metadata.saveResourceContent(newPath, content) check whether the target exists
(e.g., via metadata.hasResource/newResourceExists/getResource or equivalent) and
if it does, abort the operation (throw an error or return a user-facing
validation failure) instead of writing; only proceed to call
metadata.saveResourceContent(newPath, content),
DataMapperMetadataService.updateXsltPath(metadata, metadataId, meta, newPath),
DataMapperStepService.updateXsltFileName(vizNode, newPath, entitiesContext), and
metadata.deleteResource(oldPath) when the path is confirmed absent (or after
safely generating a unique non-conflicting newPath).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@igarashitm WDYT, is this a valid point?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes this is a valid point, I wonder if we can use something like "inline edit" here https://www.patternfly.org/components/inline-edit#single-inline-edit-active
And disable the "save" button when the file already exists with showing an error message - if api.getResourceContent() isn't fast enough for that validation, we could think about adding api.isResourceExist()

Comment on lines +129 to +131
if (xsltStep?.to) {
xsltStep.to.uri = `${XSLT_COMPONENT_NAME}:${newFileName}`;
vizNode.updateModel(model);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard xsltStep.to shape before writing uri

Line 130 can throw when to is present but not an object (e.g., string form). Please mirror the defensive check used in setUseJsonBody.

Proposed fix
   const model = vizNode.getNodeDefinition();
   const xsltStep = (model.steps as ProcessorDefinition[]).find(isXSLTComponent);
-  if (xsltStep?.to) {
+  if (xsltStep?.to && typeof xsltStep.to === 'object') {
     xsltStep.to.uri = `${XSLT_COMPONENT_NAME}:${newFileName}`;
     vizNode.updateModel(model);
     entitiesContext.updateSourceCodeFromEntities();
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (xsltStep?.to) {
xsltStep.to.uri = `${XSLT_COMPONENT_NAME}:${newFileName}`;
vizNode.updateModel(model);
const model = vizNode.getNodeDefinition();
const xsltStep = (model.steps as ProcessorDefinition[]).find(isXSLTComponent);
if (xsltStep?.to && typeof xsltStep.to === 'object') {
xsltStep.to.uri = `${XSLT_COMPONENT_NAME}:${newFileName}`;
vizNode.updateModel(model);
entitiesContext.updateSourceCodeFromEntities();
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/services/datamapper-step.service.ts` around lines 129 - 131,
The code assumes xsltStep.to is an object and directly sets xsltStep.to.uri
which can throw if to is a string; mirror the defensive pattern used in
setUseJsonBody by checking that xsltStep.to exists and is an object (e.g.,
typeof xsltStep.to === 'object' && xsltStep.to !== null) before assigning
xsltStep.to.uri = `${XSLT_COMPONENT_NAME}:${newFileName}`, then call
vizNode.updateModel(model) as before; ensure you do not mutate non-object to
values and handle the absent/invalid case appropriately.

@pvillant pvillant marked this pull request as draft May 14, 2026 12:48
checkFile();
}, [xsltDocumentName, metadata]);

useEffect(() => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This useEffect() could be removed by [localXsltDocumentName, setLocalXsltDocumentName] = useState<string>(xsltDocumentName), no?

* - disallow invalid filename characters
*/
// eslint-disable-next-line no-control-regex
const xsltFileNameRegex = /^(?!\.)([^<>:"/\\|?*\x00-\x1F]+)\.(xsl)$/i;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be moved up and make it module level const to avoid regex generation on every function call

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.

Allow changing the XSLT file name

2 participants