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

Namespace handling makes it impossible to lint recursive SVG / MathML components #2458

Closed
mordae opened this issue Apr 29, 2024 · 8 comments · Fixed by #2610
Closed

Namespace handling makes it impossible to lint recursive SVG / MathML components #2458

mordae opened this issue Apr 29, 2024 · 8 comments · Fixed by #2610

Comments

@mordae
Copy link
Contributor

mordae commented Apr 29, 2024

What rule do you want to change?

Not exactly a specific rule, but I have been motivated by vue/no-v-text-v-html-on-component being falsely triggered on MathML tags. isCustomComponent() is being called from 17 rules. The problem lies with the fact that every composition component starts with a top-level namespace of HTML, which makes it impossible to create partial, especially recursive components within another namespace without confusing the linter.

Does this change cause the rule to produce more or fewer warnings?

Fewer.

How will the change be implemented? (New option, new default behavior, etc.)?

There are multiple options:

  1. Stop examining namespaces when determining whether something is an element or a component.
  2. Treat the HTML namespace as valid namespace for SVG and MathML tags.
  3. Looks for xmlns on the top-level <template/> and adjust namespace accordingly.
  4. Implement (1) or (2), but gate it behind a configuration option.

Please provide some example code that this change will affect:

<script setup type="ts">
// This lives inside MathExpression.vue

import { Expression } from './expression.ts'

defineProps<{
  expression: Expression
}>()
</script>

<template>
  <mfrac v-if="expression instanceof Fraction">
    <mrow>
      <MathExpression v-text="expression.numerator" />
    </mrow>
    <mrow>
      <MathExpression v-text="expression.denominator" />
    </mrow>
  </mfrac>
  <!-- more cases omitted for brevity -->
  <mn v-else v-text="expression.value" />
</template>

What does the rule currently do for this code?

Triggers vue/no-v-text-v-html-on-component because it does not see <mfrac/> as being inside MathML namespace. Which is impossible to realize, because <math/> cannot be nested and is only specified at the top level. This component recurses into the data, rendering the full MathML structure.

What will the rule do after it's changed?

In case of (1), (2), (4) it won't consider using <mfrac/> in this context as an error.
In case of (3):

<template xmlns="http://www.w3.org/1998/Math/MathML">
  <mi v-text="'x'" />
</template>

It will accept this otherwise invalid, but (probably) harmless syntax to indicate that we are inside MathML namespace and proceed from there on, possibly marking HTML and SVG elements as out of place.

Additional context

This obviously applies to SVG as well, although there is not that high probability somebody will be doing anything recursive in there. Math is a different story, though.

@waynzh

This comment was marked as outdated.

@FloEdelmann
Copy link
Member

Yes, probably. Thanks for checking!

If the issue persists with the newest version of eslint-plugin-vue, please add a comment or open a new issue.

@mordae
Copy link
Contributor Author

mordae commented Jun 29, 2024

@FloEdelmann: #2457 adds support for MathML that does not span across multiple files. The issue in this report concerns MathML spanning across multiple components and is still present as described at the top.

@FloEdelmann FloEdelmann reopened this Jul 1, 2024
@FloEdelmann
Copy link
Member

I'm not sure which issue you are reporting exactly. Is an vue/no-v-text-v-html-on-component error reported for <MathExpression v-text="expression.numerator" />? That seems correct to me, regardless whether it is MathML or not. Or is it reported for <mn v-else v-text="expression.value" /> because it is not correctly recognized as a MathML element? But you mention the <mfrac /> element?

Could you please create a reproduction on playground, Stackblitz, or a separate repository?

@mordae
Copy link
Contributor Author

mordae commented Jul 21, 2024

Parent.vue:

<template>
  <math xmlns="http://www.w3.org/1998/Math/MathML">
    <Child />
  </math>
</template>

Child.vue:

<template>
  <mi v-text="'x'" />  <!-- vue/no-v-text-v-html-on-component -->
</template>

@mordae
Copy link
Contributor Author

mordae commented Oct 1, 2024

@FloEdelmann: playground example (with the usage described in the previous comment)

@FloEdelmann
Copy link
Member

I think I finally understand, thanks for your persistence and for the playground example.

v-text on MathML elements is already ignored by the vue/no-v-text-v-html-on-component rule (and related rules, via the isCustomComponent util), but only if an ancestor element is found with the MathML namespace. If you extract the child element into a separate component, the MathML namespace can't be found anymore, so the rule reports an error.

As a workaround, you could specify { "allow": ["mi"] } as a rule option.

@mordae Do you think this suffices or would you prefer another configuration option (something like ignoreElementNamespaces, which would be false by default → same behavior as now)?
@ota-meshi What do you think?

@mordae
Copy link
Contributor Author

mordae commented Oct 1, 2024

@FloEdelmann: as I've written initially, it would be nice to relax the namespace check somehow. Allowing SVG and MathML inside HTML namespace as an option would be sufficient.

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 a pull request may close this issue.

3 participants