more tidying up

pull/2252/head
Richard Harris 7 years ago
parent ba33f278be
commit a236794763

@ -2,9 +2,8 @@ import MagicString, { Bundle } from 'magic-string';
import { walk, childKeys } from 'estree-walker';
import { getLocator } from 'locate-character';
import Stats from '../Stats';
import { reserved } from '../utils/names';
import { globals, reserved } from '../utils/names';
import { namespaces, validNamespaces } from '../utils/namespaces';
import { removeNode } from '../utils/removeNode';
import wrapModule from './wrapModule';
import { create_scopes, extract_names, Scope } from './utils/scope';
import Stylesheet from './css/Stylesheet';
@ -13,14 +12,13 @@ import Fragment from './nodes/Fragment';
import internal_exports from './internal-exports';
import { Node, Ast, CompileOptions, Var, Warning } from '../interfaces';
import error from '../utils/error';
import getCodeFrame from '../utils/getCodeFrame';
import get_code_frame from '../utils/get_code_frame';
import flatten_reference from './utils/flatten_reference';
import is_reference from 'is-reference';
import TemplateScope from './nodes/shared/TemplateScope';
import fuzzymatch from '../utils/fuzzymatch';
import { remove_indentation, add_indentation } from '../utils/indentation';
import getObject from '../utils/getObject';
import globalWhitelist from '../utils/globalWhitelist';
import get_object from './utils/get_object';
type ComponentOptions = {
namespace?: string;
@ -36,6 +34,34 @@ childKeys.EachBlock = childKeys.IfBlock = ['children', 'else'];
childKeys.Attribute = ['value'];
childKeys.ExportNamedDeclaration = ['declaration', 'specifiers'];
function remove_node(code: MagicString, start: number, end: number, body: Node, node: Node) {
const i = body.indexOf(node);
if (i === -1) throw new Error('node not in list');
let a;
let b;
if (body.length === 1) {
// remove everything, leave {}
a = start;
b = end;
} else if (i === 0) {
// remove everything before second node, including comments
a = start;
while (/\s/.test(code.original[a])) a += 1;
b = body[i].end;
while (/[\s,]/.test(code.original[b])) b += 1;
} else {
// remove the end of the previous node to the end of this one
a = body[i - 1].end;
b = node.end;
}
code.remove(a, b);
return;
}
export default class Component {
stats: Stats;
warnings: Warning[];
@ -392,7 +418,7 @@ export default class Component {
const start = this.locator(pos.start);
const end = this.locator(pos.end);
const frame = getCodeFrame(this.source, start.line - 1, start.column);
const frame = get_code_frame(this.source, start.line - 1, start.column);
this.warnings.push({
code: warning.code,
@ -412,7 +438,7 @@ export default class Component {
content.body.forEach(node => {
if (node.type === 'ImportDeclaration') {
// imports need to be hoisted out of the IIFE
removeNode(code, content.start, content.end, content.body, node);
remove_node(code, content.start, content.end, content.body, node);
this.imports.push(node);
}
});
@ -453,7 +479,7 @@ export default class Component {
code.remove(node.start, node.declaration.start);
} else {
removeNode(code, content.start, content.end, content.body, node);
remove_node(code, content.start, content.end, content.body, node);
node.specifiers.forEach(specifier => {
const variable = this.var_lookup.get(specifier.local.name);
@ -662,10 +688,10 @@ export default class Component {
deep = node.left.type === 'MemberExpression';
names = deep
? [getObject(node.left).name]
? [get_object(node.left).name]
: extract_names(node.left);
} else if (node.type === 'UpdateExpression') {
names = [getObject(node.argument).name];
names = [get_object(node.argument).name];
}
if (names) {
@ -699,7 +725,7 @@ export default class Component {
}
if (is_reference(node, parent)) {
const object = getObject(node);
const object = get_object(node);
const { name } = object;
if (name[0] === '$' && !scope.has(name)) {
@ -1028,14 +1054,14 @@ export default class Component {
}
if (node.type === 'AssignmentExpression') {
const identifier = getObject(node.left)
const identifier = get_object(node.left)
assignee_nodes.add(identifier);
assignees.add(identifier.name);
} else if (node.type === 'UpdateExpression') {
const identifier = getObject(node.argument);
const identifier = get_object(node.argument);
assignees.add(identifier.name);
} else if (is_reference(node, parent)) {
const identifier = getObject(node);
const identifier = get_object(node);
if (!assignee_nodes.has(identifier)) {
const { name } = identifier;
const owner = scope.find_owner(name);
@ -1149,7 +1175,7 @@ export default class Component {
if (this.var_lookup.has(name)) return;
if (template_scope && template_scope.names.has(name)) return;
if (globalWhitelist.has(name)) return;
if (globals.has(name)) return;
let message = `'${name}' is not defined`;
if (!this.ast.instance) message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;

@ -1,13 +1,24 @@
import MagicString from 'magic-string';
import { walk } from 'estree-walker';
import Selector from './Selector';
import hash from '../../utils/hash';
import removeCSSPrefix from '../../utils/removeCSSPrefix';
import Element from '../nodes/Element';
import { Node, Ast } from '../../interfaces';
import Component from '../Component';
const isKeyframesNode = (node: Node) => removeCSSPrefix(node.name) === 'keyframes'
function remove_css_prefox(name: string): string {
return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
}
const isKeyframesNode = (node: Node) => remove_css_prefox(node.name) === 'keyframes';
// https://github.com/darkskyapp/string-hash/blob/master/index.js
function hash(str: string): string {
let hash = 5381;
let i = str.length;
while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
return (hash >>> 0).toString(36);
}
class Rule {
selectors: Selector[];
@ -97,7 +108,7 @@ class Declaration {
}
transform(code: MagicString, keyframes: Map<string, string>) {
const property = this.node.property && removeCSSPrefix(this.node.property.toLowerCase());
const property = this.node.property && remove_css_prefox(this.node.property.toLowerCase());
if (property === 'animation' || property === 'animation-name') {
this.node.value.children.forEach((block: Node) => {
if (block.type === 'Identifier') {

@ -1,5 +1,5 @@
import Node from './shared/Node';
import getObject from '../../utils/getObject';
import get_object from '../utils/get_object';
import Expression from './shared/Expression';
import Component from '../Component';
import TemplateScope from './shared/TemplateScope';
@ -27,7 +27,7 @@ export default class Binding extends Node {
let obj;
let prop;
const { name } = getObject(this.expression.node);
const { name } = get_object(this.expression.node);
this.isContextual = scope.names.has(name);
// make sure we track this as a mutable ref

@ -1,4 +1,4 @@
import isVoidElementName from '../../utils/isVoidElementName';
import { is_void } from '../../utils/names';
import Node from './shared/Node';
import Attribute from './Attribute';
import Binding from './Binding';
@ -557,7 +557,7 @@ export default class Element extends Node {
code: 'invalid-binding',
message: `'${binding.name}' is not a valid binding on SVG elements`
});
} else if (isVoidElementName(this.name)) {
} else if (is_void(this.name)) {
component.error(binding, {
code: 'invalid-binding',
message: `'${binding.name}' is not a valid binding on void elements like <${this.name}>. Use a wrapper element instead`

@ -4,12 +4,12 @@ import is_reference from 'is-reference';
import flatten_reference from '../../utils/flatten_reference';
import { create_scopes, Scope, extract_names } from '../../utils/scope';
import { Node } from '../../../interfaces';
import globalWhitelist from '../../../utils/globalWhitelist';
import { globals } from '../../../utils/names';
import deindent from '../../utils/deindent';
import Wrapper from '../../render-dom/wrappers/shared/Wrapper';
import sanitize from '../../../utils/sanitize';
import { sanitize } from '../../../utils/names';
import TemplateScope from './TemplateScope';
import getObject from '../../../utils/getObject';
import get_object from '../../utils/get_object';
import { nodes_match } from '../../../utils/nodes_match';
import Block from '../../render-dom/Block';
@ -123,7 +123,7 @@ export default class Expression {
if (scope.has(name)) return;
if (globalWhitelist.has(name) && !component.var_lookup.has(name)) return;
if (globals.has(name) && !component.var_lookup.has(name)) return;
if (name[0] === '$' && template_scope.names.has(name.slice(1))) {
component.error(node, {
@ -164,10 +164,10 @@ export default class Expression {
if (node.type === 'AssignmentExpression') {
deep = node.left.type === 'MemberExpression';
names = deep
? [getObject(node.left).name]
? [get_object(node.left).name]
: extract_names(node.left);
} else if (node.type === 'UpdateExpression') {
const { name } = getObject(node.argument);
const { name } = get_object(node.argument);
names = [name];
}
}
@ -257,7 +257,7 @@ export default class Expression {
const { name, nodes } = flatten_reference(node);
if (scope.has(name)) return;
if (globalWhitelist.has(name) && !component.var_lookup.has(name)) return;
if (globals.has(name) && !component.var_lookup.has(name)) return;
if (function_expression) {
if (template_scope.names.has(name)) {
@ -289,7 +289,7 @@ export default class Expression {
if (function_expression) {
if (node.type === 'AssignmentExpression') {
const names = node.left.type === 'MemberExpression'
? [getObject(node.left).name]
? [get_object(node.left).name]
: extract_names(node.left);
if (node.operator === '=' && nodes_match(node.left, node.right)) {
@ -311,7 +311,7 @@ export default class Expression {
});
}
} else if (node.type === 'UpdateExpression') {
const { name } = getObject(node.argument);
const { name } = get_object(node.argument);
if (scope.declarations.has(name)) return;

@ -7,10 +7,10 @@ import { CompileOptions } from '../../interfaces';
import { walk } from 'estree-walker';
import { stringify_props } from '../utils/stringify_props';
import add_to_set from '../utils/add_to_set';
import getObject from '../../utils/getObject';
import get_object from '../utils/get_object';
import { extract_names } from '../utils/scope';
import { nodes_match } from '../../utils/nodes_match';
import sanitize from '../../utils/sanitize';
import { sanitize } from '../../utils/names';
export default function dom(
component: Component,
@ -168,7 +168,7 @@ export default function dom(
let names = [];
if (node.left.type === 'MemberExpression') {
const left_object_name = getObject(node.left).name;
const left_object_name = get_object(node.left).name;
left_object_name && (names = [left_object_name]);
} else {
names = extract_names(node.left);
@ -197,7 +197,7 @@ export default function dom(
}
else if (node.type === 'UpdateExpression') {
const { name } = getObject(node.argument);
const { name } = get_object(node.argument);
if (scope.find_owner(name) !== component.instance_scope) return;

@ -1,13 +1,13 @@
import Binding from '../../../nodes/Binding';
import ElementWrapper from '.';
import { dimensions } from '../../../../utils/patterns';
import getObject from '../../../../utils/getObject';
import get_object from '../../../utils/get_object';
import Block from '../../Block';
import Node from '../../../nodes/shared/Node';
import Renderer from '../../Renderer';
import flatten_reference from '../../../utils/flatten_reference';
import { get_tail } from '../../../../utils/get_tail_snippet';
import EachBlock from '../../../nodes/EachBlock';
import { Node as INode } from '../../../../interfaces';
// TODO this should live in a specific binding
const readOnlyMediaAttributes = new Set([
@ -17,6 +17,12 @@ const readOnlyMediaAttributes = new Set([
'played'
]);
function get_tail(node: INode) {
const end = node.end;
while (node.type === 'MemberExpression') node = node.object;
return { start: node.end, end };
}
export default class BindingWrapper {
node: Binding;
parent: ElementWrapper;
@ -52,13 +58,13 @@ export default class BindingWrapper {
if (node.isContextual) {
// we need to ensure that the each block creates a context including
// the list and the index, if they're not otherwise referenced
const { name } = getObject(this.node.expression.node);
const { name } = get_object(this.node.expression.node);
const eachBlock = this.parent.node.scope.getOwner(name);
(eachBlock as EachBlock).has_binding = true;
}
this.object = getObject(this.node.expression.node).name;
this.object = get_object(this.node.expression.node).name;
// TODO unfortunate code is necessary because we need to use `ctx`
// inside the fragment, but not inside the <script>

@ -3,8 +3,7 @@ import Element from '../../../nodes/Element';
import Wrapper from '../shared/Wrapper';
import Block from '../../Block';
import Node from '../../../nodes/shared/Node';
import { quote_prop_if_necessary, quote_name_if_necessary } from '../../../../utils/names';
import isVoidElementName from '../../../../utils/isVoidElementName';
import { is_void, quote_prop_if_necessary, quote_name_if_necessary, sanitize } from '../../../../utils/names';
import FragmentWrapper from '../Fragment';
import { stringify, escapeHTML, escape } from '../../../../utils/stringify';
import TextWrapper from '../Text';
@ -20,7 +19,6 @@ import add_to_set from '../../../utils/add_to_set';
import addEventHandlers from '../shared/addEventHandlers';
import addActions from '../shared/addActions';
import create_debugging_comment from '../shared/create_debugging_comment';
import sanitize from '../../../../utils/sanitize';
import { get_context_merger } from '../shared/get_context_merger';
const events = [
@ -339,7 +337,7 @@ export default class ElementWrapper extends Wrapper {
open += ` ${fix_attribute_casing(attr.node.name)}${attr.stringify()}`
});
if (isVoidElementName(wrapper.node.name)) return open + '>';
if (is_void(wrapper.node.name)) return open + '>';
return `${open}>${wrapper.fragment.nodes.map(toHTML).join('')}</${wrapper.node.name}>`;
}

@ -3,15 +3,14 @@ import Renderer from '../../Renderer';
import Block from '../../Block';
import InlineComponent from '../../../nodes/InlineComponent';
import FragmentWrapper from '../Fragment';
import { quote_name_if_necessary, quote_prop_if_necessary } from '../../../../utils/names';
import { quote_name_if_necessary, quote_prop_if_necessary, sanitize } from '../../../../utils/names';
import { stringify_props } from '../../../utils/stringify_props';
import add_to_set from '../../../utils/add_to_set';
import deindent from '../../../utils/deindent';
import Attribute from '../../../nodes/Attribute';
import getObject from '../../../../utils/getObject';
import get_object from '../../../utils/get_object';
import flatten_reference from '../../../utils/flatten_reference';
import create_debugging_comment from '../shared/create_debugging_comment';
import sanitize from '../../../../utils/sanitize';
import { get_context_merger } from '../shared/get_context_merger';
import EachBlock from '../../../nodes/EachBlock';
import TemplateScope from '../../../nodes/shared/TemplateScope';
@ -46,7 +45,7 @@ export default class InlineComponentWrapper extends Wrapper {
if (binding.isContextual) {
// we need to ensure that the each block creates a context including
// the list and the index, if they're not otherwise referenced
const { name } = getObject(binding.expression.node);
const { name } = get_object(binding.expression.node);
const eachBlock = this.node.scope.getOwner(name);
(eachBlock as EachBlock).has_binding = true;

@ -4,9 +4,9 @@ import Block from '../Block';
import Slot from '../../nodes/Slot';
import FragmentWrapper from './Fragment';
import deindent from '../../utils/deindent';
import sanitize from '../../../utils/sanitize';
import { sanitize } from '../../../utils/names';
import add_to_set from '../../utils/add_to_set';
import get_slot_data from '../../../utils/get_slot_data';
import get_slot_data from '../../utils/get_slot_data';
import { stringify_props } from '../../utils/stringify_props';
import Expression from '../../nodes/shared/Expression';

@ -1,5 +1,4 @@
import { quote_prop_if_necessary, quote_name_if_necessary } from '../../../utils/names';
import isVoidElementName from '../../../utils/isVoidElementName';
import { is_void, quote_prop_if_necessary, quote_name_if_necessary } from '../../../utils/names';
import Attribute from '../../nodes/Attribute';
import Node from '../../nodes/shared/Node';
import { snip } from '../../../utils/snip';
@ -149,7 +148,7 @@ export default function(node, renderer, options) {
renderer.render(node.children, options);
}
if (!isVoidElementName(node.name)) {
if (!is_void(node.name)) {
renderer.append(`</${node.name}>`);
}
}

@ -1,5 +1,5 @@
import { quote_prop_if_necessary } from '../../../utils/names';
import get_slot_data from '../../../utils/get_slot_data';
import get_slot_data from '../../utils/get_slot_data';
export default function(node, renderer, options) {
const name = node.attributes.find(attribute => attribute.name === 'name');

@ -1,6 +1,6 @@
import { Node } from '../interfaces';
import { Node } from '../../interfaces';
export default function getObject(node: Node) {
export default function get_object(node: Node) {
while (node.type === 'ParenthesizedExpression') node = node.expression;
while (node.type === 'MemberExpression') node = node.object;
return node;

@ -1,5 +1,5 @@
import { snip } from './snip';
import { stringify_attribute } from './stringify_attribute';
import { snip } from '../../utils/snip';
import { stringify_attribute } from '../../utils/stringify_attribute';
export default function get_slot_data(attributes, is_ssr: boolean) {
return attributes

@ -2,7 +2,7 @@ import readExpression from '../read/expression';
import readScript from '../read/script';
import readStyle from '../read/style';
import { decodeCharacterReferences } from '../utils/html';
import isVoidElementName from '../../utils/isVoidElementName';
import { is_void } from '../../utils/names';
import { Parser } from '../index';
import { Node } from '../../interfaces';
import fuzzymatch from '../../utils/fuzzymatch';
@ -146,7 +146,7 @@ export default function tag(parser: Parser) {
parser.allowWhitespace();
if (isClosingTag) {
if (isVoidElementName(name)) {
if (is_void(name)) {
parser.error({
code: `invalid-void-content`,
message: `<${name}> is a void element and cannot have children, or a closing tag`
@ -244,7 +244,7 @@ export default function tag(parser: Parser) {
parser.current().children.push(element);
const selfClosing = parser.eat('/') || isVoidElementName(name);
const selfClosing = parser.eat('/') || is_void(name);
parser.eat('>', true);

@ -1,5 +1,4 @@
import { SourceMap } from 'magic-string';
import replaceAsync from '../utils/replaceAsync';
export interface PreprocessorGroup {
markup?: (options: {
@ -37,6 +36,39 @@ function parseAttributes(str: string) {
return attrs;
}
interface Replacement {
offset: number;
length: number;
replacement: string;
}
async function replace_async(str: string, re: RegExp, func: (...any) => Promise<string>) {
const replacements: Promise<Replacement>[] = [];
str.replace(re, (...args) => {
replacements.push(
func(...args).then(
res =>
<Replacement>({
offset: args[args.length - 2],
length: args[0].length,
replacement: res,
})
)
);
return '';
});
let out = '';
let lastEnd = 0;
for (const { offset, length, replacement } of await Promise.all(
replacements
)) {
out += str.slice(lastEnd, offset) + replacement;
lastEnd = offset + length;
}
out += str.slice(lastEnd);
return out;
}
export default async function preprocess(
source: string,
preprocessor: PreprocessorGroup | PreprocessorGroup[],
@ -61,7 +93,7 @@ export default async function preprocess(
}
for (const fn of script) {
source = await replaceAsync(
source = await replace_async(
source,
/<script([^]*?)>([^]*?)<\/script>/gi,
async (match, attributes, content) => {
@ -77,7 +109,7 @@ export default async function preprocess(
}
for (const fn of style) {
source = await replaceAsync(
source = await replace_async(
source,
/<style([^]*?)>([^]*?)<\/style>/gi,
async (match, attributes, content) => {

@ -1,5 +1,5 @@
import { locate } from 'locate-character';
import getCodeFrame from '../utils/getCodeFrame';
import get_code_frame from '../utils/get_code_frame';
class CompileError extends Error {
code: string;
@ -34,7 +34,7 @@ export default function error(message: string, props: {
error.pos = props.start;
error.filename = props.filename;
error.frame = getCodeFrame(props.source, start.line - 1, start.column);
error.frame = get_code_frame(props.source, start.line - 1, start.column);
throw error;
}

@ -53,30 +53,28 @@ function levenshtein(str1: string, str2: string) {
return current.pop();
}
const _nonWordRe = /[^\w, ]+/;
const non_word_regex = /[^\w, ]+/;
function _iterateGrams(value: string, gramSize: number) {
gramSize = gramSize || 2;
const simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-';
const lenDiff = gramSize - simplified.length;
function iterate_grams(value: string, gram_size = 2) {
const simplified = '-' + value.toLowerCase().replace(non_word_regex, '') + '-';
const len_diff = gram_size - simplified.length;
const results = [];
if (lenDiff > 0) {
for (let i = 0; i < lenDiff; ++i) {
if (len_diff > 0) {
for (let i = 0; i < len_diff; ++i) {
value += '-';
}
}
for (let i = 0; i < simplified.length - gramSize + 1; ++i) {
results.push(simplified.slice(i, i + gramSize));
for (let i = 0; i < simplified.length - gram_size + 1; ++i) {
results.push(simplified.slice(i, i + gram_size));
}
return results;
}
function _gramCounter(value: string, gramSize: number) {
function gram_counter(value: string, gram_size = 2) {
// return an object where key=gram, value=number of occurrences
gramSize = gramSize || 2;
const result = {};
const grams = _iterateGrams(value, gramSize);
const grams = iterate_grams(value, gram_size);
let i = 0;
for (i; i < grams.length; ++i) {
@ -89,25 +87,21 @@ function _gramCounter(value: string, gramSize: number) {
return result;
}
function sortDescending(a, b) {
function sort_descending(a, b) {
return b[0] - a[0];
}
class FuzzySet {
exactSet: object;
matchDict: object;
items: object;
exact_set = {};
match_dict = {};
items = {};
constructor(arr: string[]) {
// define all the object functions and attributes
this.exactSet = {};
this.matchDict = {};
this.items = {};
// initialization
for (let i = GRAM_SIZE_LOWER; i < GRAM_SIZE_UPPER + 1; ++i) {
this.items[i] = [];
}
// add all the items to the set
for (let i = 0; i < arr.length; ++i) {
this.add(arr[i]);
@ -115,8 +109,8 @@ class FuzzySet {
}
add(value: string) {
const normalizedValue = value.toLowerCase();
if (normalizedValue in this.exactSet) {
const normalized_value = value.toLowerCase();
if (normalized_value in this.exact_set) {
return false;
}
@ -126,35 +120,35 @@ class FuzzySet {
}
}
_add(value: string, gramSize: number) {
const normalizedValue = value.toLowerCase();
const items = this.items[gramSize] || [];
_add(value: string, gram_size: number) {
const normalized_value = value.toLowerCase();
const items = this.items[gram_size] || [];
const index = items.length;
items.push(0);
const gramCounts = _gramCounter(normalizedValue, gramSize);
let sumOfSquareGramCounts = 0;
const gram_counts = gram_counter(normalized_value, gram_size);
let sum_of_square_gram_counts = 0;
let gram;
let gramCount;
let gram_count;
for (gram in gramCounts) {
gramCount = gramCounts[gram];
sumOfSquareGramCounts += Math.pow(gramCount, 2);
if (gram in this.matchDict) {
this.matchDict[gram].push([index, gramCount]);
for (gram in gram_counts) {
gram_count = gram_counts[gram];
sum_of_square_gram_counts += Math.pow(gram_count, 2);
if (gram in this.match_dict) {
this.match_dict[gram].push([index, gram_count]);
} else {
this.matchDict[gram] = [[index, gramCount]];
this.match_dict[gram] = [[index, gram_count]];
}
}
const vectorNormal = Math.sqrt(sumOfSquareGramCounts);
items[index] = [vectorNormal, normalizedValue];
this.items[gramSize] = items;
this.exactSet[normalizedValue] = value;
const vector_normal = Math.sqrt(sum_of_square_gram_counts);
items[index] = [vector_normal, normalized_value];
this.items[gram_size] = items;
this.exact_set[normalized_value] = value;
};
get(value: string) {
const normalizedValue = value.toLowerCase();
const result = this.exactSet[normalizedValue];
const normalized_value = value.toLowerCase();
const result = this.exact_set[normalized_value];
if (result) {
return [[1, result]];
@ -163,11 +157,11 @@ class FuzzySet {
let results = [];
// start with high gram size and if there are no results, go to lower gram sizes
for (
let gramSize = GRAM_SIZE_UPPER;
gramSize >= GRAM_SIZE_LOWER;
--gramSize
let gram_size = GRAM_SIZE_UPPER;
gram_size >= GRAM_SIZE_LOWER;
--gram_size
) {
results = this.__get(value, gramSize);
results = this.__get(value, gram_size);
if (results) {
return results;
}
@ -175,68 +169,68 @@ class FuzzySet {
return null;
}
__get(value: string, gramSize: number) {
const normalizedValue = value.toLowerCase();
__get(value: string, gram_size: number) {
const normalized_value = value.toLowerCase();
const matches = {};
const gramCounts = _gramCounter(normalizedValue, gramSize);
const items = this.items[gramSize];
let sumOfSquareGramCounts = 0;
const gram_counts = gram_counter(normalized_value, gram_size);
const items = this.items[gram_size];
let sum_of_square_gram_counts = 0;
let gram;
let gramCount;
let gram_count;
let i;
let index;
let otherGramCount;
for (gram in gramCounts) {
gramCount = gramCounts[gram];
sumOfSquareGramCounts += Math.pow(gramCount, 2);
if (gram in this.matchDict) {
for (i = 0; i < this.matchDict[gram].length; ++i) {
index = this.matchDict[gram][i][0];
otherGramCount = this.matchDict[gram][i][1];
let other_gram_count;
for (gram in gram_counts) {
gram_count = gram_counts[gram];
sum_of_square_gram_counts += Math.pow(gram_count, 2);
if (gram in this.match_dict) {
for (i = 0; i < this.match_dict[gram].length; ++i) {
index = this.match_dict[gram][i][0];
other_gram_count = this.match_dict[gram][i][1];
if (index in matches) {
matches[index] += gramCount * otherGramCount;
matches[index] += gram_count * other_gram_count;
} else {
matches[index] = gramCount * otherGramCount;
matches[index] = gram_count * other_gram_count;
}
}
}
}
const vectorNormal = Math.sqrt(sumOfSquareGramCounts);
const vector_normal = Math.sqrt(sum_of_square_gram_counts);
let results = [];
let matchScore;
let match_score;
// build a results list of [score, str]
for (const matchIndex in matches) {
matchScore = matches[matchIndex];
match_score = matches[matchIndex];
results.push([
matchScore / (vectorNormal * items[matchIndex][0]),
match_score / (vector_normal * items[matchIndex][0]),
items[matchIndex][1],
]);
}
results.sort(sortDescending);
results.sort(sort_descending);
let newResults = [];
const endIndex = Math.min(50, results.length);
let new_results = [];
const end_index = Math.min(50, results.length);
// truncate somewhat arbitrarily to 50
for (let i = 0; i < endIndex; ++i) {
newResults.push([
_distance(results[i][1], normalizedValue),
for (let i = 0; i < end_index; ++i) {
new_results.push([
_distance(results[i][1], normalized_value),
results[i][1],
]);
}
results = newResults;
results.sort(sortDescending);
results = new_results;
results.sort(sort_descending);
newResults = [];
new_results = [];
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]]]);
new_results.push([results[i][0], this.exact_set[results[i][1]]]);
}
}
return newResults;
return new_results;
};
}

@ -4,7 +4,7 @@ function tabsToSpaces(str: string) {
return str.replace(/^\t+/, match => match.split('\t').join(' '));
}
export default function getCodeFrame(
export default function get_code_frame(
source: string,
line: number,
column: number

@ -1,12 +0,0 @@
import { Node } from '../interfaces';
export function get_tail_snippet(node: Node) {
const { start, end } = get_tail(node);
return `[✂${start}-${end}✂]`;
}
export function get_tail(node: Node) {
const end = node.end;
while (node.type === 'MemberExpression') node = node.object;
return { start: node.end, end };
}

@ -1,28 +0,0 @@
export default new Set([
'Array',
'Boolean',
'console',
'Date',
'decodeURI',
'decodeURIComponent',
'encodeURI',
'encodeURIComponent',
'Infinity',
'Intl',
'isFinite',
'isNaN',
'JSON',
'Map',
'Math',
'NaN',
'Number',
'Object',
'parseFloat',
'parseInt',
'process',
'Promise',
'RegExp',
'Set',
'String',
'undefined',
]);

@ -1,8 +0,0 @@
// https://github.com/darkskyapp/string-hash/blob/master/index.js
export default function hash(str: string): string {
let hash = 5381;
let i = str.length;
while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
return (hash >>> 0).toString(36);
}

@ -1,5 +0,0 @@
const voidElementNames = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
export default function isVoidElementName(name: string) {
return voidElementNames.test(name) || name.toLowerCase() === '!doctype';
}

@ -1,18 +1,34 @@
import { isIdentifierStart, isIdentifierChar } from 'acorn';
import full_char_code_at from './full_char_code_at';
function is_valid(str: string): boolean {
let i = 0;
while (i < str.length) {
const code = full_char_code_at(str, i);
if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true)) return false;
i += code <= 0xffff ? 1 : 2;
}
return true;
}
export const globals = new Set([
'Array',
'Boolean',
'console',
'Date',
'decodeURI',
'decodeURIComponent',
'encodeURI',
'encodeURIComponent',
'Infinity',
'Intl',
'isFinite',
'isNaN',
'JSON',
'Map',
'Math',
'NaN',
'Number',
'Object',
'parseFloat',
'parseInt',
'process',
'Promise',
'RegExp',
'Set',
'String',
'undefined',
]);
export const reserved = new Set([
'arguments',
@ -65,12 +81,35 @@ export const reserved = new Set([
'yield',
]);
export function quote_name_if_necessary(name) {
const void_element_names = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;
export function is_void(name: string) {
return void_element_names.test(name) || name.toLowerCase() === '!doctype';
}
function is_valid(str: string): boolean {
let i = 0;
while (i < str.length) {
const code = full_char_code_at(str, i);
if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true)) return false;
i += code <= 0xffff ? 1 : 2;
}
return true;
}
export function quote_name_if_necessary(name: string) {
if (!is_valid(name)) return `"${name}"`;
return name;
}
export function quote_prop_if_necessary(name) {
export function quote_prop_if_necessary(name: string) {
if (!is_valid(name)) return `["${name}"]`;
return `.${name}`;
}
export function sanitize(name: string) {
return name.replace(/[^a-zA-Z]+/g, '_').replace(/^_/, '').replace(/_$/, '');
}

@ -1,3 +0,0 @@
export default function(name: string): string {
return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
}

@ -1,36 +0,0 @@
import MagicString from 'magic-string';
import { Node } from '../interfaces';
export function removeNode(
code: MagicString,
start: number,
end: number,
body: Node,
node: Node
) {
const i = body.indexOf(node);
if (i === -1) throw new Error('node not in list');
let a;
let b;
if (body.length === 1) {
// remove everything, leave {}
a = start;
b = end;
} else if (i === 0) {
// remove everything before second node, including comments
a = start;
while (/\s/.test(code.original[a])) a += 1;
b = body[i].end;
while (/[\s,]/.test(code.original[b])) b += 1;
} else {
// remove the end of the previous node to the end of this one
a = body[i - 1].end;
b = node.end;
}
code.remove(a, b);
return;
}

@ -1,38 +0,0 @@
// asynchronous String#replace
export default async function replaceAsync(
str: string,
re: RegExp,
func: (...any) => Promise<string>
) {
const replacements: Promise<Replacement>[] = [];
str.replace(re, (...args) => {
replacements.push(
func(...args).then(
res =>
<Replacement>({
offset: args[args.length - 2],
length: args[0].length,
replacement: res,
})
)
);
return '';
});
let out = '';
let lastEnd = 0;
for (const { offset, length, replacement } of await Promise.all(
replacements
)) {
out += str.slice(lastEnd, offset) + replacement;
lastEnd = offset + length;
}
out += str.slice(lastEnd);
return out;
}
interface Replacement {
offset: number;
length: number;
replacement: string;
}

@ -1,3 +0,0 @@
export default function sanitize(name) {
return name.replace(/[^a-zA-Z]+/g, '_').replace(/^_/, '').replace(/_$/, '');
}
Loading…
Cancel
Save