Issues with certain HTML and SVG elements missing certain properties
When using:
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" viewBox="0 0 250 250" width="100%" height="100%">:
Property 'xmlns' does not exist on type 'SVGElementAttributes<"svg"> & HTMLComponentProps<SVGSVGElement> & EventAttributesBase<SVGSVGElement> & { ...; }'.
When using:
<path fill="url(#a)" d="M250 125q0-52-37-88-36-37-88-37T37 37Q0 73 0 125t37 88q36 37 88 37t88-37q37-36 37-88M87 195V55l100 70-100 70z"></path>
Property 'fill' does not exist on type 'SVGElementAttributes<"path"> & HTMLComponentProps<SVGPathElement> & EventAttributesBase<SVGPathElement> & { ...; }'.
Property 'd' does not exist on type 'SVGElementAttributes<"path"> & HTMLComponentProps<SVGPathElement> & EventAttributesBase<SVGPathElement> & { ...; }'.
When using:
<circle class="spinner" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
Property 'fill' does not exist on type 'SVGElementAttributes<"circle"> & HTMLComponentProps<SVGCircleElement> & EventAttributesBase<SVGCircleElement> & { ...; }'.
When using:
<text id="unmute-text" x="256" y="560" text-anchor="middle" font-size="60px" fill="#FFF" stroke="#FFF">
Property 'fill' does not exist on type 'SVGElementAttributes<"text"> & HTMLComponentProps<SVGTextElement> & EventAttributesBase<SVGTextElement> & { ...; }'.
When using:
<input id="virtual-keyboard" type="text" autocapitalize="none" autocomplete="off" autocorrect="off" />
Property 'autocorrect' does not exist on type 'ElementAttributes<HTMLInputElement, HTMLAttributes> & HTMLComponentProps<HTMLInputElement> & EventAttributesBase<...> & { ...; }'.
Property 'autocapitalize' does not exist on type 'ElementAttributes<HTMLInputElement, HTMLAttributes> & HTMLComponentProps<HTMLInputElement> & EventAttributesBase<...> & { ...; }'.
References:
xmlns: https://developer.mozilla.org/en-US/docs/Web/SVG/Namespaces_Crash_Course#declaring_namespaces
fill: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill and https://svgwg.org/svg2-draft/painting.html#FillProperties
d: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d and https://svgwg.org/svg2-draft/paths.html#DProperty
autocorrect: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autocorrect
autocapitalize: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize and https://html.spec.whatwg.org/multipage/interaction.html#attr-autocapitalize
I created these type definitions to try to work around the issue:
interface SVGSVGElement {
xmlns?: string; // Works
scale?: string | number; // Works
}
interface SVGPathElement {
fill?: string; // Works
stroke?: string; // Works
d?: string; // Doesn't work
}
interface SVGTextElement {
fill?: string; // Works
stroke?: string; // Works
}
interface SVGCircleElement {
fill?: string; // Works
}
interface HTMLInputElement {
autocapitalize?: string; // Doesn't work
autocorrect?: string; // Doesn't work
}
These errors remained:
Property 'd' does not exist on type 'SVGElementAttributes<"path"> & HTMLComponentProps<SVGPathElement> & EventAttributesBase<SVGPathElement> & { ...; }'.Property 'autocapitalize' does not exist on type 'ElementAttributes<HTMLInputElement, HTMLAttributes> & HTMLComponentProps<HTMLInputElement> & EventAttributesBase<...> & { ...; }'.Property 'autocorrect' does not exist on type 'ElementAttributes<HTMLInputElement, HTMLAttributes> & HTMLComponentProps<HTMLInputElement> & EventAttributesBase<...> & { ...; }'.
Thanks for the report. I'll try to look at this at the weekend.
In the meantime, you can try one of these two things:
- switch back to the last major version.. I changed the types a bit recently and am not sure if this might have caused your issue.
- For the changes to work in the latest version, you'll need to adjust two interfaces:
declare module "tsx-dom-types" {
export interface SVGAttributes {
xmlns?: string;
}
}
declare global {
interface SVGSVGElement {
xmlns: string;
}
}
edit: nevermind, just the top-one seems to be needed. Leaving the code snippet as is though, in case it might be needed for other attributes
I'll try to find a better way to solve these kinds of fixes/adjustments
~Somehow, with no other changes to globals.d.ts, this is all that's needed, no matter how many property errors I'm getting with this package before that change:~
~declare module "tsx-dom-types" { }~
~I think that might be turning off type checking for this package. Which seems wrong.~
So the issue seems three-fold:
- Properties defined only on SVGAttributes but not HTMLAttributes don't work without changing the type definitions for the element interfaces to add the properties there too (except if you abuse number 3).
- The properties autocorrect and autocapitalize are missing from HTMLAttributes and the property d is missing from SVGAttributes.
- ~Adjusting the module definition for tsx-dom-types disables type checking for tsx-dom altogether, which seems wrong.~
Have you tried importing the types first in addition to declaring the module?
import "tsx-dom-types";
declare module "tsx-dom-types" { }
When you declare a module and do not import it first, it will act as if the original types do not exist.
Ah yeah, that works (fixes number 3 from https://github.com/Lusito/tsx-dom/issues/22#issuecomment-2237461126). So this is my new working globals.d.ts file:
import "tsx-dom-types";
declare module "tsx-dom-types" {
export interface HTMLAttributes {
autocapitalize?: string;
autocorrect?: string;
}
export interface SVGAttributes {
d?: string;
}
}
declare global {
interface SVGSVGElement {
xmlns?: string;
scale?: string | number;
}
interface SVGPathElement {
xmlns?: string;
fill?: string;
stroke?: string;
d?: string;
}
interface SVGTextElement {
xmlns?: string;
fill?: string;
stroke?: string;
}
interface SVGCircleElement {
xmlns?: string;
fill?: string;
}
interface SVGDefsElement {
xmlns?: string;
}
interface SVGGElement {
xmlns?: string;
}
interface SVGLinearGradientElement {
xmlns?: string;
}
interface SVGStopElement {
xmlns?: string;
}
interface SVGUseElement {
xmlns?: string;
}
interface HTMLInputElement {
autocapitalize?: string;
autocorrect?: string;
}
}
Following #23 and #24 I shouldn't need the autocapitalize changes or the d change on tsx-dom-types, but I still seem to need the other changes.
Thanks for sharing your definitions. That helps verifying my new implementation.
-
Are you sure, that the
<svg>element receives a scale property? I can't seem to find it in the spec or on MDN. It seems to be only available on<feDisplacementMap> -
I can't find any documentation on xmlns for non-
<svg>elements. Are you sure that it's needed in all of those elements?.The xmlns attribute is only required on the outermost svg element of SVG documents, or inside HTML documents with XML serialization. It is unnecessary for inner svg elements or inside HTML documents with HTML serialization.
This doesn't seem to exclude it, but I can't find any specific definition on where it's needed. If you are using it in HTML, it's not needed at all. HTML Parsers already define the namespace correctly.
The other issues are on their way to be fixed. I'm working on a bigger change, where I parsed/converted a lot of data from https://www.w3.org/TR/SVG2/.
Idea to shorten your definitions even further:
interface SVGElement {
xmlns?: string;
fill?: string;
stroke?: string;
}
Then you can remove those properties from all other svg element interfaces since they all extend from it.
If scale is a presentational property as well (css value that can be set via html attribute), then this can be set on SVGElement as well, though as said above, I think this is only valid on <feDisplacementMap>.
xmlns shouldn't be needed for non-<svg> elements but it is because of this, as createElement doesn't work properly for SVG elements.
https://github.com/Lusito/tsx-dom/blob/7440919ac2811bc8b88c397c6bc7d90efd8c28b8/packages/tsx-dom/src/utils.ts#L22
Basically, the logic of tsx-dom would need to take into account the xmlns of parent SVG elements and use createElementNS with that to avoid using xmlns. document.createElement("linearGradient") makes a <lineargradient>, not a <linearGradient>, which is not right.
Are you sure, that the
<svg>element receives a scale property? I can't seem to find it in the spec or on MDN. It seems to be only available on<feDisplacementMap>
You're right, this was incorrect. Thank you for pointing that out, I opened https://github.com/ruffle-rs/ruffle/pull/17224
For the shortened and fixed definitions, I opened https://github.com/ruffle-rs/ruffle/pull/17213, so thanks for that too. I can remove the scale from there after my above PR is merged.
As I noted, xmlns shouldn't be needed, but it is because of an issue with this library only using createElementNS when an element directly contains the xmlns attribute, which I suppose is a separate and larger issue, but until it's fixed I can work around it by putting xmlns on every SVG element.
document.createElementNS("http://www.w3.org/2000/svg", "linearGradient").tagName is "linearGradient"
document.createElement("linearGradient").tagName is "LINEARGRADIENT"
Case-sensitivity is required for SVG elements.
These will be my new definitions:
import "tsx-dom-types";
declare module "tsx-dom-types" {
interface HTMLAttributes {
autocapitalize?: string; // Removable after a new tsx-dom release
autocorrect?: string;
}
interface SVGAttributes {
d?: string; // Removable after a new tsx-dom release
}
}
declare global {
interface SVGElement {
xmlns?: string;
fill?: string;
stroke?: string;
}
interface SVGPathElement {
d?: string;
}
interface HTMLInputElement {
autocapitalize?: string; // Removable after a new tsx-dom release
autocorrect?: string;
}
}
xmlns shouldn't be needed for non-<svg> elements but it is because of this, as createElement doesn't work properly for SVG elements.
Opened #25 for this since it's really a separate issue.