From 60c3c8f7ea298aad8ff9fa624a0638bcc3f5bef4 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 29 Jul 2017 21:31:53 -0400 Subject: [PATCH 1/3] fix various typescript errors --- src/generators/Generator.ts | 8 +- src/generators/shared/utils/getGlobals.ts | 7 +- src/generators/shared/utils/getIntro.ts | 38 +-- src/generators/shared/utils/getOutro.ts | 5 +- src/generators/shared/utils/walkHtml.ts | 2 +- src/interfaces.ts | 16 + src/utils/clone.ts | 6 +- src/utils/removeNode.ts | 5 +- src/validate/utils/FuzzySet.ts | 357 +++++++++------------- 9 files changed, 184 insertions(+), 260 deletions(-) diff --git a/src/generators/Generator.ts b/src/generators/Generator.ts index e20deb75bb..48491e410c 100644 --- a/src/generators/Generator.ts +++ b/src/generators/Generator.ts @@ -15,11 +15,12 @@ import clone from '../utils/clone'; import DomBlock from './dom/Block'; import SsrBlock from './server-side-rendering/Block'; import Stylesheet from '../css/Stylesheet'; -import { Node, Parsed, CompileOptions } from '../interfaces'; +import { Node, GenerateOptions, Parsed, CompileOptions } from '../interfaces'; const test = typeof global !== 'undefined' && global.__svelte_test; export default class Generator { + ast: Parsed; parsed: Parsed; source: string; name: string; @@ -78,9 +79,6 @@ export default class Generator { // styles this.stylesheet = stylesheet; - // TODO this is legacy — just to get the tests to pass during the transition - this.css = this.stylesheet.render(options.cssOutputFilename).css; - // allow compiler to deconflict user's `import { get } from 'whatever'` and // Svelte's builtin `import { get, ... } from 'svelte/shared.ts'`; this.importedNames = new Set(); @@ -263,7 +261,7 @@ export default class Generator { return (expression._dependencies = dependencies); } - generate(result, options: CompileOptions, { name, format }) { + generate(result: string, options: CompileOptions, { name, format }: GenerateOptions ) { if (this.imports.length) { const statements: string[] = []; diff --git a/src/generators/shared/utils/getGlobals.ts b/src/generators/shared/utils/getGlobals.ts index 1c00a08f60..8133757b4d 100644 --- a/src/generators/shared/utils/getGlobals.ts +++ b/src/generators/shared/utils/getGlobals.ts @@ -1,8 +1,7 @@ -import { Declaration, Options } from './getIntro'; +import { CompileOptions, Node } from '../../../interfaces'; -export type Globals = (id: string) => any; -export default function getGlobals(imports: Declaration[], options: Options) { +export default function getGlobals(imports: Node[], options: CompileOptions) { const { globals, onerror, onwarn } = options; const globalFn = getGlobalFn(globals); @@ -40,7 +39,7 @@ export default function getGlobals(imports: Declaration[], options: Options) { }); } -function getGlobalFn(globals: any): Globals { +function getGlobalFn(globals: any): (id: string) => string { if (typeof globals === 'function') return globals; if (typeof globals === 'object') { return id => globals[id]; diff --git a/src/generators/shared/utils/getIntro.ts b/src/generators/shared/utils/getIntro.ts index 7427f69a0b..6b043fcfec 100644 --- a/src/generators/shared/utils/getIntro.ts +++ b/src/generators/shared/utils/getIntro.ts @@ -1,29 +1,11 @@ import deindent from '../../../utils/deindent'; -import getGlobals, { Globals } from './getGlobals'; - -export type ModuleFormat = 'es' | 'amd' | 'cjs' | 'iife' | 'umd' | 'eval'; - -export interface Options { - name: string; - amd?: { - id?: string; - }; - globals: Globals | object; - onerror: (err: Error) => void; - onwarn: (obj: Error | { message: string }) => void; -} - -export interface Declaration { - name: string; - source: { - value: string; - }; -} +import getGlobals from './getGlobals'; +import { CompileOptions, ModuleFormat, Node } from '../../../interfaces'; export default function getIntro( format: ModuleFormat, - options: Options, - imports: Declaration[] + options: CompileOptions, + imports: Node[] ) { if (format === 'es') return ''; if (format === 'amd') return getAmdIntro(options, imports); @@ -35,7 +17,7 @@ export default function getIntro( throw new Error(`Not implemented: ${format}`); } -function getAmdIntro(options: Options, imports: Declaration[]) { +function getAmdIntro(options: CompileOptions, imports: Node[]) { const sourceString = imports.length ? `[ ${imports .map(declaration => `'${removeExtension(declaration.source.value)}'`) @@ -49,7 +31,7 @@ function getAmdIntro(options: Options, imports: Declaration[]) { : ''}${sourceString}function (${paramString(imports)}) { 'use strict';\n\n`; } -function getCjsIntro(options: Options, imports: Declaration[]) { +function getCjsIntro(options: CompileOptions, imports: Node[]) { const requireBlock = imports .map( declaration => @@ -64,7 +46,7 @@ function getCjsIntro(options: Options, imports: Declaration[]) { return `'use strict';\n\n`; } -function getIifeIntro(options: Options, imports: Declaration[]) { +function getIifeIntro(options: CompileOptions, imports: Node[]) { if (!options.name) { throw new Error(`Missing required 'name' option for IIFE export`); } @@ -74,7 +56,7 @@ function getIifeIntro(options: Options, imports: Declaration[]) { )}) { 'use strict';\n\n`; } -function getUmdIntro(options: Options, imports: Declaration[]) { +function getUmdIntro(options: CompileOptions, imports: Node[]) { if (!options.name) { throw new Error(`Missing required 'name' option for UMD export`); } @@ -101,11 +83,11 @@ function getUmdIntro(options: Options, imports: Declaration[]) { ); } -function getEvalIntro(options: Options, imports: Declaration[]) { +function getEvalIntro(options: CompileOptions, imports: Node[]) { return `(function (${paramString(imports)}) { 'use strict';\n\n`; } -function paramString(imports: Declaration[]) { +function paramString(imports: Node[]) { return imports.length ? ` ${imports.map(dep => dep.name).join(', ')} ` : ''; } diff --git a/src/generators/shared/utils/getOutro.ts b/src/generators/shared/utils/getOutro.ts index f9d8f186bc..682a3cc870 100644 --- a/src/generators/shared/utils/getOutro.ts +++ b/src/generators/shared/utils/getOutro.ts @@ -1,10 +1,11 @@ import getGlobals from './getGlobals'; +import { CompileOptions, Node } from '../../../interfaces'; export default function getOutro( format: string, name: string, - options, - imports + options: CompileOptions, + imports: Node[] ) { if (format === 'es') { return `export default ${name};`; diff --git a/src/generators/shared/utils/walkHtml.ts b/src/generators/shared/utils/walkHtml.ts index e12b36bbf2..b7ea97aa55 100644 --- a/src/generators/shared/utils/walkHtml.ts +++ b/src/generators/shared/utils/walkHtml.ts @@ -1,4 +1,4 @@ -import { Node } from '../../../interfaces'; +import { Node, Visitor } from '../../../interfaces'; export default function walkHtml(html: Node, visitors) { function visit(node: Node) { diff --git a/src/interfaces.ts b/src/interfaces.ts index 668c9816f8..4944bf8c46 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -39,6 +39,10 @@ export interface CompileOptions { name?: string; filename?: string; generate?: string; + globals?: ((id: string) => string) | object; + amd?: { + id?: string; + }; outputFilename?: string; cssOutputFilename?: string; @@ -51,3 +55,15 @@ export interface CompileOptions { onerror?: (error: Error) => void; onwarn?: (warning: Warning) => void; } + +export type ModuleFormat = 'es' | 'amd' | 'cjs' | 'iife' | 'umd' | 'eval'; + +export interface GenerateOptions { + name: string; + format: ModuleFormat; +} + +export interface Visitor { + enter: (node: Node) => void; + leave?: (node: Node) => void; +} \ No newline at end of file diff --git a/src/utils/clone.ts b/src/utils/clone.ts index d01b7aaa87..60b90c2208 100644 --- a/src/utils/clone.ts +++ b/src/utils/clone.ts @@ -1,7 +1,7 @@ -import { Node } from '../interfaces'; +import { Node, Parsed } from '../interfaces'; -export default function clone(node: Node) { - const cloned = {}; +export default function clone(node: Node|Parsed) { + const cloned: any = {}; for (const key in node) { const value = node[key]; diff --git a/src/utils/removeNode.ts b/src/utils/removeNode.ts index bce5984a98..6abea2f8c9 100644 --- a/src/utils/removeNode.ts +++ b/src/utils/removeNode.ts @@ -1,3 +1,4 @@ +import MagicString from 'magic-string'; import { Node } from '../interfaces'; const keys = { @@ -10,7 +11,7 @@ const offsets = { Program: [0, 0], }; -export function removeNode(code, parent: Node, node: Node) { +export function removeNode(code: MagicString, parent: Node, node: Node) { const key = keys[parent.type]; const offset = offsets[parent.type]; if (!key || !offset) throw new Error(`not implemented: ${parent.type}`); @@ -44,7 +45,7 @@ export function removeNode(code, parent: Node, node: Node) { return; } -export function removeObjectKey(code, node, key) { +export function removeObjectKey(code: MagicString, node: Node, key: string) { if (node.type !== 'ObjectExpression') return; let i = node.properties.length; diff --git a/src/validate/utils/FuzzySet.ts b/src/validate/utils/FuzzySet.ts index 1973d3ff83..f52242cf5d 100644 --- a/src/validate/utils/FuzzySet.ts +++ b/src/validate/utils/FuzzySet.ts @@ -1,115 +1,152 @@ // adapted from https://github.com/Glench/fuzzyset.js/blob/master/lib/fuzzyset.js // BSD Licensed -export default function FuzzySet( - arr, - useLevenshtein, - gramSizeLower, - gramSizeUpper -) { - // default options - arr = arr || []; - this.gramSizeLower = gramSizeLower || 2; - this.gramSizeUpper = gramSizeUpper || 3; - this.useLevenshtein = typeof useLevenshtein !== 'boolean' - ? true - : useLevenshtein; - - // define all the object functions and attributes - this.exactSet = {}; - this.matchDict = {}; - this.items = {}; - - // helper functions - function levenshtein(str1, str2) { - const current = []; - let prev; - let value; - - for (let i = 0; i <= str2.length; i++) { - for (let j = 0; j <= str1.length; j++) { - if (i && j) { - if (str1.charAt(j - 1) === str2.charAt(i - 1)) { - value = prev; - } else { - value = Math.min(current[j], current[j - 1], prev) + 1; - } +const GRAM_SIZE_LOWER = 2; +const GRAM_SIZE_UPPER = 3; + +// return an edit distance from 0 to 1 +function _distance(str1: string, str2: string) { + if (str1 === null && str2 === null) + throw 'Trying to compare two null values'; + if (str1 === null || str2 === null) return 0; + str1 = String(str1); + str2 = String(str2); + + const distance = levenshtein(str1, str2); + if (str1.length > str2.length) { + return 1 - distance / str1.length; + } else { + return 1 - distance / str2.length; + } +} + +// helper functions +function levenshtein(str1: string, str2: string) { + const current: number[] = []; + let prev; + let value; + + for (let i = 0; i <= str2.length; i++) { + for (let j = 0; j <= str1.length; j++) { + if (i && j) { + if (str1.charAt(j - 1) === str2.charAt(i - 1)) { + value = prev; } else { - value = i + j; + value = Math.min(current[j], current[j - 1], prev) + 1; } - - prev = current[j]; - current[j] = value; + } else { + value = i + j; } + + prev = current[j]; + current[j] = value; } + } + + return current.pop(); +} + +const _nonWordRe = /[^\w, ]+/; - return current.pop(); +function _iterateGrams(value: string, gramSize: number) { + gramSize = gramSize || 2; + const simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-'; + const lenDiff = gramSize - simplified.length; + const results = []; + + if (lenDiff > 0) { + for (let i = 0; i < lenDiff; ++i) { + value += '-'; + } + } + for (let i = 0; i < simplified.length - gramSize + 1; ++i) { + results.push(simplified.slice(i, i + gramSize)); } + return results; +} + +function _gramCounter(value: string, gramSize: number) { + // return an object where key=gram, value=number of occurrences + gramSize = gramSize || 2; + const result = {}; + const grams = _iterateGrams(value, gramSize); + let i = 0; - // return an edit distance from 0 to 1 - function _distance(str1, str2) { - if (str1 === null && str2 === null) - throw 'Trying to compare two null values'; - if (str1 === null || str2 === null) return 0; - str1 = String(str1); - str2 = String(str2); - - const distance = levenshtein(str1, str2); - if (str1.length > str2.length) { - return 1 - distance / str1.length; + for (i; i < grams.length; ++i) { + if (grams[i] in result) { + result[grams[i]] += 1; } else { - return 1 - distance / str2.length; + result[grams[i]] = 1; } } + return result; +} + +function sortDescending(a, b) { + return b[0] - a[0]; +} - const _nonWordRe = /[^\w, ]+/; +export default class FuzzySet { + exactSet: object; + matchDict: object; + items: object; - function _iterateGrams(value, gramSize) { - gramSize = gramSize || 2; - const simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-'; - const lenDiff = gramSize - simplified.length; - const results = []; + constructor(arr: string[]) { + // define all the object functions and attributes + this.exactSet = {}; + this.matchDict = {}; + this.items = {}; - if (lenDiff > 0) { - for (let i = 0; i < lenDiff; ++i) { - value += '-'; - } + // initialization + for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) { + this.items[i] = []; } - for (let i = 0; i < simplified.length - gramSize + 1; ++i) { - results.push(simplified.slice(i, i + gramSize)); + // add all the items to the set + for (let i = 0; i < arr.length; ++i) { + this.add(arr[i]); } - return results; } - function _gramCounter(value, gramSize) { - // return an object where key=gram, value=number of occurrences - gramSize = gramSize || 2; - const result = {}; - const grams = _iterateGrams(value, gramSize); - let i = 0; + add(value: string) { + const normalizedValue = value.toLowerCase(); + if (normalizedValue in this.exactSet) { + return false; + } - for (i; i < grams.length; ++i) { - if (grams[i] in result) { - result[grams[i]] += 1; - } else { - result[grams[i]] = 1; - } + let i = GRAM_SIZE_LOWER; + for (i; i < GRAM_SIZE_UPPER + 1; ++i) { + this._add(value, i); } - return result; } - // the main functions - this.get = function(value, defaultValue) { - // check for value in set, returning defaultValue or null if none found - const result = this._get(value); - if (!result && typeof defaultValue !== 'undefined') { - return defaultValue; + _add(value: string, gramSize: number) { + const normalizedValue = value.toLowerCase(); + const items = this.items[gramSize] || []; + const index = items.length; + + items.push(0); + const gramCounts = _gramCounter(normalizedValue, gramSize); + let sumOfSquareGramCounts = 0; + let gram; + let gramCount; + + for (gram in gramCounts) { + gramCount = gramCounts[gram]; + sumOfSquareGramCounts += Math.pow(gramCount, 2); + if (gram in this.matchDict) { + this.matchDict[gram].push([index, gramCount]); + } else { + this.matchDict[gram] = [[index, gramCount]]; + } } - return result; + const vectorNormal = Math.sqrt(sumOfSquareGramCounts); + items[index] = [vectorNormal, normalizedValue]; + this.items[gramSize] = items; + this.exactSet[normalizedValue] = value; }; - this._get = function(value) { - const normalizedValue = this._normalizeStr(value); + get(value: string) { + const normalizedValue = value.toLowerCase(); const result = this.exactSet[normalizedValue]; if (result) { @@ -119,8 +156,8 @@ export default function FuzzySet( let results = []; // start with high gram size and if there are no results, go to lower gram sizes for ( - let gramSize = this.gramSizeUpper; - gramSize >= this.gramSizeLower; + let gramSize = GRAM_SIZE_UPPER; + gramSize >= GRAM_SIZE_LOWER; --gramSize ) { results = this.__get(value, gramSize); @@ -129,10 +166,10 @@ export default function FuzzySet( } } return null; - }; + } - this.__get = function(value, gramSize) { - const normalizedValue = this._normalizeStr(value); + __get(value: string, gramSize: number) { + const normalizedValue = value.toLowerCase(); const matches = {}; const gramCounts = _gramCounter(normalizedValue, gramSize); const items = this.items[gramSize]; @@ -159,17 +196,6 @@ export default function FuzzySet( } } - function isEmptyObject(obj) { - for (const prop in obj) { - if (obj.hasOwnProperty(prop)) return false; - } - return true; - } - - if (isEmptyObject(matches)) { - return null; - } - const vectorNormal = Math.sqrt(sumOfSquareGramCounts); let results = []; let matchScore; @@ -182,127 +208,28 @@ export default function FuzzySet( items[matchIndex][1], ]); } - function sortDescending(a, b) { - if (a[0] < b[0]) { - return 1; - } else if (a[0] > b[0]) { - return -1; - } else { - return 0; - } - } results.sort(sortDescending); - if (this.useLevenshtein) { - const newResults = []; - const endIndex = Math.min(50, results.length); - // truncate somewhat arbitrarily to 50 - for (let i = 0; i < endIndex; ++i) { - newResults.push([ - _distance(results[i][1], normalizedValue), - results[i][1], - ]); - } - results = newResults; - results.sort(sortDescending); + + let newResults = []; + const endIndex = Math.min(50, results.length); + // truncate somewhat arbitrarily to 50 + for (let i = 0; i < endIndex; ++i) { + newResults.push([ + _distance(results[i][1], normalizedValue), + results[i][1], + ]); } - const newResults = []; + results = newResults; + results.sort(sortDescending); + + newResults = []; for (let i = 0; i < results.length; ++i) { if (results[i][0] == results[0][0]) { newResults.push([results[i][0], this.exactSet[results[i][1]]]); } } - return newResults; - }; - - this.add = function(value) { - const normalizedValue = this._normalizeStr(value); - if (normalizedValue in this.exactSet) { - return false; - } - - let i = this.gramSizeLower; - for (i; i < this.gramSizeUpper + 1; ++i) { - this._add(value, i); - } - }; - - this._add = function(value, gramSize) { - const normalizedValue = this._normalizeStr(value); - const items = this.items[gramSize] || []; - const index = items.length; - - items.push(0); - const gramCounts = _gramCounter(normalizedValue, gramSize); - let sumOfSquareGramCounts = 0; - let gram; - let gramCount; - - for (gram in gramCounts) { - gramCount = gramCounts[gram]; - sumOfSquareGramCounts += Math.pow(gramCount, 2); - if (gram in this.matchDict) { - this.matchDict[gram].push([index, gramCount]); - } else { - this.matchDict[gram] = [[index, gramCount]]; - } - } - const vectorNormal = Math.sqrt(sumOfSquareGramCounts); - items[index] = [vectorNormal, normalizedValue]; - this.items[gramSize] = items; - this.exactSet[normalizedValue] = value; - }; - - this._normalizeStr = function(str) { - if (Object.prototype.toString.call(str) !== '[object String]') - throw 'Must use a string as argument to FuzzySet functions'; - return str.toLowerCase(); - }; - - // return length of items in set - this.length = function() { - let count = 0; - let prop; - for (prop in this.exactSet) { - if (this.exactSet.hasOwnProperty(prop)) { - count += 1; - } - } - return count; - }; - - // return is set is empty - this.isEmpty = function() { - for (const prop in this.exactSet) { - if (this.exactSet.hasOwnProperty(prop)) { - return false; - } - } - return true; - }; - - // return list of values loaded into set - this.values = function() { - const values = []; - - for (const prop in this.exactSet) { - if (this.exactSet.hasOwnProperty(prop)) { - values.push(this.exactSet[prop]); - } - } - return values; + return newResults; }; - - // initialization - let i = this.gramSizeLower; - for (i; i < this.gramSizeUpper + 1; ++i) { - this.items[i] = []; - } - // add all the items to the set - for (i = 0; i < arr.length; ++i) { - this.add(arr[i]); - } - - return this; -} +} \ No newline at end of file From fedbab88395b39ffa46dc7da7b396e82936007a7 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 29 Jul 2017 21:55:12 -0400 Subject: [PATCH 2/3] more TS fixes --- src/generators/Generator.ts | 17 ++++++++++++----- src/generators/dom/index.ts | 4 ++-- src/generators/dom/interfaces.ts | 2 +- src/generators/interfaces.ts | 23 +++++++++++++++++++++++ src/interfaces.ts | 6 +++--- src/parse/read/directives.ts | 2 +- src/parse/read/script.ts | 3 ++- src/parse/read/style.ts | 5 +++-- src/parse/state/mustache.ts | 4 +--- src/parse/state/tag.ts | 8 +++----- src/parse/state/text.ts | 2 -- 11 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 src/generators/interfaces.ts diff --git a/src/generators/Generator.ts b/src/generators/Generator.ts index 48491e410c..330f824333 100644 --- a/src/generators/Generator.ts +++ b/src/generators/Generator.ts @@ -16,6 +16,7 @@ import DomBlock from './dom/Block'; import SsrBlock from './server-side-rendering/Block'; import Stylesheet from '../css/Stylesheet'; import { Node, GenerateOptions, Parsed, CompileOptions } from '../interfaces'; +import { Computation, TemplateProperties } from './interfaces'; const test = typeof global !== 'undefined' && global.__svelte_test; @@ -26,12 +27,18 @@ export default class Generator { name: string; options: CompileOptions; + defaultExport: Node[]; imports: Node[]; helpers: Set; components: Set; events: Set; transitions: Set; importedComponents: Map; + namespace: string; + hasComponents: boolean; + hasJs: boolean; + computations: Computation[]; + templateProperties: TemplateProperties; code: MagicString; @@ -379,9 +386,9 @@ export default class Generator { return alias; } - getUniqueNameMaker(params) { + getUniqueNameMaker(params: string[]) { const localUsedNames = new Set(params); - return name => { + return (name: string) => { if (test) name = `${name}$`; let alias = name; for ( @@ -402,8 +409,8 @@ export default class Generator { const { js } = this.parsed; const imports = this.imports; - const computations = []; - const templateProperties = {}; + const computations: Computation[] = []; + const templateProperties: TemplateProperties = {}; let namespace = null; let hasJs = !!js; @@ -459,7 +466,7 @@ export default class Generator { const visited = new Set(); - function visit(key) { + function visit(key: string) { if (!dependencies.has(key)) return; // not a computation if (visited.has(key)) return; diff --git a/src/generators/dom/index.ts b/src/generators/dom/index.ts index 073471e5b0..03cdd0d7bd 100644 --- a/src/generators/dom/index.ts +++ b/src/generators/dom/index.ts @@ -317,7 +317,7 @@ export default function dom( let scope = annotateWithScopes(expression); walk(expression, { - enter(node, parent) { + enter(node: Node, parent: Node) { if (node._scope) scope = node._scope; if ( @@ -337,7 +337,7 @@ export default function dom( } }, - leave(node) { + leave(node: Node) { if (node._scope) scope = scope.parent; }, }); diff --git a/src/generators/dom/interfaces.ts b/src/generators/dom/interfaces.ts index 03923b79bf..858680b7df 100644 --- a/src/generators/dom/interfaces.ts +++ b/src/generators/dom/interfaces.ts @@ -1,5 +1,5 @@ export interface State { - name: string; + name?: string; namespace: string; parentNode: string; parentNodes: string; diff --git a/src/generators/interfaces.ts b/src/generators/interfaces.ts new file mode 100644 index 0000000000..795122a8b5 --- /dev/null +++ b/src/generators/interfaces.ts @@ -0,0 +1,23 @@ +import { Node } from '../interfaces'; + +export interface Computation { + key: string; + deps: string[] +} + +export interface TemplateProperties { + computed?: Node; + components?: Node; + data?: Node; + events?: Node; + helpers?: Node; + methods?: Node; + namespace?: Node; + oncreate?: Node; + ondestroy?: Node; + transitions?: Node; + + // TODO remove in v2 + onrender?: Node; + onteardown?: Node; +} \ No newline at end of file diff --git a/src/interfaces.ts b/src/interfaces.ts index 4944bf8c46..fc0a6b1147 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -34,8 +34,10 @@ export interface Warning { toString: () => string; } +export type ModuleFormat = 'es' | 'amd' | 'cjs' | 'iife' | 'umd' | 'eval'; + export interface CompileOptions { - format?: string; + format?: ModuleFormat; name?: string; filename?: string; generate?: string; @@ -56,8 +58,6 @@ export interface CompileOptions { onwarn?: (warning: Warning) => void; } -export type ModuleFormat = 'es' | 'amd' | 'cjs' | 'iife' | 'umd' | 'eval'; - export interface GenerateOptions { name: string; format: ModuleFormat; diff --git a/src/parse/read/directives.ts b/src/parse/read/directives.ts index 0b61ad6350..c0c46d6af9 100644 --- a/src/parse/read/directives.ts +++ b/src/parse/read/directives.ts @@ -2,7 +2,7 @@ import { parseExpressionAt } from 'acorn'; import spaces from '../../utils/spaces'; import { Parser } from '../index'; -function readExpression(parser: Parser, start: number, quoteMark) { +function readExpression(parser: Parser, start: number, quoteMark: string|null) { let str = ''; let escaped = false; diff --git a/src/parse/read/script.ts b/src/parse/read/script.ts index 4d4a8559a1..42e8729e06 100644 --- a/src/parse/read/script.ts +++ b/src/parse/read/script.ts @@ -1,10 +1,11 @@ import { parse } from 'acorn'; import spaces from '../../utils/spaces'; import { Parser } from '../index'; +import { Node } from '../../interfaces'; const scriptClosingTag = ''; -export default function readScript(parser: Parser, start: number, attributes) { +export default function readScript(parser: Parser, start: number, attributes: Node[]) { const scriptStart = parser.index; const scriptEnd = parser.template.indexOf(scriptClosingTag, scriptStart); diff --git a/src/parse/read/style.ts b/src/parse/read/style.ts index d1882d67df..d12cd0ab41 100644 --- a/src/parse/read/style.ts +++ b/src/parse/read/style.ts @@ -1,8 +1,9 @@ import parse from 'css-tree/lib/parser/index.js'; import walk from 'css-tree/lib/utils/walk.js'; import { Parser } from '../index'; +import { Node } from '../../interfaces'; -export default function readStyle(parser: Parser, start: number, attributes) { +export default function readStyle(parser: Parser, start: number, attributes: Node[]) { const contentStart = parser.index; const styles = parser.readUntil(/<\/style>/); const contentEnd = parser.index; @@ -23,7 +24,7 @@ export default function readStyle(parser: Parser, start: number, attributes) { } // tidy up AST - walk.all(ast, node => { + walk.all(ast, (node: Node) => { if (node.loc) { node.start = node.loc.start.offset; node.end = node.loc.end.offset; diff --git a/src/parse/state/mustache.ts b/src/parse/state/mustache.ts index 716f20d288..88107af750 100644 --- a/src/parse/state/mustache.ts +++ b/src/parse/state/mustache.ts @@ -6,7 +6,7 @@ import { Node } from '../../interfaces'; const validIdentifier = /[a-zA-Z_$][a-zA-Z0-9_$]*/; -function trimWhitespace(block, trimBefore, trimAfter) { +function trimWhitespace(block: Node, trimBefore: boolean, trimAfter: boolean) { const firstChild = block.children[0]; const lastChild = block.children[block.children.length - 1]; @@ -220,6 +220,4 @@ export default function mustache(parser: Parser) { expression, }); } - - return null; } diff --git a/src/parse/state/tag.ts b/src/parse/state/tag.ts index cfa0561365..c77127b53f 100644 --- a/src/parse/state/tag.ts +++ b/src/parse/state/tag.ts @@ -78,7 +78,7 @@ export default function tag(parser: Parser) { data, }); - return null; + return; } const isClosingTag = parser.eat('/'); @@ -133,7 +133,7 @@ export default function tag(parser: Parser) { parent.end = parser.index; parser.stack.pop(); - return null; + return; } else if (disallowedContents.has(parent.name)) { // can this be a child of the parent element, or does it implicitly // close it, like `
  • one
  • two`? @@ -200,8 +200,6 @@ export default function tag(parser: Parser) { // don't push self-closing elements onto the stack parser.stack.push(element); } - - return null; } function readTagName(parser: Parser) { @@ -242,7 +240,7 @@ function readTagName(parser: Parser) { return name; } -function readAttribute(parser: Parser, uniqueNames) { +function readAttribute(parser: Parser, uniqueNames: Set) { const start = parser.index; let name = parser.readUntil(/(\s|=|\/|>)/); diff --git a/src/parse/state/text.ts b/src/parse/state/text.ts index 0f85040c21..bdd625569c 100644 --- a/src/parse/state/text.ts +++ b/src/parse/state/text.ts @@ -20,6 +20,4 @@ export default function text(parser: Parser) { type: 'Text', data: decodeCharacterReferences(data), }); - - return null; } From 91c3aa8542a2c379263f2687c497803f2c932669 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 30 Jul 2017 11:06:55 -0400 Subject: [PATCH 3/3] use Records to remove TS errors --- src/generators/Generator.ts | 14 +++++++++----- src/generators/interfaces.ts | 23 ----------------------- src/generators/shared/utils/walkHtml.ts | 2 +- src/utils/namespaces.ts | 4 +++- 4 files changed, 13 insertions(+), 30 deletions(-) delete mode 100644 src/generators/interfaces.ts diff --git a/src/generators/Generator.ts b/src/generators/Generator.ts index 330f824333..002e52bbf9 100644 --- a/src/generators/Generator.ts +++ b/src/generators/Generator.ts @@ -16,10 +16,14 @@ import DomBlock from './dom/Block'; import SsrBlock from './server-side-rendering/Block'; import Stylesheet from '../css/Stylesheet'; import { Node, GenerateOptions, Parsed, CompileOptions } from '../interfaces'; -import { Computation, TemplateProperties } from './interfaces'; const test = typeof global !== 'undefined' && global.__svelte_test; +interface Computation { + key: string; + deps: string[] +} + export default class Generator { ast: Parsed; parsed: Parsed; @@ -38,7 +42,7 @@ export default class Generator { hasComponents: boolean; hasJs: boolean; computations: Computation[]; - templateProperties: TemplateProperties; + templateProperties: Record; code: MagicString; @@ -410,7 +414,7 @@ export default class Generator { const imports = this.imports; const computations: Computation[] = []; - const templateProperties: TemplateProperties = {}; + const templateProperties: Record = {}; let namespace = null; let hasJs = !!js; @@ -444,7 +448,7 @@ export default class Generator { ['helpers', 'events', 'components', 'transitions'].forEach(key => { if (templateProperties[key]) { - templateProperties[key].value.properties.forEach((prop: node) => { + templateProperties[key].value.properties.forEach((prop: Node) => { this[key].add(prop.key.name); }); } @@ -466,7 +470,7 @@ export default class Generator { const visited = new Set(); - function visit(key: string) { + const visit = function visit(key: string) { if (!dependencies.has(key)) return; // not a computation if (visited.has(key)) return; diff --git a/src/generators/interfaces.ts b/src/generators/interfaces.ts deleted file mode 100644 index 795122a8b5..0000000000 --- a/src/generators/interfaces.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Node } from '../interfaces'; - -export interface Computation { - key: string; - deps: string[] -} - -export interface TemplateProperties { - computed?: Node; - components?: Node; - data?: Node; - events?: Node; - helpers?: Node; - methods?: Node; - namespace?: Node; - oncreate?: Node; - ondestroy?: Node; - transitions?: Node; - - // TODO remove in v2 - onrender?: Node; - onteardown?: Node; -} \ No newline at end of file diff --git a/src/generators/shared/utils/walkHtml.ts b/src/generators/shared/utils/walkHtml.ts index b7ea97aa55..fb9251b7b4 100644 --- a/src/generators/shared/utils/walkHtml.ts +++ b/src/generators/shared/utils/walkHtml.ts @@ -1,6 +1,6 @@ import { Node, Visitor } from '../../../interfaces'; -export default function walkHtml(html: Node, visitors) { +export default function walkHtml(html: Node, visitors: Record) { function visit(node: Node) { const visitor = visitors[node.type]; if (!visitor) throw new Error(`Not implemented: ${node.type}`); diff --git a/src/utils/namespaces.ts b/src/utils/namespaces.ts index dc5cee2752..a038dfa345 100644 --- a/src/utils/namespaces.ts +++ b/src/utils/namespaces.ts @@ -20,4 +20,6 @@ export const validNamespaces = [ xmlns, ]; -export default { html, mathml, svg, xlink, xml, xmlns }; +const namespaces: Record = { html, mathml, svg, xlink, xml, xmlns }; + +export default namespaces;