-
-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add vertical-align
in format expression
#900
base: main
Are you sure you want to change the base?
Changes from 15 commits
d785d2b
cfd9111
7593fa9
6065c88
a4630d0
071c277
1a5cf7c
4460a7e
695efdf
c74afe5
b55daaa
2429fe8
4cf94a5
8e957bd
37e1178
ef5ac81
653c90a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ import { | |
ColorType, | ||
ResolvedImageType, | ||
} from '../types'; | ||
import {Formatted, FormattedSection} from '../types/formatted'; | ||
import {Formatted, FormattedSection, VERTICAL_ALIGN_OPTIONS, VerticalAlign} from '../types/formatted'; | ||
import {valueToString, typeOf} from '../values'; | ||
|
||
import type {Expression} from '../expression'; | ||
|
@@ -22,6 +22,7 @@ type FormattedSectionExpression = { | |
scale: Expression | null; | ||
font: Expression | null; | ||
textColor: Expression | null; | ||
verticalAlign: Expression | null; | ||
}; | ||
|
||
export class FormatExpression implements Expression { | ||
|
@@ -69,10 +70,21 @@ export class FormatExpression implements Expression { | |
if (!textColor) return null; | ||
} | ||
|
||
let verticalAlign = null; | ||
if (arg['vertical-align']) { | ||
if (typeof arg['vertical-align'] === 'string' && !VERTICAL_ALIGN_OPTIONS.includes(arg['vertical-align'] as VerticalAlign)) { | ||
return context.error(`'vertical-align' must be one of: 'bottom', 'center', 'top' but found '${arg['vertical-align']}' instead.`) as null; | ||
} | ||
|
||
verticalAlign = context.parse(arg['vertical-align'], 1, StringType); | ||
if (!verticalAlign) return null; | ||
} | ||
|
||
const lastExpression = sections[sections.length - 1]; | ||
lastExpression.scale = scale; | ||
lastExpression.font = font; | ||
lastExpression.textColor = textColor; | ||
lastExpression.verticalAlign = verticalAlign; | ||
} else { | ||
const content = context.parse(args[i], 1, ValueType); | ||
if (!content) return null; | ||
|
@@ -82,7 +94,7 @@ export class FormatExpression implements Expression { | |
return context.error('Formatted text type must be \'string\', \'value\', \'image\' or \'null\'.') as null; | ||
|
||
nextTokenMayBeObject = true; | ||
sections.push({content, scale: null, font: null, textColor: null}); | ||
sections.push({content, scale: null, font: null, textColor: null, verticalAlign: null}); | ||
} | ||
} | ||
|
||
|
@@ -93,15 +105,23 @@ export class FormatExpression implements Expression { | |
const evaluateSection = section => { | ||
const evaluatedContent = section.content.evaluate(ctx); | ||
if (typeOf(evaluatedContent) === ResolvedImageType) { | ||
return new FormattedSection('', evaluatedContent, null, null, null); | ||
return new FormattedSection( | ||
'', | ||
evaluatedContent, | ||
null, | ||
null, | ||
null, | ||
section.verticalAlign ? section.verticalAlign.evaluate(ctx) : null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is this different than other properties? Why not passing null here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the instantiation of |
||
); | ||
} | ||
|
||
return new FormattedSection( | ||
valueToString(evaluatedContent), | ||
null, | ||
section.scale ? section.scale.evaluate(ctx) : null, | ||
section.font ? section.font.evaluate(ctx).join(',') : null, | ||
section.textColor ? section.textColor.evaluate(ctx) : null | ||
section.textColor ? section.textColor.evaluate(ctx) : null, | ||
section.verticalAlign ? section.verticalAlign.evaluate(ctx) : null | ||
); | ||
}; | ||
|
||
|
@@ -120,6 +140,9 @@ export class FormatExpression implements Expression { | |
if (section.textColor) { | ||
fn(section.textColor); | ||
} | ||
if (section.verticalAlign) { | ||
fn(section.verticalAlign); | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -1,19 +1,24 @@ | ||||
import type {Color} from '../../expression/types/color'; | ||||
import type {ResolvedImage} from '../types/resolved_image'; | ||||
|
||||
export const VERTICAL_ALIGN_OPTIONS = ['bottom', 'center', 'top'] as const; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be defined in the v8 spec file and not here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see a way how to do it - there is no other expression where this kind of definition lives in
|
||||
export type VerticalAlign = typeof VERTICAL_ALIGN_OPTIONS[number]; | ||||
|
||||
export class FormattedSection { | ||||
text: string; | ||||
image: ResolvedImage | null; | ||||
scale: number | null; | ||||
fontStack: string | null; | ||||
textColor: Color | null; | ||||
verticalAlign: VerticalAlign | null; | ||||
|
||||
constructor(text: string, image: ResolvedImage | null, scale: number | null, fontStack: string | null, textColor: Color | null) { | ||||
constructor(text: string, image: ResolvedImage | null, scale: number | null, fontStack: string | null, textColor: Color | null, verticalAlign: VerticalAlign | null) { | ||||
this.text = text; | ||||
this.image = image; | ||||
this.scale = scale; | ||||
this.fontStack = fontStack; | ||||
this.textColor = textColor; | ||||
this.verticalAlign = verticalAlign; | ||||
} | ||||
} | ||||
|
||||
|
@@ -25,7 +30,7 @@ export class Formatted { | |||
} | ||||
|
||||
static fromString(unformatted: string): Formatted { | ||||
return new Formatted([new FormattedSection(unformatted, null, null, null, null)]); | ||||
return new Formatted([new FormattedSection(unformatted, null, null, null, null, null)]); | ||||
} | ||||
|
||||
isEmpty(): boolean { | ||||
|
HarelM marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3226,10 +3226,10 @@ | |
} | ||
}, | ||
"format": { | ||
"doc": "Returns a `formatted` string for displaying mixed-format text in the `text-field` property. The input may contain a string literal or expression, including an [`'image'`](#image) expression. Strings may be followed by a style override object that supports the following properties:\n\n- `\"text-font\"`: Overrides the font stack specified by the root layout property.\n\n- `\"text-color\"`: Overrides the color specified by the root paint property.\n\n- `\"font-scale\"`: Applies a scaling factor on `text-size` as specified by the root layout property.\n\n - [Change the case of labels](https://maplibre.org/maplibre-gl-js/docs/examples/change-case-of-labels/)\n\n - [Display and style rich text labels](https://maplibre.org/maplibre-gl-js/docs/examples/display-and-style-rich-text-labels/)", | ||
"doc": "Returns a `formatted` string for displaying mixed-format text in the `text-field` property. The input may contain a string literal or expression, including an [`'image'`](#image) expression. Strings may be followed by a style override object that supports the following properties:\n\n- `\"text-font\"`: Overrides the font stack specified by the root layout property.\n\n- `\"text-color\"`: Overrides the color specified by the root paint property.\n\n- `\"font-scale\"`: Applies a scaling factor on `text-size` as specified by the root layout property.\n\n- `\"vertical-align\"`: Aligns vertically text section or image in relation to the row it belongs to. Possible values are: \n\t- `\"bottom\"` *default*: text baseline or image bottom are in line.\n\t- `\"center\"`: image center or text center are in line.\n\t- `\"top\"`: image top and text top are in line.\n\n - [Change the case of labels](https://maplibre.org/maplibre-gl-js/docs/examples/change-case-of-labels/)\n\n - [Display and style rich text labels](https://maplibre.org/maplibre-gl-js/docs/examples/display-and-style-rich-text-labels/)", | ||
"example": { | ||
"syntax": { | ||
"method": ["value", "{ \"text-font\": string, \"text-color\": color, \"font-scale\": number }", "..."], | ||
"method": ["value", "{ \"text-font\": string, \"text-color\": color, \"font-scale\": number, \"vertical-align\": string }", "..."], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we put enum possible values instead of string? Not sure how the handled in different places... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed
|
||
"result": "formatted" | ||
}, | ||
"value": ["format", ["upcase", ["get", "FacilityName"]], {"font-scale": 0.8}, "\n\n", {}, ["downcase", ["get", "Comments"]], {"font-scale": 0.6}] | ||
|
@@ -3256,6 +3256,11 @@ | |
"android": "7.3.0", | ||
"ios": "4.10.0" | ||
}, | ||
"vertical-align": { | ||
"js": "https://github.com/maplibre/maplibre-gl-js/issues/5043", | ||
"android": "https://github.com/maplibre/maplibre-native/issues/3055", | ||
"ios": "https://github.com/maplibre/maplibre-native/issues/3055" | ||
}, | ||
"image": { | ||
"js": "1.6.0", | ||
"android": "8.6.0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
{ | ||
"expression": [ | ||
"format", | ||
"a", | ||
{ | ||
"vertical-align": [ | ||
"get", | ||
"vertical-align" | ||
] | ||
} | ||
], | ||
"inputs": [ | ||
[ | ||
{}, | ||
{ | ||
"properties": { | ||
"vertical-align": "center" | ||
} | ||
} | ||
], | ||
[ | ||
{}, | ||
{ | ||
"properties": { | ||
"vertical-align": "top" | ||
} | ||
} | ||
] | ||
], | ||
"expected": { | ||
"compiled": { | ||
"result": "success", | ||
"isFeatureConstant": false, | ||
"isZoomConstant": true, | ||
"type": "formatted" | ||
}, | ||
"outputs": [ | ||
{ | ||
"sections": [ | ||
{ | ||
"text": "a", | ||
"image": null, | ||
"scale": null, | ||
"fontStack": null, | ||
"textColor": null, | ||
"verticalAlign": "center" | ||
} | ||
] | ||
}, | ||
{ | ||
"sections": [ | ||
{ | ||
"text": "a", | ||
"image": null, | ||
"scale": null, | ||
"fontStack": null, | ||
"textColor": null, | ||
"verticalAlign": "top" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this if be moved to the parse code to keep this as clean as the other if statements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did try to move it to parse - however then it shouldn't be placed in parse fn itself, but I found that it is better to add
enum
validation, like for array in other places.However, to make it possible there are multiple changes that has to be made. Moreover the validation for enum is a bit different, because other validations are based on types, and enum validation requires access to the value, so it is possible to compare with enum values.
You can see how it looks here: tomtom-forks#2
After making this try I actually think that having it in
format.ts
, as it is now, is better and much simpler. Also in similar fashion the validation is implemented forinterpolate
expression (link to the file).