If you have any questions or feedback, pleasefill out this form
Table of Contents
This post is translated by ChatGPT and originally written in Mandarin, so there may be some inaccuracies or mistakes.
Today, I went to check out the Svelte source code, familiarizing myself with the architecture while also looking for some simple issues to practice on. I came across this one — emits warning.
Although I believe that, based on the issue's description, an a
tag without an href
should be considered invalid (at least it doesn’t comply with a11y standards), I later found out that there are some inconsistencies in the current specifications mentioned on StackOverflow.
Basically, an href
can be empty, but in such cases, it’s better to use a button or similar tag instead, as this is more friendly for screen readers.
Afterward, I checked out eslint-plugin-jsx-a11y and found that this ESLint plugin helps you determine if an href
is a valid value. Here are some invalid values:
<a onClick={foo} /> // Can be replaced with button
<a href="#" /> // Only # without an id
<a href={"#"} /> // Literal value
<a href={`#`} /> // Literal value
<a href="javascript:void(0)" /> // Should not use javascript:void(0)
<a href={"javascript:void(0)"} /> // Literal value
<a href={`javascript:void(0)`} /> // Literal value
And cases where href
is empty:
<a />
<a href={undefined} />
<a href={null} />
Svelte performs basic a11y
checks, such as missing href
or invalid href
values. Since Svelte itself has a compiler, these checks are carried out during the compilation phase:
// compiler/compile/nodes/Element.ts
// L425
if (this.name === 'a') {
const attribute = attribute_map.get('href') || attribute_map.get('xlink:href');
if (attribute) {
const value = attribute.get_static_value();
if (value === '' || value === '#') {
component.warn(attribute, {
code: `a11y-invalid-attribute`,
message: `A11y: '${value}' is not a valid ${attribute.name} attribute`
});
}
} else {
component.warn(this, {
code: `a11y-missing-attribute`,
message: `A11y: <a> element should have an href attribute`
});
}
}
At this stage, Svelte transforms the syntax into an Abstract Syntax Tree (AST), which makes the checks very convenient.
However, upon closer inspection, I noticed that the case for javascript:void(0)
seems to be unhandled; currently, it only processes cases where the value is empty or #
. So, I casually added a line for checking: if (value === '' || value === '#' || /^\W*javascript:/.test(value))
and proposed a Pull Request.
Additionally, it’s worth noting that Svelte currently only checks values that are is_static
, so for cases like:
<a href={undefined} />
<a href={null} />
<a href={`#`} />
<a href={"javascript:void(0)"} />
<a href={`javascript:void(0)`} />
Since the expressions inside {}
are not detected by Svelte (they are marked as is_static
false), you would need to implement additional handling for these expressions. If I have time (Golden Week is approaching), I’ll look into fixing these.
It doesn’t seem like a particularly useful feature, but since it’s done during the compilation phase, it won't affect the bundle size. I’m increasingly convinced that the path of using a compiler is viable; you can write in whatever way you prefer, as long as it compiles down to JavaScript.
Although this isn’t a new idea—languages like LiveScript
or Elm
have similar concepts to varying extents—I think the reason Svelte has gained attention (and is more widely used) is that it retains most of the JavaScript syntax. The learning curve for templates is nearly zero (if you know React or Vue), and it feels like Vue with HTML, CSS, and JavaScript seamlessly integrated.
Moreover, Svelte's reactive mechanism and animation control are aspects that frontend developers need to consider when implementing pages, which other compilers may not be able to provide. Everyone wants Functional Programming, but if it doesn’t solve the real problems developers face, it remains merely a passion for a select few.
If you found this article helpful, please consider buying me a coffee ☕ It'll make my ordinary day shine ✨
☕Buy me a coffee