Skip to content

Conversation

Golddirio
Copy link

What is the purpose of this pull request?

  • Documentation update
  • Bug fix
  • Feature addition or enhancement
  • Code maintenance
  • DevOps
  • Improve developer experience
  • Others, please explain:

Fixes #2688

Overview of changes:
Popover error messages are placed in the content position which is consistent right now.

Anything you'd like to highlight/discuss:
Now the error messages are shown below:
Screenshot 2025-07-28 210239
Screenshot 2025-07-28 210244

Testing instructions:
NA

Proposed commit message: (wrap lines at 72 characters)
Fix the inconsistency in positions of popover error messages


Checklist: ☑️

  • Updated the documentation for feature additions and enhancements
  • Added tests for bug fixes or features
  • Linked all related issues
  • No unrelated changes

Reviewer checklist:

Indicate the SEMVER impact of the PR:

  • Major (when you make incompatible API changes)
  • Minor (when you add functionality in a backward compatible manner)
  • Patch (when you make backward compatible bug fixes)

At the end of the review, please label the PR with the appropriate label: r.Major, r.Minor, r.Patch.

Breaking change release note preparation (if applicable):

  • To be included in the release note for any feature that is made obsolete/breaking

Give a brief explanation note about:

  • what was the old feature that was made obsolete
  • any replacement feature (if any), and
  • how the author should modify his website to migrate from the old feature to the replacement feature (if possible).

@Golddirio Golddirio marked this pull request as ready for review July 28, 2025 13:10
@damithc damithc requested review from Copilot, gerteck and AgentHagu and removed request for gerteck August 3, 2025 15:34
Copy link

@Copilot 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 fixes the inconsistency in positions of popover error messages by modifying how error messages are displayed in the Popover component and how they are generated in the include panel processor.

  • Adds local error handling and display functionality to the Popover Vue component
  • Replaces error node creation with inline error slots in the popover content area
  • Introduces error validation and DOM error capturing mechanisms

Reviewed Changes

Copilot reviewed 2 out of 66 changed files in this pull request and generated 6 comments.

File Description
packages/vue-components/src/Popover.vue Adds local error state, validation methods, and inline error message display
packages/core/src/html/includePanelProcessor.ts Replaces error node creation with inline error slots for consistent positioning

},
isValidUrl(url) {
try {
(() => new URL(url))();
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

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

The immediately invoked function expression (IIFE) pattern (() => new URL(url))() is unnecessarily complex. Replace with new URL(url) directly since the constructor already throws on invalid URLs.

Suggested change
(() => new URL(url))();
new URL(url);

Copilot uses AI. Check for mistakes.

this.localError = errorEl.textContent;
errorEl.remove();
}
});
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

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

Direct DOM querying with document.querySelectorAll breaks Vue's component encapsulation and reactive data flow. Consider using Vue's ref system or emitting events to parent components instead of global DOM manipulation.

Suggested change
});
// Check for error messages within this component only
const errorEl = this.$refs.popoverError;
if (errorEl && (errorEl.textContent.includes('popover') || errorEl.textContent.includes('src'))) {
// Optionally, further check if the error is related to this popover
if (errorEl.textContent.includes(this.src) || errorEl.textContent.includes(this.header)) {
this.localError = errorEl.textContent;
}
}

Copilot uses AI. Check for mistakes.

if (errorEl.textContent.includes(this.src)
|| errorEl.textContent.includes(this.header)) {
this.localError = errorEl.textContent;
errorEl.remove();
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

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

Directly removing DOM elements with errorEl.remove() can cause memory leaks and break Vue's reactivity. If error elements need to be removed, use Vue's conditional rendering with v-if instead.

Suggested change
errorEl.remove();
// Instead of removing the element, hide it to avoid breaking Vue's reactivity
errorEl.style.display = 'none';

Copilot uses AI. Check for mistakes.

}
.popover-error-message {
color: #f00;
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

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

[nitpick] The hardcoded color value #f00 is a magic number. Consider using a CSS custom property or a semantic color variable from your design system for better maintainability.

Suggested change
color: #f00;
color: var(--popover-error-color, #f00);

Copilot uses AI. Check for mistakes.

{
type: 'tag',
name: 'div',
attribs: { style: 'color: red;' },
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

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

[nitpick] Inline styles with hardcoded colors should use CSS classes instead for consistency and maintainability. Consider using a CSS class like 'error-message' that can be styled centrally.

Suggested change
attribs: { style: 'color: red;' },
attribs: { class: 'error-message' },

Copilot uses AI. Check for mistakes.

cheerio(node).replaceWith(createErrorNode(node, error));
const errorMsg
= 'URLs are not allowed in the \'src\' attribute.<br>'
+ `File: ${context.cwf}<br>`
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

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

Using HTML <br> tags in error messages couples the error content with presentation. Consider using \n for line breaks and let the display layer handle formatting, or use an array of message parts.

Suggested change
+ `File: ${context.cwf}<br>`
= 'URLs are not allowed in the \'src\' attribute.\n'
+ `File: ${context.cwf}\n`

Copilot uses AI. Check for mistakes.

@gerteck
Copy link
Contributor

gerteck commented Aug 4, 2025

Hi @Golddirio,

just a preliminary test, will give a more detailed PR review. I noticed that the popover error message no longer shows for URLs in your branch, see:

image

Copy link
Contributor

@gerteck gerteck left a comment

Choose a reason for hiding this comment

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

Hi @Golddirio , thank you for your PR!

Firstly, just a small nit, do try to keep your PR clean by not committing the font files unless there are any specific font changes, and for the frontend bundles as well. Link.

I believe you are on the right track, do feel free to clarify any comments.

I would suggest refining the processing logic and minimizing any changes to the vue component to avoid introducing any unnecessary coupling between the two. Ideally, the vue popover component should not need to be too aware of how the src attribute processing logic functions.

Think about why in one case, the error is generated at the location of the popover, and in the other case, it is not. There might already be a way to generate any similar error at the location of the popover then without modifying the logic or introducing if-else clauses in the vue component, with some slight tweaking.

I think with some refinement, you could achieve a simpler and more elegant fix. Great effort!

As a stretch goal, you could even consider adding a few testcases to verify that the popover appears at the desired location in the HTML dom.

node.children = createPopoverInlineErrorSlot(errorMsg);
return context;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps it would be helpful to understand how the original implementation displays the error message in-place without touching the logic in the separate vue UI components

},
findAndHandleGlobalErrors() {
// Look for error messages that might have been injected elsewhere
const popoverErrors = Array.from(document.querySelectorAll('.popover-error'))
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious, where do the elements with class popover-error originate from? I can't seem to find where such elements would be injected or modified upstream

type: String,
default: 'top',
},
src: {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the popover expect this attribute?

const attributeSlotElement: NodeOrText[] = createSlotTemplateNode('content', actualContent);
node.children = node.children ? attributeSlotElement.concat(node.children) : attributeSlotElement;
delete node.attribs.src;
return childContext;
}

Our processPopoverSrc upstream function deletes this attribute, would it be better that the vue component remains unaware of a potential src attribute?

Copy link
Contributor

@AgentHagu AgentHagu left a comment

Choose a reason for hiding this comment

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

Hi @Golddirio, thanks for the contribution. I'd just like to follow up on @gerteck's comments.

Think about why in one case, the error is generated at the location of the popover, and in the other case, it is not. There might already be a way to generate any similar error at the location of the popover then without modifying the logic or introducing if-else clauses in the vue component, with some slight tweaking.

Just as gerteck mentioned, look at the original code to see why there is differing behavior between error locations for different errors. In particular, after some investigation there seems to be some strange behavior between cheerio's replaceWith function and our createErrorNode function.

  1. createErrorNode actually doesn't "create" a new node, it mutates the given element into an error node.
  2. This leads to an issue when used with replaceWith, since we are accidentally replacing a node with itself. From my own testing, this often leads to strange behavior like placing the node at the end or deleting other nodes.

With this knowledge, think about a way to standardize error location behavior. Good luck!

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.

Inconsistencies with popover error message location
3 participants