You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/src/validate/index.ts

104 lines
2.5 KiB

import validateJs from './js/index';
import validateHtml from './html/index';
import { getLocator, Location } from 'locate-character';
import getCodeFrame from '../utils/getCodeFrame';
import CompileError from '../utils/CompileError'
import { Node, Parsed } from '../interfaces';
class ValidationError extends CompileError {
constructor ( message: string, template: string, index: number, filename: string ) {
super( message, template, index, filename );
this.name = 'ValidationError';
}
}
export class Validator {
readonly source: string;
readonly filename: string;
onwarn: ({}) => void;
locator?: (pos: number) => Location;
namespace: string;
defaultExport: Node;
properties: Map<string, Node>;
components: Map<string, Node>;
methods: Map<string, Node>;
helpers: Map<string, Node>;
transitions: Map<string, Node>;
constructor ( parsed: Parsed, source: string, options: { onwarn, name?: string, filename?: string } ) {
this.source = source;
this.filename = options !== undefined ? options.filename : undefined;
this.onwarn = options !== undefined ? options.onwarn : undefined;
this.namespace = null;
this.defaultExport = null;
this.properties = new Map();
this.components = new Map();
this.methods = new Map();
this.helpers = new Map();
this.transitions = new Map();
}
error ( message: string, pos: number ) {
throw new ValidationError( message, this.source, pos, this.filename );
}
warn ( message: string, pos: number ) {
if ( !this.locator ) this.locator = getLocator( this.source );
const { line, column } = this.locator( pos );
const frame = getCodeFrame( this.source, line, column );
this.onwarn({
message,
frame,
loc: { line: line + 1, column },
pos,
filename: this.filename,
toString: () => `${message} (${line + 1}:${column})\n${frame}`
});
}
}
export default function validate ( parsed: Parsed, source: string, { onerror, onwarn, name, filename } ) {
try {
if ( name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test( name ) ) {
const error = new Error( `options.name must be a valid identifier` );
throw error;
}
if ( name && !/^[A-Z]/.test( name ) ) {
const message = `options.name should be capitalised`;
onwarn({
message,
filename,
toString: () => message
});
}
const validator = new Validator( parsed, source, {
onwarn,
name,
filename
});
if ( parsed.js ) {
validateJs( validator, parsed.js );
}
if ( parsed.html ) {
validateHtml( validator, parsed.html );
}
} catch ( err ) {
if ( onerror ) {
onerror( err );
} else {
throw err;
}
}
}