[Geoserver-devel] Brainstorming substitution variables for styling languages

Hi [0],
with this mail I’d like to start a discussion on “substitution variables” for styling languages,
something like the lesscss concept, which would look something like:

// Variables
@link-color: #428bca; // sea blue
@link-color-hover: darken(@link-color, 10%);

// Usage
a,
.link {
color: @link-color;
}
a:hover {
color: @link-color-hover;
}
.widget {
color: #fff;
background: @link-color;
}

I’d like to have something like that, but more flexible. Limitations I see in the above:

  • It’s language specific

  • Seems a bit rigid in terms of usage, local to the style, or requiring a new concept, like an “import”, to be shared among multiple files [1]

  • It’s a new concept when we already have something similar around

So, here is what I’d propose instead: let’s use the environment variable support, it’s already there, we are already using it in the styles, it just needs some “love”.
Limits I can see so far:
a) Lacks a centralized way to set default values
b) Requires calling a function
c) It is limited in usage to places accepting expressions
d) Can only expand literals

About a), setting the defaults should be done outside of styles imho, or it would drive us back to
requiring imports. So what about having a “variables configuration” (please help with names…
“contexts” or “preset” maybe?) that would allow centralizing server side variable definitions[2].
And maybe allow also to define if the variable can be substituted from the request (env)
or it is meant to be a constat that the client side cannot redefine.
Something like this:

water=blue
land=lightgray
_river-width=10;

Where “river_width” would be a constant (not overridable from outside), the trailing underscore making
that variable “private”.
Maybe the context file could allow workspace specific overrides, e.g., when one is requesting a
layer in workspace “foo” there might be a different definitions of the values in there.

Going to b), I would not get nuts trying to add a nicer way to use variables in SLD, a function
call is probably good enough in an language not design to be succint/hand written.
GeoCSS wise, allowing @varname to be a shortcut to [env(‘varname’)] could be a nice way to make
this functionality easier to use (I believe other languages could do something similar).

As for c), the significant places where expressions can not be used could be:

  • Vendor options
  • Scale denominators

I see no problem in evolving those to use Expression as we already did in other places only
allowing for static values, but this could be done later, what we have today would already
pack a significant amount of functionality.

Finally, d) wise, env could be expanded to interpret a CQL expression, and/or we could
have a new type of function knowing its contents might be expression (suggestions welcomed).

While we are here, I’d also like to discuss how to switch from a preset to another.
Like, for example, using the context/preset, one might want to switch from a map color theme to
another, or even turn off all labels [3]. But how to do that? Some ideas:

a) By a request parameter similar to env, e.g. “&env_context:grayscale”
b) By allowing the definition of the desired preset in a layer group definition (similar to having it in a workspace)
c) By creating a new “derived style”, e.g., a custom styling language that would accept only two inputs,
a base style and a different preset (e.g., style “abc” is like “foo”, but using preset “pre2”)

Personally I like all 3, a) allows for dynamic behavior, b) makes sense while creating basemaps,
c) allows for quick definition of a new named style that can be exposed in WMS.

Aaand… that’s all for now, the mail is too long already :-p

Well, let me know what you think about it

Cheers
Andrea

[0] Yes, this is one of my long mails!

[1] I’m hesitant to look at imports in the GeoServer concept as they are somehow remeniscent
of file system relationships, and it seems we are trying to get off the filesystem and
its “relative path” support at the catalog level (although if we want we could still do that, assuming
global to be the root and workspaces to be subfolders, so that “@import /foo/bar.css” would
import bar.css found in the bar workspace, or for a file system data directory,
$DATA_DIR/workspaces/foo/styles/bar.css

[2] Could be as simple as a property file, but other implementations are plausible too

[3] Could be done by placing a variable in the filter of the rule containg the symbolizer, e.g.:
[@labelsOn = true] { label: [name]; … }

==
GeoServer Professional Services from the experts! Visit
http://goo.gl/it488V for more information.

Ing. Andrea Aime

@geowolf
Technical Lead

GeoSolutions S.A.S.
Via di Montramito 3/A
55054 Massarosa (LU)
phone: +39 0584 962313

fax: +39 0584 1660272
mob: +39 339 8844549

http://www.geo-solutions.it
http://twitter.com/geosolutions_it

AVVERTENZE AI SENSI DEL D.Lgs. 196/2003

Le informazioni contenute in questo messaggio di posta elettronica e/o nel/i file/s allegato/i sono da considerarsi strettamente riservate. Il loro utilizzo è consentito esclusivamente al destinatario del messaggio, per le finalità indicate nel messaggio stesso. Qualora riceviate questo messaggio senza esserne il destinatario, Vi preghiamo cortesemente di darcene notizia via e-mail e di procedere alla distruzione del messaggio stesso, cancellandolo dal Vostro sistema. Conservare il messaggio stesso, divulgarlo anche in parte, distribuirlo ad altri soggetti, copiarlo, od utilizzarlo per finalità diverse, costituisce comportamento contrario ai principi dettati dal D.Lgs. 196/2003.

The information in this message and/or attachments, is intended solely for the attention and use of the named addressee(s) and may be confidential or proprietary in nature or covered by the provisions of privacy act (Legislative Decree June, 30 2003, no.196 - Italy’s New Data Protection Code).Any use not in accord with its purpose, any disclosure, reproduction, copying, distribution, or either dissemination, either whole or partial, is strictly forbidden except previous formal approval of the named addressee(s). If you are not the intended recipient, please contact immediately the sender by telephone, fax or e-mail and delete the information in this message that has been received in error. The sender does not give any warranty or accept liability as the content, accuracy or completeness of sent messages and accepts no responsibility for changes made after they were sent or for other risks which arise as a result of e-mail transmission, viruses, etc.


I like the idea, how about a “theme” defining a set of env variables that can be referenced by styles in a request.

Idea: Could we list alternate themes against a layer group? To cover the usual day/night or mobile/desktop cases?

···

On 7 May 2017 at 11:36, Andrea Aime <andrea.aime@anonymised.com> wrote:

Hi [0],
with this mail I’d like to start a discussion on “substitution variables” for styling languages,
something like the lesscss concept, which would look something like:

// Variables
@link-color: #428bca; // sea blue
@link-color-hover: darken(@link-color, 10%);

// Usage
a,
.link {
color: @link-color;
}
a:hover {
color: @link-color-hover;
}
.widget {
color: #fff;
background: @link-color;
}

I’d like to have something like that, but more flexible. Limitations I see in the above:

  • It’s language specific

  • Seems a bit rigid in terms of usage, local to the style, or requiring a new concept, like an “import”, to be shared among multiple files [1]

  • It’s a new concept when we already have something similar around

So, here is what I’d propose instead: let’s use the environment variable support, it’s already there, we are already using it in the styles, it just needs some “love”.
Limits I can see so far:
a) Lacks a centralized way to set default values
b) Requires calling a function
c) It is limited in usage to places accepting expressions
d) Can only expand literals

About a), setting the defaults should be done outside of styles imho, or it would drive us back to
requiring imports. So what about having a “variables configuration” (please help with names…
“contexts” or “preset” maybe?) that would allow centralizing server side variable definitions[2].
And maybe allow also to define if the variable can be substituted from the request (env)
or it is meant to be a constat that the client side cannot redefine.
Something like this:

water=blue
land=lightgray
_river-width=10;

Where “river_width” would be a constant (not overridable from outside), the trailing underscore making
that variable “private”.
Maybe the context file could allow workspace specific overrides, e.g., when one is requesting a
layer in workspace “foo” there might be a different definitions of the values in there.

Going to b), I would not get nuts trying to add a nicer way to use variables in SLD, a function
call is probably good enough in an language not design to be succint/hand written.
GeoCSS wise, allowing @varname to be a shortcut to [env(‘varname’)] could be a nice way to make
this functionality easier to use (I believe other languages could do something similar).

As for c), the significant places where expressions can not be used could be:

  • Vendor options
  • Scale denominators

I see no problem in evolving those to use Expression as we already did in other places only
allowing for static values, but this could be done later, what we have today would already
pack a significant amount of functionality.

Finally, d) wise, env could be expanded to interpret a CQL expression, and/or we could
have a new type of function knowing its contents might be expression (suggestions welcomed).

While we are here, I’d also like to discuss how to switch from a preset to another.
Like, for example, using the context/preset, one might want to switch from a map color theme to
another, or even turn off all labels [3]. But how to do that? Some ideas:

a) By a request parameter similar to env, e.g. “&env_context:grayscale”
b) By allowing the definition of the desired preset in a layer group definition (similar to having it in a workspace)
c) By creating a new “derived style”, e.g., a custom styling language that would accept only two inputs,
a base style and a different preset (e.g., style “abc” is like “foo”, but using preset “pre2”)

Personally I like all 3, a) allows for dynamic behavior, b) makes sense while creating basemaps,
c) allows for quick definition of a new named style that can be exposed in WMS.

Aaand… that’s all for now, the mail is too long already :-p

Well, let me know what you think about it

Cheers
Andrea

[0] Yes, this is one of my long mails!

[1] I’m hesitant to look at imports in the GeoServer concept as they are somehow remeniscent
of file system relationships, and it seems we are trying to get off the filesystem and
its “relative path” support at the catalog level (although if we want we could still do that, assuming
global to be the root and workspaces to be subfolders, so that “@import /foo/bar.css” would
import bar.css found in the bar workspace, or for a file system data directory,
$DATA_DIR/workspaces/foo/styles/bar.css

[2] Could be as simple as a property file, but other implementations are plausible too

[3] Could be done by placing a variable in the filter of the rule containg the symbolizer, e.g.:
[@labelsOn = true] { label: [name]; … }

==
GeoServer Professional Services from the experts! Visit
http://goo.gl/it488V for more information.

Ing. Andrea Aime

@geowolf
Technical Lead

GeoSolutions S.A.S.
Via di Montramito 3/A
55054 Massarosa (LU)
phone: +39 0584 962313

fax: +39 0584 1660272
mob: +39 339 8844549

http://www.geo-solutions.it
http://twitter.com/geosolutions_it

AVVERTENZE AI SENSI DEL D.Lgs. 196/2003

Le informazioni contenute in questo messaggio di posta elettronica e/o nel/i file/s allegato/i sono da considerarsi strettamente riservate. Il loro utilizzo è consentito esclusivamente al destinatario del messaggio, per le finalità indicate nel messaggio stesso. Qualora riceviate questo messaggio senza esserne il destinatario, Vi preghiamo cortesemente di darcene notizia via e-mail e di procedere alla distruzione del messaggio stesso, cancellandolo dal Vostro sistema. Conservare il messaggio stesso, divulgarlo anche in parte, distribuirlo ad altri soggetti, copiarlo, od utilizzarlo per finalità diverse, costituisce comportamento contrario ai principi dettati dal D.Lgs. 196/2003.

The information in this message and/or attachments, is intended solely for the attention and use of the named addressee(s) and may be confidential or proprietary in nature or covered by the provisions of privacy act (Legislative Decree June, 30 2003, no.196 - Italy’s New Data Protection Code).Any use not in accord with its purpose, any disclosure, reproduction, copying, distribution, or either dissemination, either whole or partial, is strictly forbidden except previous formal approval of the named addressee(s). If you are not the intended recipient, please contact immediately the sender by telephone, fax or e-mail and delete the information in this message that has been received in error. The sender does not give any warranty or accept liability as the content, accuracy or completeness of sent messages and accepts no responsibility for changes made after they were sent or for other risks which arise as a result of e-mail transmission, viruses, etc.



Check out the vibrant tech community on one of the world’s most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot


Geoserver-devel mailing list
Geoserver-devel@anonymised.com.366…sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel


Jody Garnett

Hi [0],

with this mail I'd like to start a discussion on "substitution variables"
for styling languages,
something like the lesscss concept
<Features In-Depth | Less.js, which would look
something like:

Note that YSLD already supports something similar, using "define", so we
may be able to learn from the approach used there:

define: &bgcolor #333366

polygon:
  fill:color: *bgcolor

Since SyledLayerDescriptor does not currently have the concept of
variables, this substitution is done when the YSLD is parsed into SLD.
One other thing that has been useful in YSLD is the ability to make a
variable that represents a block of YSLD, (e.g. a line-color, label, font,
and line-width), which is often used to style shared elements in a
situation with many filters (usually in a case where recode doesn't quite
work). Unfortunately, this doesn't seem like it would be feasible, as it
requires structural elements that are not the same between languages.

One question is what level would this new variable substitution be at:
parsing-level (such that variable definitions don't get included when
converting between languages) or language-level (such that variable
definitions are preserved when converting between languages). The former
opens up the possibility of more powerful variable constructs, but the
latter is more flexible and requires less specialization between languages.
The environment variable approach you mention below would require the
latter.

I'd like to have something like that, but more flexible. Limitations I see
in the above:

   - It's language specific

I don't see any reliable way of having variable substitiution that is not

at least somewhat language specific (if only in syntax), because of the
different ways in which different styling languages treat individual
elements, and reserved characters.

   - Seems a bit rigid in terms of usage, local to the style, or
   requiring a new concept, like an "import", to be shared among multiple
   files [1]
   - It's a new concept when we already have something similar around

So, here is what I'd propose instead: let's use the environment variable
support, it's already there, we are already using it in the styles, it just
needs some "love".

Seems like a good approach. This also helps get around the
language-specific issue, since existing languages should all have some way
of handling environment variables.

Limits I can see so far:

a) Lacks a centralized way to set default values
b) Requires calling a function
c) It is limited in usage to places accepting expressions
d) Can only expand literals

c) and d) seem the most problematic.

About a), setting the defaults should be done outside of styles imho, or
it would drive us back to
requiring imports. So what about having a "variables configuration"
(please help with names...
"contexts" or "preset" maybe?) that would allow centralizing server side
variable definitions[2].
And maybe allow also to define if the variable can be substituted from the
request (env)
or it is meant to be a constat that the client side cannot redefine.

I imaging this could be useful beyond just environment variables used in
styling. At present, it seems like it could tie in with some of the module
status stuff.

As for c), the significant places where expressions can not be used could
be:
* Vendor options
* Scale denominators

I see no problem in evolving those to use Expression as we already did in
other places only
allowing for static values, but this could be done later, what we have
today would already
pack a significant amount of functionality.

+1, more support for expressions is always nice.

While we are here, I'd also like to discuss how to switch from a preset to

another.
Like, for example, using the context/preset, one might want to switch from
a map color theme to
another, or even turn off all labels [3]. But how to do that? Some ideas:

a) By a request parameter similar to env, e.g. "&env_context:grayscale"
b) By allowing the definition of the desired preset in a layer group
definition (similar to having it in a workspace)
c) By creating a new "derived style", e.g., a custom styling language that
would accept only two inputs,
    a base style and a different preset (e.g., style "abc" is like "foo",
but using preset "pre2")

d) By supporting structural / block variables (probably not feasible, as
discussed when mentioning this functionality in YSLD, above). By changing
the value of these variables, one could change how the style displays.
Unfortunately, this doesn't really work in a language agnostic way.

I think I like c) the best. For syntax, does something like
&styles=foo#pre2 seem sensible? (probably use a different character than #,
since that already has a functional behavior in URLs)

Overall, this seems like a great idea. Making it work among all styling
languages seems like it could be problematic, but using env vars seems like
a good solution for this issue.

Torben

Hi,

I tried to represent a possible process and form visualization based on this discussion.

VARIABLES DATA FORM

Similar to the current style form where a user can assign a name and have a text area to fill with the variables code.

image 000.png

e.g. :
/* name: default /
/
default environment variables */

@water_color: #9bb0c3;
@sand_color: #f0d1a8;
@building_color: #2b220c;
@tree_color: #3d5a38;

/* use a different representation for constant value /
/
they can’t be changed from client request [0] */

const @font_family: ‘Arial’;
const @background_color: #f2f2f2;

so we could saved multiple variables file.

e.g.:
/* name: building_water /
/
in this preset I would like to change only roof, background and water colors */

@building_color: #d03b00;
@water_color: #2f5379;

const @background_color: #333333;

with this structure the preset overrides only the defined values and constants of default file.

STYLE FORM

image 001.png

As described by Andrea it could be extended with new selectors input for default and preset variables and the CSS code:

/* name: base /
/
here I imagined a database with multiple polygons with different categories (CAT) */

  • {
    fill: @background_color;
    label: [NAME];
    font-size: 10;
    font-family: @font-family;
    }

[CAT=‘TREE’] {
fill: @tree_color;
}

[CAT=‘SAND’] {
fill: @sand_color;
}

[CAT=‘BUILDING’] {
fill: @building_color;
}

but we could have another style file where we choose the same default variable file

e.g.:
/* name: water */

  • {
    fill: @water_color;
    }

the request could use both attributes ‘preset’ or ‘context’.
I would like to use ‘preset’ for variable file published on server side and ‘context’ for new combinations requested from client side [0]

e.g. :

preset=building_water
if not defined it will use the default

context={water_color: #00ffff, tree_color: #00ff00}
it should work as a custom preset that overrides only the default variables with the requested ones

Regards,

Stefano Bovio

···

Il 08 mag 2017 6:57 PM, “Torben Barsballe” <tbarsballe@anonymised.com> ha scritto:


Check out the vibrant tech community on one of the world’s most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot


Geoserver-devel mailing list
Geoserver-devel@anonymised.com.366…sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

Hi [0],
with this mail I’d like to start a discussion on “substitution variables” for styling languages,
something like the lesscss concept, which would look something like:

Note that YSLD already supports something similar, using “define”, so we may be able to learn from the approach used there:

define: &bgcolor #333366

polygon:
fill:color: *bgcolor

Since SyledLayerDescriptor does not currently have the concept of variables, this substitution is done when the YSLD is parsed into SLD.
One other thing that has been useful in YSLD is the ability to make a variable that represents a block of YSLD, (e.g. a line-color, label, font, and line-width), which is often used to style shared elements in a situation with many filters (usually in a case where recode doesn’t quite work). Unfortunately, this doesn’t seem like it would be feasible, as it requires structural elements that are not the same between languages.

One question is what level would this new variable substitution be at: parsing-level (such that variable definitions don’t get included when converting between languages) or language-level (such that variable definitions are preserved when converting between languages). The former opens up the possibility of more powerful variable constructs, but the latter is more flexible and requires less specialization between languages. The environment variable approach you mention below would require the latter.

I’d like to have something like that, but more flexible. Limitations I see in the above:

  • It’s language specific

I don’t see any reliable way of having variable substitiution that is not at least somewhat language specific (if only in syntax), because of the different ways in which different styling languages treat individual elements, and reserved characters.

  • Seems a bit rigid in terms of usage, local to the style, or requiring a new concept, like an “import”, to be shared among multiple files [1]
  • It’s a new concept when we already have something similar around

So, here is what I’d propose instead: let’s use the environment variable support, it’s already there, we are already using it in the styles, it just needs some “love”.

Seems like a good approach. This also helps get around the language-specific issue, since existing languages should all have some way of handling environment variables.

Limits I can see so far:
a) Lacks a centralized way to set default values
b) Requires calling a function
c) It is limited in usage to places accepting expressions
d) Can only expand literals

c) and d) seem the most problematic.

About a), setting the defaults should be done outside of styles imho, or it would drive us back to
requiring imports. So what about having a “variables configuration” (please help with names…
“contexts” or “preset” maybe?) that would allow centralizing server side variable definitions[2].
And maybe allow also to define if the variable can be substituted from the request (env)
or it is meant to be a constat that the client side cannot redefine.

I imaging this could be useful beyond just environment variables used in styling. At present, it seems like it could tie in with some of the module status stuff.

As for c), the significant places where expressions can not be used could be:

  • Vendor options
  • Scale denominators

I see no problem in evolving those to use Expression as we already did in other places only
allowing for static values, but this could be done later, what we have today would already
pack a significant amount of functionality.

+1, more support for expressions is always nice.

While we are here, I’d also like to discuss how to switch from a preset to another.
Like, for example, using the context/preset, one might want to switch from a map color theme to
another, or even turn off all labels [3]. But how to do that? Some ideas:

a) By a request parameter similar to env, e.g. “&env_context:grayscale”
b) By allowing the definition of the desired preset in a layer group definition (similar to having it in a workspace)
c) By creating a new “derived style”, e.g., a custom styling language that would accept only two inputs,
a base style and a different preset (e.g., style “abc” is like “foo”, but using preset “pre2”)

d) By supporting structural / block variables (probably not feasible, as discussed when mentioning this functionality in YSLD, above). By changing the value of these variables, one could change how the style displays. Unfortunately, this doesn’t really work in a language agnostic way.

I think I like c) the best. For syntax, does something like &styles=foo#pre2 seem sensible? (probably use a different character than #, since that already has a functional behavior in URLs)

Overall, this seems like a great idea. Making it work among all styling languages seems like it could be problematic, but using env vars seems like a good solution for this issue.

Torben