diff --git a/src/data/bucket/symbol_bucket.js b/src/data/bucket/symbol_bucket.js index 17aa10c4d13..3945e7f6f26 100644 --- a/src/data/bucket/symbol_bucket.js +++ b/src/data/bucket/symbol_bucket.js @@ -18,7 +18,7 @@ import Anchor from '../../symbol/anchor'; import { getSizeData } from '../../symbol/symbol_size'; import { register } from '../../util/web_worker_transfer'; import EvaluationParameters from '../../style/evaluation_parameters'; -import {Formatted} from '../../style-spec/expression/definitions/formatted'; +import Formatted from '../../style-spec/expression/types/formatted'; import type { diff --git a/src/style-spec/expression/definitions/coercion.js b/src/style-spec/expression/definitions/coercion.js index 58f062551b5..17ba74b043f 100644 --- a/src/style-spec/expression/definitions/coercion.js +++ b/src/style-spec/expression/definitions/coercion.js @@ -11,7 +11,6 @@ import type ParsingContext from '../parsing_context'; import type EvaluationContext from '../evaluation_context'; import type { Value } from '../values'; import type { Type } from '../types'; -import { Formatted, FormattedSection } from './formatted'; const types = { 'to-boolean': BooleanType, @@ -84,15 +83,6 @@ class Coercion implements Expression { } } throw new RuntimeError(error || `Could not parse color from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`); - } else if (this.type.kind === 'formatted') { - let input; - for (const arg of this.args) { - input = arg.evaluate(ctx); - if (typeof input === 'string') { - return new Formatted([new FormattedSection(input, null, null)]); - } - } - throw new RuntimeError(`Could not parse formatted text from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`); } else if (this.type.kind === 'number') { let value = null; for (const arg of this.args) { diff --git a/src/style-spec/expression/definitions/collator.js b/src/style-spec/expression/definitions/collator.js index c99f9e3a8df..bc7ae8ad8b8 100644 --- a/src/style-spec/expression/definitions/collator.js +++ b/src/style-spec/expression/definitions/collator.js @@ -1,73 +1,14 @@ // @flow import { StringType, BooleanType, CollatorType } from '../types'; +import Collator from '../types/collator'; import type { Expression } from '../expression'; import type EvaluationContext from '../evaluation_context'; import type ParsingContext from '../parsing_context'; import type { Type } from '../types'; -// Flow type declarations for Intl cribbed from -// https://github.com/facebook/flow/issues/1270 - -declare var Intl: { - Collator: Class -} - -declare class Intl$Collator { - constructor ( - locales?: string | string[], - options?: CollatorOptions - ): Intl$Collator; - - static ( - locales?: string | string[], - options?: CollatorOptions - ): Intl$Collator; - - compare (a: string, b: string): number; - - resolvedOptions(): any; -} - -type CollatorOptions = { - localeMatcher?: 'lookup' | 'best fit', - usage?: 'sort' | 'search', - sensitivity?: 'base' | 'accent' | 'case' | 'variant', - ignorePunctuation?: boolean, - numeric?: boolean, - caseFirst?: 'upper' | 'lower' | 'false' -} - -export class Collator { - locale: string | null; - sensitivity: 'base' | 'accent' | 'case' | 'variant'; - collator: Intl$Collator; - - constructor(caseSensitive: boolean, diacriticSensitive: boolean, locale: string | null) { - if (caseSensitive) - this.sensitivity = diacriticSensitive ? 'variant' : 'case'; - else - this.sensitivity = diacriticSensitive ? 'accent' : 'base'; - - this.locale = locale; - this.collator = new Intl.Collator(this.locale ? this.locale : [], - { sensitivity: this.sensitivity, usage: 'search' }); - } - - compare(lhs: string, rhs: string): number { - return this.collator.compare(lhs, rhs); - } - - resolvedLocale(): string { - // We create a Collator without "usage: search" because we don't want - // the search options encoded in our result (e.g. "en-u-co-search") - return new Intl.Collator(this.locale ? this.locale : []) - .resolvedOptions().locale; - } -} - -export class CollatorExpression implements Expression { +export default class CollatorExpression implements Expression { type: Type; caseSensitive: Expression; diacriticSensitive: Expression; diff --git a/src/style-spec/expression/definitions/formatted.js b/src/style-spec/expression/definitions/format.js similarity index 77% rename from src/style-spec/expression/definitions/formatted.js rename to src/style-spec/expression/definitions/format.js index ef4a74b86c3..071c2110b4c 100644 --- a/src/style-spec/expression/definitions/formatted.js +++ b/src/style-spec/expression/definitions/format.js @@ -1,6 +1,7 @@ // @flow import { NumberType, ValueType, FormattedType, array, StringType } from '../types'; +import Formatted, { FormattedSection } from '../types/formatted'; import { toString } from '../values'; import type { Expression } from '../expression'; @@ -8,49 +9,13 @@ import type EvaluationContext from '../evaluation_context'; import type ParsingContext from '../parsing_context'; import type { Type } from '../types'; -export class FormattedSection { - text: string - scale: number | null - fontStack: string | null - - constructor(text: string, scale: number | null, fontStack: string | null) { - this.text = text; - this.scale = scale; - this.fontStack = fontStack; - } -} - -export class Formatted { - sections: Array - - constructor(sections: Array) { - this.sections = sections; - } - - toString(): string { - return this.sections.map(section => section.text).join(''); - } - - serialize() { - const serialized = ["format"]; - for (const section of this.sections) { - serialized.push(section.text); - const fontStack = section.fontStack ? - ["literal", section.fontStack.split(',')] : - null; - serialized.push({ "text-font": fontStack, "font-scale": section.scale }); - } - return serialized; - } -} - type FormattedSectionExpression = { text: Expression, scale: Expression | null; font: Expression | null; } -export class FormatExpression implements Expression { +export default class FormatExpression implements Expression { type: Type; sections: Array; diff --git a/src/style-spec/expression/definitions/index.js b/src/style-spec/expression/definitions/index.js index 107249f40ce..da07b7bc9bd 100644 --- a/src/style-spec/expression/definitions/index.js +++ b/src/style-spec/expression/definitions/index.js @@ -36,8 +36,8 @@ import { LessThanOrEqual, GreaterThanOrEqual } from './comparison'; -import { CollatorExpression } from './collator'; -import { FormatExpression } from './formatted'; +import CollatorExpression from './collator'; +import FormatExpression from './format'; import Length from './length'; import type { Varargs } from '../compound_expression'; diff --git a/src/style-spec/expression/definitions/literal.js b/src/style-spec/expression/definitions/literal.js index 2c8668d0e52..015a4cac93d 100644 --- a/src/style-spec/expression/definitions/literal.js +++ b/src/style-spec/expression/definitions/literal.js @@ -2,7 +2,7 @@ import assert from 'assert'; import { isValue, typeOf, Color } from '../values'; -import { Formatted } from './formatted'; +import Formatted from '../types/formatted'; import type { Type } from '../types'; import type { Value } from '../values'; diff --git a/src/style-spec/expression/parsing_context.js b/src/style-spec/expression/parsing_context.js index 646c2a39da2..b12de8a1002 100644 --- a/src/style-spec/expression/parsing_context.js +++ b/src/style-spec/expression/parsing_context.js @@ -9,14 +9,14 @@ import Assertion from './definitions/assertion'; import Coercion from './definitions/coercion'; import EvaluationContext from './evaluation_context'; import CompoundExpression from './compound_expression'; -import { CollatorExpression } from './definitions/collator'; +import CollatorExpression from './definitions/collator'; +import FormatExpression from './definitions/format'; import {isGlobalPropertyConstant, isFeatureConstant} from './is_constant'; import Var from './definitions/var'; import type {Expression, ExpressionRegistry} from './expression'; import type {Type} from './types'; -import {FormatExpression} from './definitions/formatted'; /** * State associated parsing at a given point in an expression tree. diff --git a/src/style-spec/expression/types/collator.js b/src/style-spec/expression/types/collator.js new file mode 100644 index 00000000000..40e80ec3214 --- /dev/null +++ b/src/style-spec/expression/types/collator.js @@ -0,0 +1,61 @@ +// @flow + +// Flow type declarations for Intl cribbed from +// https://github.com/facebook/flow/issues/1270 + +declare var Intl: { + Collator: Class +}; + +declare class Intl$Collator { + constructor ( + locales?: string | string[], + options?: CollatorOptions + ): Intl$Collator; + + static ( + locales?: string | string[], + options?: CollatorOptions + ): Intl$Collator; + + compare (a: string, b: string): number; + + resolvedOptions(): any; +} + +type CollatorOptions = { + localeMatcher?: 'lookup' | 'best fit', + usage?: 'sort' | 'search', + sensitivity?: 'base' | 'accent' | 'case' | 'variant', + ignorePunctuation?: boolean, + numeric?: boolean, + caseFirst?: 'upper' | 'lower' | 'false' +} + +export default class Collator { + locale: string | null; + sensitivity: 'base' | 'accent' | 'case' | 'variant'; + collator: Intl$Collator; + + constructor(caseSensitive: boolean, diacriticSensitive: boolean, locale: string | null) { + if (caseSensitive) + this.sensitivity = diacriticSensitive ? 'variant' : 'case'; + else + this.sensitivity = diacriticSensitive ? 'accent' : 'base'; + + this.locale = locale; + this.collator = new Intl.Collator(this.locale ? this.locale : [], + { sensitivity: this.sensitivity, usage: 'search' }); + } + + compare(lhs: string, rhs: string): number { + return this.collator.compare(lhs, rhs); + } + + resolvedLocale(): string { + // We create a Collator without "usage: search" because we don't want + // the search options encoded in our result (e.g. "en-u-co-search") + return new Intl.Collator(this.locale ? this.locale : []) + .resolvedOptions().locale; + } +} diff --git a/src/style-spec/expression/types/formatted.js b/src/style-spec/expression/types/formatted.js new file mode 100644 index 00000000000..7637e2717cf --- /dev/null +++ b/src/style-spec/expression/types/formatted.js @@ -0,0 +1,37 @@ +// @flow + +export class FormattedSection { + text: string; + scale: number | null; + fontStack: string | null; + + constructor(text: string, scale: number | null, fontStack: string | null) { + this.text = text; + this.scale = scale; + this.fontStack = fontStack; + } +} + +export default class Formatted { + sections: Array; + + constructor(sections: Array) { + this.sections = sections; + } + + toString(): string { + return this.sections.map(section => section.text).join(''); + } + + serialize() { + const serialized = ["format"]; + for (const section of this.sections) { + serialized.push(section.text); + const fontStack = section.fontStack ? + ["literal", section.fontStack.split(',')] : + null; + serialized.push({ "text-font": fontStack, "font-scale": section.scale }); + } + return serialized; + } +} diff --git a/src/style-spec/expression/values.js b/src/style-spec/expression/values.js index 80e1d99dffa..3f8b5c874c2 100644 --- a/src/style-spec/expression/values.js +++ b/src/style-spec/expression/values.js @@ -3,9 +3,9 @@ import assert from 'assert'; import Color from '../util/color'; -import { Collator } from './definitions/collator'; -import { Formatted } from './definitions/formatted'; -import { NullType, NumberType, StringType, BooleanType, ColorType, ObjectType, ValueType, CollatorType, array } from './types'; +import Collator from './types/collator'; +import Formatted from './types/formatted'; +import { NullType, NumberType, StringType, BooleanType, ColorType, ObjectType, ValueType, CollatorType, FormattedType, array } from './types'; import type { Type } from './types'; @@ -28,7 +28,7 @@ export function validateRGBA(r: mixed, g: mixed, b: mixed, a?: mixed): ?string { return null; } -export type Value = null | string | boolean | number | Color | Collator | $ReadOnlyArray | { +[string]: Value } +export type Value = null | string | boolean | number | Color | Collator | Formatted | $ReadOnlyArray | { +[string]: Value } export function isValue(mixed: mixed): boolean { if (mixed === null) { @@ -43,6 +43,8 @@ export function isValue(mixed: mixed): boolean { return true; } else if (mixed instanceof Collator) { return true; + } else if (mixed instanceof Formatted) { + return true; } else if (Array.isArray(mixed)) { for (const item of mixed) { if (!isValue(item)) { @@ -75,6 +77,8 @@ export function typeOf(value: Value): Type { return ColorType; } else if (value instanceof Collator) { return CollatorType; + } else if (value instanceof Formatted) { + return FormattedType; } else if (Array.isArray(value)) { const length = value.length; let itemType: ?Type; diff --git a/src/style/style_layer/background_style_layer_properties.js b/src/style/style_layer/background_style_layer_properties.js index 64644162963..c4c9b36ab37 100644 --- a/src/style/style_layer/background_style_layer_properties.js +++ b/src/style/style_layer/background_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type PaintProps = {| diff --git a/src/style/style_layer/circle_style_layer_properties.js b/src/style/style_layer/circle_style_layer_properties.js index cfa515be11a..65ea36aeb18 100644 --- a/src/style/style_layer/circle_style_layer_properties.js +++ b/src/style/style_layer/circle_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type PaintProps = {| diff --git a/src/style/style_layer/fill_extrusion_style_layer_properties.js b/src/style/style_layer/fill_extrusion_style_layer_properties.js index fbfd2a08f5c..c8e27695110 100644 --- a/src/style/style_layer/fill_extrusion_style_layer_properties.js +++ b/src/style/style_layer/fill_extrusion_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type PaintProps = {| diff --git a/src/style/style_layer/fill_style_layer_properties.js b/src/style/style_layer/fill_style_layer_properties.js index c321dede0d8..d0173c989b3 100644 --- a/src/style/style_layer/fill_style_layer_properties.js +++ b/src/style/style_layer/fill_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type PaintProps = {| diff --git a/src/style/style_layer/heatmap_style_layer_properties.js b/src/style/style_layer/heatmap_style_layer_properties.js index a2cc3bacdca..76b6079e550 100644 --- a/src/style/style_layer/heatmap_style_layer_properties.js +++ b/src/style/style_layer/heatmap_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type PaintProps = {| diff --git a/src/style/style_layer/hillshade_style_layer_properties.js b/src/style/style_layer/hillshade_style_layer_properties.js index 0c7b96f850d..39d94286ad8 100644 --- a/src/style/style_layer/hillshade_style_layer_properties.js +++ b/src/style/style_layer/hillshade_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type PaintProps = {| diff --git a/src/style/style_layer/layer_properties.js.ejs b/src/style/style_layer/layer_properties.js.ejs index a916e899726..573538879dc 100644 --- a/src/style/style_layer/layer_properties.js.ejs +++ b/src/style/style_layer/layer_properties.js.ejs @@ -20,7 +20,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; <% if (layoutProperties.length) { -%> export type LayoutProps = {| diff --git a/src/style/style_layer/line_style_layer_properties.js b/src/style/style_layer/line_style_layer_properties.js index 468b937ecc0..a9fb955ef94 100644 --- a/src/style/style_layer/line_style_layer_properties.js +++ b/src/style/style_layer/line_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type LayoutProps = {| "line-cap": DataConstantProperty<"butt" | "round" | "square">, diff --git a/src/style/style_layer/raster_style_layer_properties.js b/src/style/style_layer/raster_style_layer_properties.js index 97d46906570..b813a73459c 100644 --- a/src/style/style_layer/raster_style_layer_properties.js +++ b/src/style/style_layer/raster_style_layer_properties.js @@ -15,7 +15,7 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type PaintProps = {| diff --git a/src/style/style_layer/symbol_style_layer_properties.js b/src/style/style_layer/symbol_style_layer_properties.js index adf350a093e..9a1c4a64109 100644 --- a/src/style/style_layer/symbol_style_layer_properties.js +++ b/src/style/style_layer/symbol_style_layer_properties.js @@ -15,13 +15,13 @@ import { import type Color from '../../style-spec/util/color'; -import type {Formatted} from '../../style-spec/expression/definitions/formatted'; +import type Formatted from '../../style-spec/expression/types/formatted'; export type LayoutProps = {| "symbol-placement": DataConstantProperty<"point" | "line" | "line-center">, "symbol-spacing": DataConstantProperty, "symbol-avoid-edges": DataConstantProperty, - "symbol-z-order": DataConstantProperty, + "symbol-z-order": DataConstantProperty<"viewport-y" | "source">, "icon-allow-overlap": DataConstantProperty, "icon-ignore-placement": DataConstantProperty, "icon-optional": DataConstantProperty, diff --git a/src/symbol/mergelines.js b/src/symbol/mergelines.js index 3468cf74f30..a3bde56367f 100644 --- a/src/symbol/mergelines.js +++ b/src/symbol/mergelines.js @@ -1,7 +1,7 @@ // @flow import type {SymbolFeature} from '../data/bucket/symbol_bucket'; -import {Formatted} from '../style-spec/expression/definitions/formatted'; +import Formatted from '../style-spec/expression/types/formatted'; export default function (features: Array): Array { const leftIndex: {[string]: number} = {}; diff --git a/src/symbol/shaping.js b/src/symbol/shaping.js index fc6036fed9d..b1e7e1f26aa 100644 --- a/src/symbol/shaping.js +++ b/src/symbol/shaping.js @@ -9,7 +9,7 @@ import { plugin as rtlTextPlugin } from '../source/rtl_text_plugin'; import type {StyleGlyph} from '../style/style_glyph'; import type {ImagePosition} from '../render/image_atlas'; -import {Formatted} from '../style-spec/expression/definitions/formatted'; +import Formatted from '../style-spec/expression/types/formatted'; const WritingMode = { horizontal: 1, diff --git a/src/symbol/symbol_layout.js b/src/symbol/symbol_layout.js index 8aef10f1228..91f10722cab 100644 --- a/src/symbol/symbol_layout.js +++ b/src/symbol/symbol_layout.js @@ -17,7 +17,7 @@ import classifyRings from '../util/classify_rings'; import EXTENT from '../data/extent'; import SymbolBucket from '../data/bucket/symbol_bucket'; import EvaluationParameters from '../style/evaluation_parameters'; -import {Formatted} from '../style-spec/expression/definitions/formatted'; +import Formatted from '../style-spec/expression/types/formatted'; import {SIZE_PACK_FACTOR} from './symbol_size'; import type {Shaping, PositionedIcon} from './shaping'; diff --git a/src/symbol/transform_text.js b/src/symbol/transform_text.js index e7058086c90..b2904d9fcc9 100644 --- a/src/symbol/transform_text.js +++ b/src/symbol/transform_text.js @@ -4,7 +4,7 @@ import { plugin as rtlTextPlugin } from '../source/rtl_text_plugin'; import type SymbolStyleLayer from '../style/style_layer/symbol_style_layer'; import type {Feature} from '../style-spec/expression'; -import {Formatted} from '../style-spec/expression/definitions/formatted'; +import Formatted from '../style-spec/expression/types/formatted'; function transformText(text: string, layer: SymbolStyleLayer, feature: Feature) { const transform = layer.layout.get('text-transform').evaluate(feature, {});