mirror of https://github.com/sveltejs/svelte
parent
a85b6002a7
commit
37749bd3e4
@ -0,0 +1,35 @@
|
||||
import flattenReference from '../../utils/flattenReference.js';
|
||||
import list from '../utils/list.js';
|
||||
|
||||
const validBuiltins = new Set([
|
||||
'set',
|
||||
'fire',
|
||||
'destroy'
|
||||
]);
|
||||
|
||||
export default function validateEventHandlerCallee ( validator, attribute ) {
|
||||
const { callee, start, type } = attribute.expression;
|
||||
|
||||
if ( type !== 'CallExpression' ) {
|
||||
validator.error( `Expected a call expression`, start );
|
||||
}
|
||||
|
||||
const { name } = flattenReference( callee );
|
||||
|
||||
if ( name === 'this' || name === 'event' ) return;
|
||||
if ( callee.type === 'Identifier' && validBuiltins.has( callee.name ) || validator.methods.has( callee.name ) ) return;
|
||||
|
||||
const validCallees = [ 'this.*', 'event.*' ]
|
||||
.concat(
|
||||
Array.from( validBuiltins ),
|
||||
Array.from( validator.methods.keys() )
|
||||
);
|
||||
|
||||
let message = `'${validator.source.slice( callee.start, callee.end )}' is an invalid callee (should be one of ${list( validCallees )})`;
|
||||
|
||||
if ( callee.type === 'Identifier' && validator.helpers.has( callee.name ) ) {
|
||||
message += `. '${callee.name}' exists on 'helpers', did you put it in the wrong place?`;
|
||||
}
|
||||
|
||||
validator.error( message, start );
|
||||
}
|
@ -1,3 +1,48 @@
|
||||
export default function validateWindow () {
|
||||
// TODO
|
||||
import flattenReference from '../../utils/flattenReference.js';
|
||||
import fuzzymatch from '../utils/fuzzymatch.js';
|
||||
import list from '../utils/list.js';
|
||||
import validateEventHandler from './validateEventHandler.js';
|
||||
|
||||
const validBindings = [
|
||||
'innerWidth',
|
||||
'innerHeight',
|
||||
'outerWidth',
|
||||
'outerHeight',
|
||||
'scrollX',
|
||||
'scrollY'
|
||||
];
|
||||
|
||||
export default function validateWindow ( validator, node ) {
|
||||
node.attributes.forEach( attribute => {
|
||||
if ( attribute.type === 'Binding' ) {
|
||||
if ( attribute.value.type !== 'Identifier' ) {
|
||||
const { parts } = flattenReference( attribute.value );
|
||||
|
||||
validator.error(
|
||||
`Bindings on <:Window/> must be to top-level properties, e.g. '${parts[ parts.length - 1 ]}' rather than '${parts.join( '.' )}'`,
|
||||
attribute.value.start
|
||||
);
|
||||
}
|
||||
|
||||
if ( !~validBindings.indexOf( attribute.name ) ) {
|
||||
const match = (
|
||||
attribute.name === 'width' ? 'innerWidth' :
|
||||
attribute.name === 'height' ? 'innerHeight' :
|
||||
fuzzymatch( attribute.name, validBindings )
|
||||
);
|
||||
|
||||
const message = `'${attribute.name}' is not a valid binding on <:Window>`;
|
||||
|
||||
if ( match ) {
|
||||
validator.error( `${message} (did you mean '${match}'?)`, attribute.start );
|
||||
} else {
|
||||
validator.error( `${message} — valid bindings are ${list( validBindings )}`, attribute.start );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if ( attribute.type === 'EventHandler' ) {
|
||||
validateEventHandler( validator, attribute );
|
||||
}
|
||||
});
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import FuzzySet from './FuzzySet.js';
|
||||
|
||||
export default function fuzzymatch ( name, names ) {
|
||||
const set = new FuzzySet( names );
|
||||
const matches = set.get( name );
|
||||
|
||||
return matches && matches[0] && matches[0][0] > 0.7 ?
|
||||
matches[0][1] :
|
||||
null;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export default function list ( items, conjunction = 'or' ) {
|
||||
if ( items.length === 1 ) return items[0];
|
||||
return `${items.slice( 0, -1 ).join( ', ' )} ${conjunction} ${items[ items.length - 1 ]}`;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
[{
|
||||
"message": "'innerwidth' is not a valid binding on <:Window> (did you mean 'innerWidth'?)",
|
||||
"loc": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"pos": 9
|
||||
}]
|
@ -0,0 +1 @@
|
||||
<:Window bind:innerwidth='w'/>
|
@ -0,0 +1,8 @@
|
||||
[{
|
||||
"message": "Bindings on <:Window/> must be to top-level properties, e.g. 'baz' rather than 'foo.bar.baz'",
|
||||
"loc": {
|
||||
"line": 1,
|
||||
"column": 26
|
||||
},
|
||||
"pos": 26
|
||||
}]
|
@ -0,0 +1 @@
|
||||
<:Window bind:innerWidth='foo.bar.baz'/>
|
@ -0,0 +1,8 @@
|
||||
[{
|
||||
"message": "'width' is not a valid binding on <:Window> (did you mean 'innerWidth'?)",
|
||||
"loc": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"pos": 9
|
||||
}]
|
@ -0,0 +1 @@
|
||||
<:Window bind:width='w'/>
|
@ -0,0 +1,8 @@
|
||||
[{
|
||||
"message": "'potato' is not a valid binding on <:Window> — valid bindings are innerWidth, innerHeight, outerWidth, outerHeight, scrollX or scrollY",
|
||||
"loc": {
|
||||
"line": 1,
|
||||
"column": 9
|
||||
},
|
||||
"pos": 9
|
||||
}]
|
@ -0,0 +1 @@
|
||||
<:Window bind:potato='foo'/>
|
@ -0,0 +1,8 @@
|
||||
[{
|
||||
"message": "'resize' is an invalid callee (should be one of this.*, event.*, set, fire or destroy)",
|
||||
"loc": {
|
||||
"line": 1,
|
||||
"column": 20
|
||||
},
|
||||
"pos": 20
|
||||
}]
|
@ -0,0 +1 @@
|
||||
<:Window on:resize='resize()'/>
|
Loading…
Reference in new issue