Remove unused namespace redirection from the astro parser (#1245)
* nit: remove unused namespace checking from astro parser * test: add tests for namespaced attributes, including one removed attribute * add changeset
This commit is contained in:
parent
5cc7947a58
commit
5d2ea57841
7 changed files with 32 additions and 84 deletions
5
.changeset/wise-maps-pump.md
Normal file
5
.changeset/wise-maps-pump.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@astrojs/parser': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fixed an issue using namespaced attributes in astro files
|
|
@ -5,7 +5,7 @@ import read_style from '../read/style.js';
|
||||||
import { decode_character_references, closing_tag_omitted } from '../utils/html.js';
|
import { decode_character_references, closing_tag_omitted } from '../utils/html.js';
|
||||||
import { is_void } from '../../utils/names.js';
|
import { is_void } from '../../utils/names.js';
|
||||||
import { Parser } from '../index.js';
|
import { Parser } from '../index.js';
|
||||||
import { Directive, DirectiveType, TemplateNode, Text } from '../../interfaces.js';
|
import { TemplateNode, Text } from '../../interfaces.js';
|
||||||
import fuzzymatch from '../../utils/fuzzymatch.js';
|
import fuzzymatch from '../../utils/fuzzymatch.js';
|
||||||
import list from '../../utils/list.js';
|
import list from '../../utils/list.js';
|
||||||
import { FEATURE_CUSTOM_ELEMENT } from '../utils/features.js';
|
import { FEATURE_CUSTOM_ELEMENT } from '../utils/features.js';
|
||||||
|
@ -403,9 +403,6 @@ function read_attribute(parser: Parser, unique_names: Set<string>) {
|
||||||
|
|
||||||
parser.allow_whitespace();
|
parser.allow_whitespace();
|
||||||
|
|
||||||
const colon_index = name.indexOf(':');
|
|
||||||
const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index));
|
|
||||||
|
|
||||||
let value: any[] | true = true;
|
let value: any[] | true = true;
|
||||||
if (parser.eat('=')) {
|
if (parser.eat('=')) {
|
||||||
parser.allow_whitespace();
|
parser.allow_whitespace();
|
||||||
|
@ -421,74 +418,6 @@ function read_attribute(parser: Parser, unique_names: Set<string>) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type) {
|
|
||||||
const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|');
|
|
||||||
|
|
||||||
if (type === 'Binding' && directive_name !== 'this') {
|
|
||||||
check_unique(directive_name);
|
|
||||||
} else if (type !== 'EventHandler' && type !== 'Action') {
|
|
||||||
check_unique(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Ref') {
|
|
||||||
parser.error(
|
|
||||||
{
|
|
||||||
code: 'invalid-ref-directive',
|
|
||||||
message: `The ref directive is no longer supported — use \`bind:this={${directive_name}}\` instead`,
|
|
||||||
},
|
|
||||||
start
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'Class' && directive_name === '') {
|
|
||||||
parser.error(
|
|
||||||
{
|
|
||||||
code: 'invalid-class-directive',
|
|
||||||
message: 'Class binding name cannot be empty',
|
|
||||||
},
|
|
||||||
start + colon_index + 1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value[0]) {
|
|
||||||
if ((value as any[]).length > 1 || value[0].type === 'Text') {
|
|
||||||
parser.error(
|
|
||||||
{
|
|
||||||
code: 'invalid-directive-value',
|
|
||||||
message: 'Directive value must be a JavaScript expression enclosed in curly braces',
|
|
||||||
},
|
|
||||||
value[0].start
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const directive: Directive = {
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
type,
|
|
||||||
name: directive_name,
|
|
||||||
modifiers,
|
|
||||||
expression: (value[0] && value[0].expression) || null,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (type === 'Transition') {
|
|
||||||
const direction = name.slice(0, colon_index);
|
|
||||||
directive.intro = direction === 'in' || direction === 'transition';
|
|
||||||
directive.outro = direction === 'out' || direction === 'transition';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!directive.expression && (type === 'Binding' || type === 'Class')) {
|
|
||||||
directive.expression = {
|
|
||||||
start: directive.start + colon_index + 1,
|
|
||||||
end: directive.end,
|
|
||||||
type: 'Identifier',
|
|
||||||
name: directive.name,
|
|
||||||
} as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
return directive;
|
|
||||||
}
|
|
||||||
|
|
||||||
check_unique(name);
|
check_unique(name);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -500,17 +429,6 @@ function read_attribute(parser: Parser, unique_names: Set<string>) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_directive_type(name: string): DirectiveType {
|
|
||||||
if (name === 'use') return 'Action';
|
|
||||||
if (name === 'animate') return 'Animation';
|
|
||||||
if (name === 'bind') return 'Binding';
|
|
||||||
if (name === 'class') return 'Class';
|
|
||||||
if (name === 'on') return 'EventHandler';
|
|
||||||
if (name === 'let') return 'Let';
|
|
||||||
if (name === 'ref') return 'Ref';
|
|
||||||
if (name === 'in' || name === 'out' || name === 'transition') return 'Transition';
|
|
||||||
}
|
|
||||||
|
|
||||||
function read_attribute_value(parser: Parser) {
|
function read_attribute_value(parser: Parser) {
|
||||||
const quote_mark = parser.eat("'") ? "'" : parser.eat('"') ? '"' : null;
|
const quote_mark = parser.eat("'") ? "'" : parser.eat('"') ? '"' : null;
|
||||||
|
|
||||||
|
|
|
@ -36,4 +36,21 @@ Attributes('Passes boolean attributes to components as expected', async ({ runti
|
||||||
assert.equal($('#false').attr('type'), 'boolean');
|
assert.equal($('#false').attr('type'), 'boolean');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Attributes('Passes namespaced attributes as expected', async ({ runtime }) => {
|
||||||
|
const result = await runtime.load('/namespaced');
|
||||||
|
assert.ok(!result.error, `build error: ${result.error}`);
|
||||||
|
|
||||||
|
const $ = doc(result.contents);
|
||||||
|
assert.equal($('div').attr('xmlns:happy'), 'https://example.com/schemas/happy');
|
||||||
|
assert.equal($('img').attr('happy:smile'), 'sweet');
|
||||||
|
});
|
||||||
|
|
||||||
|
Attributes('Passes namespaced attributes to components as expected', async ({ runtime }) => {
|
||||||
|
const result = await runtime.load('/namespaced-component');
|
||||||
|
assert.ok(!result.error, `build error: ${result.error}`);
|
||||||
|
|
||||||
|
const $ = doc(result.contents);
|
||||||
|
assert.equal($('span').attr('on:click'), Function.prototype.toString.call((event) => console.log(event)));
|
||||||
|
});
|
||||||
|
|
||||||
Attributes.run();
|
Attributes.run();
|
||||||
|
|
1
packages/astro/test/fixtures/astro-attrs/src/components/NamespacedSpan.astro
vendored
Normal file
1
packages/astro/test/fixtures/astro-attrs/src/components/NamespacedSpan.astro
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<span {...Astro.props} />
|
|
@ -3,4 +3,4 @@ import Span from '../components/Span.jsx';
|
||||||
---
|
---
|
||||||
|
|
||||||
<Span id="true" attr={true} />
|
<Span id="true" attr={true} />
|
||||||
<Span id="false" attr={false} />
|
<Span id="false" attr={false} />
|
||||||
|
|
4
packages/astro/test/fixtures/astro-attrs/src/pages/namespaced-component.astro
vendored
Normal file
4
packages/astro/test/fixtures/astro-attrs/src/pages/namespaced-component.astro
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
import NamespacedSpan from '../components/NamespacedSpan.astro'
|
||||||
|
---
|
||||||
|
<NamespacedSpan on:click={event => console.log(event)} />
|
3
packages/astro/test/fixtures/astro-attrs/src/pages/namespaced.astro
vendored
Normal file
3
packages/astro/test/fixtures/astro-attrs/src/pages/namespaced.astro
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<div xmlns:happy="https://example.com/schemas/happy">
|
||||||
|
<img src="jolly.avif" happy:smile="sweet"/>
|
||||||
|
</div>
|
Loading…
Add table
Reference in a new issue