Skip to content

Instantly share code, notes, and snippets.

@tonilastre
Created April 17, 2024 13:41
Show Gist options
  • Save tonilastre/102604ee527c07c699b3e3e4dcd71cb8 to your computer and use it in GitHub Desktop.
Save tonilastre/102604ee527c07c699b3e3e4dcd71cb8 to your computer and use it in GitHub Desktop.
Content that explains GSS (Graph Style script) for the LLM

I want you to learn what Graph Style Script looks like so you can help generate GSS code on user request. Let's start with the introduction:

GSS (Graph Style Script) is a language for customizing the visual display of graphs.

Main building blocks

The main building blocks of Graph Style Script (GSS) are expressions and directives. GSS files are a sequence of expressions and directives.

Expressions

Expressions are used to combine values to create new values using functions. For example, the expression:

Add(2, 5)

creates a new value 7 from values 2 and 5. There are a lot of functions built into Graph Style Script so there are even more ways to combine values. There is even a function to create new functions.

When expressions are evaluated, values are created. There are several types of Graph Style Script values: Boolean, Color, Number, String, Array, Dictionary, Function and Null. An expression can be either literal expressions, name expressions or function applications. Literal expressions exist for Color, Number and String.

Strings

This is a literal expression for String: "Hello". It evaluates to the value "Hello" of the type String. The newline character and double quotes can be escaped in strings using \ (backslash), e.g.

"In the end he said: \"I am Iron Man!\""

Numbers

This is a literal expression for Number: 1 or 12.100.

Colors

This is a literal expression for Color: red or #FF0000 or #FF000010. Literal expressions for colors are hex strings starting with '#'.

Variables

Name expressions are names that can be evaluated if there are values bound to them in the environment (lexical scope). Names can start with any of the lower case or upper case letters of the English alphabet and apart from those can contain digits and the following characters: -, _. Names can be defined using the Define function:

Define(superhero, "Iron Man")

In the previous example the value "Iron Man" was bound to the name superhero. After that name expression superhero evaluates the value "Iron Man" to type String.

There are many built-in names that are bound to useful values. Most used are boolean values which are bound to True and False and null value which is bound to Null. Also, all the CSS web colors are bound to their names:

dodgerblue -> evaluates to #1e90ff
forestgreen -> evaluates to #228b22

Functions

Another type of expressions are function application expressions. A function can be applied to the list of expressions (arguments) in the following way.

Concat("Agents", " ", "of", " ", "S.H.I.E.L.D.") -> evaluates to "Agents of S.H.I.E.L.D."

Here the function Concat was applied to the list of string literal expressions to produce their concatenation. Any expression can be an argument.

Not all expressions have to be evaluated. For example, when calling If function one argument will not be evaluated.

Define(mood, "happy")
Define(name, "Happy Hogan")
If(Equals(mood, "happy"),
   Format("{} is happy today.", name),
   Format("{} is not happy today.", name))

-> evaluates to "Happy Hogan is happy today."

In the previous example expression Format("{} is not happy today", name) will not be evaluated because its value is not needed.

Some other function will not evaluate their arguments because they are interested in their names and not values. For example, when creating a new function argument names aren't evaluated, but are remembered to be later bound to the function arguments when the function is called.

Define(square, Function(x, Mul(x, x)))
square(2) -> evaluates to 4

In the previous example the name x isn't evaluated in the first line, and neither is the expression Mul(x, x). In the second line when the function square is called number 2 will be bound to the name x and only then will Mul(x, x) be evaluated.

Let's cover the GSS built-in elements, here comes the first part about colors:

Colors

Graph Style Script comes with built-in colors that you can use by their name.

Example of using color names:

@NodeStyle {
  color: aquamarine
  color-hover: Darker(cyan)
}

Example of using color codes:

@NodeStyle {
  color: #7FFFD4
  color-hover: Darker(#00FFFF)
}

The color names come from a list of the X11 colors supported by popular browsers with the addition of gray/grey variants from SVG 1.0.

Color name HEX code
blue #FF0000
aliceblue #F0F8FF
antiquewhite #FAEBD7
aqua #00FFFF
aquamarine #7FFFD4
azure #F0FFFF
beige #F5F5DC
bisque #FFE4C4
black #000000
blanchedalmond #FFEBCD
blue #0000FF
blueviolet #8A2BE2
brown #A52A2A
burlywood #DEB887
cadetblue #5F9EA0
chartreuse #7FFF00
chocolate #D2691E
coral #FF7F50
cornflowerblue #6495ED
cornsilk #FFF8DC
crimson #DC143C
cyan #00FFFF
darkblue #00008B
darkcyan #008B8B
darkgoldenrod #B8860B
darkgray #A9A9A9
darkgreen #006400
darkgrey #A9A9A9
darkkhaki #BDB76B
darkmagenta #8B008B
darkolivegreen #556B2F
darkorange #FF8C00
darkorchid #9932CC
darkred #8B0000
darksalmon #E9967A
darkseagreen #8FBC8F
darkslateblue #483D8B
darkslategray #2F4F4F
darkslategrey #2F4F4F
darkturquoise #00CED1
darkviolet #9400D3
deeppink #FF1493
deepskyblue #00BFFF
dimgray #696969
dimgrey #696969
dodgerblue #1E90FF
firebrick #B22222
floralwhite #FFFAF0
forestgreen #228B22
fuchsia #FF00FF
gainsboro #DCDCDC
ghostwhite #F8F8FF
gold #FFD700
goldenrod #DAA520
gray #808080
green #008000
greenyellow #ADFF2F
grey #808080
honeydew #F0FFF0
hotpink #FF69B4
indianred #CD5C5C
indigo #4B0082
ivory #FFFFF0
khaki #F0E68C
lavender #E6E6FA
lavenderblush #FFF0F5
lawngreen #7CFC00
lemonchiffon #FFFACD
lightblue #ADD8E6
lightcoral #F08080
lightcyan #E0FFFF
lightgoldenrodyellow #FAFAD2
lightgray #D3D3D3
lightgreen #90EE90
lightgrey #D3D3D3
lightpink #FFB6C1
lightsalmon #FFA07A
lightseagreen #20B2AA
lightskyblue #87CEFA
lightslategray #778899
lightslategrey #778899
lightsteelblue #B0C4DE
lightyellow #FFFFE0
lime #00FF00
limegreen #32CD32
linen #FAF0E6
magenta #FF00FF
maroon #800000
mediumaquamarine #66CDAA
mediumblue #0000CD
mediumorchid #BA55D3
mediumpurple #9370DB
mediumseagreen #3CB371
mediumslateblue #7B68EE
mediumspringgreen #00FA9A
mediumturquoise #48D1CC
mediumvioletred #C71585
midnightblue #191970
mintcream #F5FFFA
mistyrose #FFE4E1
moccasin #FFE4B5
navajowhite #FFDEAD
navy #000080
oldlace #FDF5E6
olive #808000
olivedrab #6B8E23
orange #FFA500
orangered #FF4500
orchid #DA70D6
palegoldenrod #EEE8AA
palegreen #98FB98
paleturquoise #AFEEEE
palevioletred #DB7093
papayawhip #FFEFD5
peachpuff #FFDAB9
peru #CD853F
pink #FFC0CB
plum #DDA0DD
powderblue #B0E0E6
purple #800080
red #FF0000
rosybrown #BC8F8F
royalblue #4169E1
saddlebrown #8B4513
salmon #FA8072
sandybrown #F4A460
seagreen #2E8B57
seashell #FFF5EE
sienna #A0522D
silver #C0C0C0
skyblue #87CEEB
slateblue #6A5ACD
slategray #708090
slategrey #708090
snow #FFFAFA
springgreen #00FF7F
steelblue #4682B4
tan #D2B48C
teal #008080
thistle #D8BFD8
tomato #FF6347
turquoise #40E0D0
violet #EE82EE
wheat #F5DEB3
white #FFFFFF
whitesmoke #F5F5F5
yellow #FFFF00
yellowgreen #9ACD32

GSS built-in elements include various functions too:

Functions

Graph Style Script has a large number of built-in functions. With these functions, you can achieve the right style for your graph.

Color functions

Darker(color)

Returns a darker version of the given color.

Example:

  • color-hover: Darker(#dd2222) will make the hover event color darker.

Inputs:

  • color: Color

Outputs:

  • Color

Lighter(color)

Returns a lighter version of the given color.

Example:

  • color-hover: Lighter(#dd2222) sets a lighter on hover event color.

Inputs:

  • color: Color

Outputs:

  • Color

Mix(color1, color2)

Mixes given colors (performs linear interpolation).

Example:

  • Mix(#1B5E20, orange)

Inputs:

  • color1: Color
  • color2: Color

Outputs:

  • Color

Red(color)

Returns the red component of a given color. The value will be between 0 and 255 (both inclusive).

Examples:

  • Red(mediumseagreen) will return the value 60.
  • Red(#6a0dad) will return the value 106.

Inputs:

  • color: Color

Outputs:

  • number

Green(color)

Returns the green component of a given color. The value will be between 0 and 255 (both inclusive).

Examples:

  • Green(mediumseagreen) will return the value 179.
  • Green(#6a0dad) will return the value 13.

Inputs:

  • color: Color

Outputs:

  • number

Blue(color)

Returns the blue component of a given color. The value will be between 0 and 255 (both inclusive).

Examples:

  • Blue(mediumseagreen) will return the value 113.
  • Blue(#6a0dad) will return the value 173.

Inputs:

  • color: Color

Outputs:

  • number

RGB(red, green, blue)

Creates a new color with given components.

Example:

  • RGB (128, 159, 255) will return the color that has value #809fff.

Inputs:

  • red: number
  • green: number
  • blue: number

Outputs:

  • Color

RGBA(red, green, blue, alpha)

Creates a new color with given components. Same as RGB with an additional alpha value (between 0 and 1) for transparency.

Example:

  • RGBA(128, 159, 255, 0.2) will return the color that has value #809fff33.

Inputs:

  • red: number
  • green: number
  • blue: number
  • alpha: number

Outputs:

  • Color

Hue(color)

Returns the hue (HSL) component of a given color. The value will be between 0 and 359 (both inclusive).

Example:

  • Hue(aliceblue) will return value 208.
  • Hue(#00FFFF) will return value 180.

Inputs:

  • color: Color

Outputs:

  • number

Saturation(color)

Returns the saturation (HSL) component of a given color. The value will be between 0 and 100 (both inclusive).

Example:

  • Saturation(aliceblue) will return value 100.
  • Saturation(#77a4ab) will return value 24.

Inputs:

  • color: Color

Outputs:

  • number

Lightness(color)

Returns the lightness (HSL) component of a given color. The value will be between 0 and 100 (both inclusive).

Example:

  • Lightness(aliceblue) will return value 97.
  • Lightness(#FFFF00) will return value 50.

Inputs:

  • color: Color

Outputs:

  • number

HSL(hue, saturation, lightness)

Creates a new color with given HSL (hue, saturation, lightness) values. Hue value must be between 0 and 359 (both inclusive), saturation and lightness values must be between 0 and 100 (both inclusive).

Example:

  • HSL(282, 23, 56) will return the color that has value #9975a9.

Inputs:

  • hue: number
  • saturation: number
  • lightness: number

Outputs:

  • Color

HSLA(hue, saturation, lightness, alpha)

Creates a new color with given components. Same as HSL with an additional alpha value (between 0 and 1) for transparency.

Example:

  • HSLA(282, 23, 56, 0.2) will return the color that has value #9975a933.

Inputs:

  • hue: number
  • saturation: number
  • lightness: number
  • alpha: number

Outputs:

  • Color

Alpha(color)

Returns alpha (transparency) component of a given color. The value will be between 0 and 1 (both inclusive).

Examples:

  • Alpha(aliceblue) will return value 1.
  • Alpha(#FFFF0033) will return value 0.2.
  • Alpha(RGBA(282, 23, 56, 0.8)) will return value 0.8.
  • Alpha(HSLA(282, 23, 56, 0.2)) will return value 0.2.

Inputs:

  • color: Color

Outputs:

  • number

GSS built-in functions also include:

Conditional functions

And(value...)

Returns True if all the given values are Truthy. Returns False otherwise. Expressions after the first expression that evaluates to Falsy are not evaluated.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Example:

  • And(HasProperty(node, "a"), HasProperty(node, "b")) will return True if node has properties a and b.

Inputs:

  • value1: any
  • value2: any
  • valueN: any

Outputs:

  • boolean

Or(value...)

Returns True if any of the given values is Truthy. Returns False otherwise. Expressions after the first expression that evaluates to Truthy are not evaluated.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Example:

  • Or(Less(Property(node, "age"),20), Greater(Property(node, "age"),40)) returns True if the node's age property is either less than 20 or greater than 40.

Inputs:

  • value1: any
  • value2: any
  • valueN: any

Outputs:

  • boolean

Not(value)

Returns True if the value is Falsy and returns False if the value is Truthy.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Example:

  • @NodeStyle Not(HasProperty(node, "count")) {...} will apply the defined styles to the nodes without the count property.

Inputs:

  • value: any

Outputs:

  • boolean

Equals(value1, value2)

Returns True if given values are equal, False otherwise. Numbers, Strings and Booleans are compared by value, Arrays and Maps by the content, Nodes and Edges are compared by identity.

Example:

  • Equals(Property(edge, "category"), "Food") checks if edge.category equals to text "Food".
  • Equals(Property(node, "name"), "Jon Snow") returns True if the condition is met.

Inputs:

  • value1: any
  • value2: any

Outputs:

  • boolean

Greater(value1, value2)

Returns True if value1 is greater than value2, False otherwise.

Example:

  • Greater(Size(Labels(node)), 0)

Inputs:

  • value1: number
  • value2: number

Outputs:

  • boolean

Less(number1, number2)

Returns True if value1 is less than value2, False otherwise.

Example:

  • Less(Property(node, "age"),40) will return True if given node.age is less than 40.

Inputs:

  • value1: number
  • value2: number

Outputs:

  • boolean

If(condition, then, else)

If condition is Truthy returns the then value, otherwise returns the else value.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Example:

  • label: If(HasProperty(node, "name"), Property(node, "name"), "No name") returns the property name as label if the node has one, or No name if the node doesn't have it.

Inputs:

  • condition: any
  • then: any
  • else: any

Outputs:

  • any

GSS built-in functions also include:

Graph functions

HasLabel(node, label)

Returns True if the given graph node has a label, False otherwise.

Example:

  • HasLabel(node, "Category") will return True if a node has a label with the name Category.

Inputs:

  • node: Node
  • label: string

Outputs:

  • boolean

HasProperty(nodeOrEdge, propertyName)

Returns True if a given graph node or relationship has the property propertyName.

Example:

  • HasProperty(node, "City") will return True if a node has a property with the name City.

Inputs:

  • nodeOrEdge: Node | Relationship
  • propertyName: string

Outputs:

  • boolean

Id(nodeOrEdge)

Returns the ID of a given graph node or edge.

Example:

  • label: AsText(Id(node)) sets the label to be the node ID.

Inputs:

  • nodeOrEdge: Node | Relationship

Outputs:

  • number

Identity(nodeOrEdge)

Returns the ID of a given graph node or edge.

Example:

  • label: AsText(Identity(node)) sets the label to be the node ID.

Inputs:

  • nodeOrEdge: Node | Relationship

Outputs:

  • number

Labels(node)

Returns the list of labels of the given graph node.

Example:

  • label: Labels(node) sets the label to be a list of all the node's labels.

Inputs:

  • node: Node

Outputs:

  • List[string]

Property(nodeOrEdge, propertyName)

Returns the property with the name propertyName of given graph node or relationship.

Example:

  • label: AsText(Property(node, "name")) creates a label using the node's name property.

Inputs:

  • nodeOrEdge: Node | Relationship
  • propertyName: string

Outputs:

  • any

Type(edge)

Returns the type of a given graph relationship.

Example:

  • label: Type(edge) sets the label to the relationship type.

Inputs:

  • edge: Relationship

Outputs:

  • string

InEdges(node)

Returns the list of inbound edges from a given graph node.

Example:

  • size: Size(InEdges(node)) sets the size to be equal to the count of inbound edges.

Inputs:

  • node: Node

Outputs:

  • List[Relationship]

OutEdges(node)

Returns the list of outbound edges from a given graph node.

Example:

  • size: Size(OutEdges(node)) sets the size to be equal to the count of outbound edges.

Inputs:

  • node: Node

Outputs:

  • List[Relationship]

Edges(graphOrNode)

Returns the list of inbound and outbound edges from a given graph node. It returns all the edges in the graph if the input is a graph.

Examples:

  • size: Size(Edges(graph)) sets the size to be equal to the count of all graph edges.
  • size: Size(Edges(node)) sets the size to be equal to the count of inbound and outbound edges.

Inputs:

  • graphOrNode: Graph | Node

Outputs:

  • List[Relationship]

Nodes(graphOrEdge)

Returns the list of start and end nodes from a given graph edge. It returns all the nodes in the graph if the input is a graph.

Examples:

  • size: Size(Nodes(graph)) sets the size to be equal to the count of all graph nodes.
  • size: Size(Nodes(edge)) sets the size to be equal to the count of nodes that edge connects (usually 2).

Inputs:

  • graphOrEdge: Graph | Relationship

Outputs:

  • List[Node]

AdjacentNodes(node)

Returns the list of adjacent nodes for a given graph node. An adjacent node is a node connected directly with a single edge, inbound or outbound.

Example:

  • size: Size(AdjacentNodes(node)) sets the size to be equal to the count of adjacent nodes.

Inputs:

  • node: Node

Outputs:

  • List[Node]

StartNode(edge)

Returns the start (source) node for a given graph edge.

Example:

  • label: AsText(Id(StartNode(edge))) sets the label of the edge to be the start node ID.

Inputs:

  • edge: Relationship

Outputs:

  • Node

EndNode(edge)

Returns the end (target) node for a given graph edge.

Example:

  • label: AsText(Id(EndNode(edge))) sets the label of the edge to be the end node ID.

Inputs:

  • edge: Relationship

Outputs:

  • Node

NodeCount(graph)

Returns the total number of nodes in the graph.

Example:

  • size: NodeCount(graph) sets the size to be the total number of nodes in the graph.

Inputs:

  • graph: Graph

Outputs:

  • number

EdgeCount(graph)

Returns the total number of edges in the graph.

Example:

  • size: EdgeCount(graph) sets the size to be the total number of edges in the graph.

Inputs:

  • graph: Graph

Outputs:

  • number

GSS built-in functions also include:

Map functions

MapKeys(map)

Returns an array of all map keys.

Example:

  • MapKeys(AsMap("key1", "value1", "key2", "value2"))) will return an array ["key1", "key2"].

Inputs:

  • map: Map[string, any]

Outputs:

  • List[string]

MapValues(map)

Returns an array of all map values.

Example:

  • MapValues(AsMap("key1", "value1", "key2", 12))) will return an array ["value1", 12].

Inputs:

  • map: Map[string, any]

Outputs:

  • List[any]

Check other map functions down below: AsMap, IsMap, Get, Set, Del.

Math functions

Add(value...)

Returns the sum of given values.

Example:

  • Add(10, Property(node, "age")) will give node.age + 10 if age is defined (as a number).

Inputs:

  • value1: number
  • value2: number
  • valueN: number

Outputs:

  • number

Div(value1, value2)

Returns value1 divided by value2.

Example:

  • Div(Property(node, "population"), 2) will divide node.population with 2 if population is defined (as a number).

Inputs:

  • value1: number
  • value2: number

Outputs:

  • number

Exp(value)

Returns 2.71828... raised to the power value.

Example: -Exp(2) will return the number 7.38905609893

Inputs:

  • value: number

Outputs:

  • number

Log(value)

Returns the logarithm (to the base e) of a value.

Example:

  • Log(Property(node, "sales"))

Inputs:

  • value: number

Outputs:

  • number

Log10(value)

Returns the logarithm (to the base 10) of a value.

Example:

  • Log10(Property(node, "sales"))

Inputs:

  • value: number

Outputs:

  • number

Mul(value...)

Returns the product of given values.

Example:

  • Mul(2,10,3) returns 60 (2103).

Inputs:

  • value1: number
  • value2: number
  • valueN: number

Outputs:

  • number

Random()

Returns a random number between 0 (inclusive) and 1 (exclusive). All the possible numbers are equally likely to be returned.

Example:

  • Random()

Outputs:

  • number

RandomInt(bound)

Returns a random integer between 0 (inclusive) and bound (exclusive). All the possible numbers are equally likely to be returned.

Example:

  • RandomInteger(Property(node, "population")) will return an integer between 0 and node.population if population is defined (as a number).

Inputs:

  • bound: number

Outputs:

  • number

Sqrt(value)

Returns the square root of a value.

Example:

  • Sqrt(Property(node, "surface")) will return the square root of a node.surface.

Inputs:

  • value: number

Outputs:

  • number

Sub(value1, value2)

Subtracts value2 from value1.

Example:

  • Sub(Property(node, "age"),10) returns node.age - 10 if age is defined (as a number).

Inputs:

  • value1: number
  • value2: number

Outputs:

  • number

Floor(value)

Returns the largest integer less than or equal to the input value.

Examples:

  • Floor(2.8) will return number 2.
  • Floor(2) will return number 2.

Inputs:

  • value: number

Outputs:

  • number

Ceil(value)

Returns the smallest integer greater than or equal to the input value.

Examples:

  • Ceil(2.1) will return number 3.
  • Ceil(2) will return number 2.

Inputs:

  • value: number

Outputs:

  • number

Round(value)

Returns the closest integer to the input value.

Examples:

  • Round(2.1) will return number 2.
  • Round(2.5) will return number 3.
  • Round(2.8) will return number 3.

Inputs:

  • value: number

Outputs:

  • number

Sum(array)

Returns the sum of all numbers in the input array. For an empty array, it returns 0.

Example:

  • Sum(AsArray()) will return number 0.
  • Sum(AsArray(1, 2, 3, 4)) will return number 10.
  • Sum(AsArray(5.0, 6.5)) will return number 11.5.

Inputs:

  • array: List[number]

Outputs:

  • number

Avg(array)

Returns the average of all numbers in the input array. An array should have at least one number.

Example:

  • Avg(AsArray(1)) will return number 1.
  • Avg(AsArray(1, 2, 3, 4, 5)) will return number 3.
  • Avg(AsArray(4.8, 6.2)) will return number 5.5.

Inputs:

  • array: List[number]

Outputs:

  • number

Min(array)

Returns the minimum of all numbers in the input array. An array should have at least one number.

Example:

  • Min(AsArray(1)) will return number 1.
  • Min(AsArray(1, 2, 3, 4, 5)) will return number 1.
  • Min(AsArray(4.8, 6.2)) will return number 4.8.

Inputs:

  • array: List[number]

Outputs:

  • number

Max(array)

Returns the maximum of all numbers in the input array. An array should have at least one number.

Example:

  • Max(AsArray(1)) will return number 1.
  • Max(AsArray(1, 2, 3, 4, 5)) will return number 5.
  • Max(AsArray(4.8, 6.2)) will return number 6.2.

Inputs:

  • array: List[number]

Outputs:

  • number

GSS built-in functions also include:

Text functions

Concat(value...)

Concatenates given strings or arrays.

Example:

  • Concat("City", " ", "of", " ", "London") will return City of London.
  • Concat(AsArray(1, 2, 3), AsArray(4, 5)) will return [1, 2, 3, 4, 5].

Inputs:

  • value1: string | List[any] - value2: string | List[any] - valueN: string | List[any]

Outputs:

  • string | List[any]

Slice(value, start, end?)

Returns a string or array slice defined by the start and optional end index. Negative indexes will also work.

Examples:

  • Slice("Hello", 1) will return "ello".
  • Slice("Hello", -3, -1) will return "ll".
  • Slice(AsArray(1, 2, 3, 4, 5), 1, 3) will return [2, 3].
  • Slice(AsArray(1, 2, 3, 4, 5), -2) will return [4, 5].

Inputs:

  • value: string | List[any]
  • start: number
  • end?: number

Outputs:

  • string | List[any]

Split(text, delimiter)

Returns a string or array slice defined by the start and optional end index. Negative indexes will also work.

Examples:

  • Split("Hello", "x") will return ["Hello"].
  • Split("Hello", "") will return ["H", "e", "l", "l", "o"].
  • Split("Hello", "lo") will return ["Hel", ""].
  • Split("Hello there", " ") will return ["Hello", "there"].

Inputs:

  • text: string
  • delimiter: string

Outputs:

  • List[string]

Format(formatString, value...)

Substitutes occurrences of curly brace pairs in formatString with textual representations of given values. The first occurrence is substituted with the first value, the second occurrence with the second value and so on.

Examples:

  • Format("{}, {}!", "Hello", "World") -> "Hello, World!"

Text inside curly braces is ignored.

  • Format("{name}: {age}", "Antun", 23) -> "Antun: 23"

Inputs:

  • formatString: string
  • value1: any
  • valueN: any

Outputs:

  • string

Matches(text, regex)

Returns True if text matches regex. The evaluation of the regex is done with the Javascript function RegExp.test(text).

Examples:

  • Matches("Graph style script", "style") -> True
  • Matches("Graph style script", "st.* script") -> True
  • Matches("Graph style script", "^G") -> True
  • Matches("Graph style script", "GRAPH?") -> False

Inputs:

  • text: string
  • regex: string

Outputs:

  • boolean

Replace(text, regex, replacement)

Returns a new string where a replacement value will be used instead of the first regex match. The creation of the regex is done with the Javascript function new RegExp(text).

Examples:

  • Replace("Graph style script", "xyz", "text") -> "Graph style script"
  • Replace("Graph style script", "style ", "") -> "Graph script"
  • Replace("Graph style script", "style.*", "rocks!") -> "Graph rocks!"
  • Replace("Graph style script", "s", "S!") -> "Graph S!tyle script"

Inputs:

  • text: string
  • regex: string
  • replacement: string

Outputs:

  • string

LowerCase(text)

Returns the value of a string converted to lower case.

Example:

  • AsText(LowerCase(Property(node, "name"))) will return node name in lower case.

Inputs:

  • text: string

Outputs:

  • string

UpperCase(text)

Returns the value of a string converted to upper case.

Example:

  • AsText(UpperCase(Property(node, "name"))) will return the node name in upper case.

Inputs:

  • text: string

Outputs:

  • string

Trim(text)

Returns the string without starting and ending whitespaces.

Example:

  • Trim(" Hello there! ") will return "Hello there!.

Inputs:

  • text: string

Outputs:

  • string

GSS built-in functions also include:

Array functions

Join(array, delimiter)

Returns a new string by joining array elements with the delimiter.

Example:

  • label: Join(Labels(node), ", ") creates a label which is a string made out of all the labels delimited with a comma.

Inputs:

  • array: List[any]
  • delimiter: string

Outputs:

  • string

Contains(array, value)

Returns True if the array contains the defined value, False otherwise.

Example:

  • Contains(AsArray(2,7,8,9), 2) will return True.

Inputs:

  • array: List[any]
  • value: any

Outputs:

  • boolean

RandomOf(array)

Returns a random element of the given array. All the elements are equally likely to be chosen.

Example:

  • RandomOf(AsArray(1,3,5,7,11,13)) will return one of the array elements.

Inputs:

  • array: List[any]

Outputs:

  • any | null

Find(array, function)

Returns the first element of the given array for which the function yields Truthy value.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Function argument function has one input argument which is the item of the array.

Example:

  • Find(AsArray(1, 2, 3, 4), Function(item, Greater(item, 2))) will return number 3.
  • Find(AsArray(1, 2, 1, 1), Function(item, Greater(item, 2))) will return Null.

Inputs:

  • array: List[any]
  • function: Function

Outputs:

  • any | null

Filter(array, function)

Returns the new array with elements of the given array for which the function yields Truthy value.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Function argument function has one input argument which is the item of the array.

Example:

  • Filter(AsArray(1, 2, 3, 4), Function(item, Greater(item, 2))) will return array [3, 4].
  • Filter(AsArray(1, 2, 1, 1), Function(item, Greater(item, 2))) will return [].

Inputs:

  • array: List[any]
  • function: Function

Outputs:

  • List[any]

Map(array, function)

Returns the new array where each element of the given array is converted (mapped) with the defined function.

Function argument function has one input argument which is the item of the array.

Example:

  • Map(AsArray(1, 2, 3, 4), Function(item, Mul(item, 2))) will return array [2, 4, 6, 8].
  • Map(AdjacentNodes(node), Function(n, Property(n, "name"))) will return the list of names of adjacent nodes.

Inputs:

  • array: List[any]
  • function: Function

Outputs:

  • List[any]

Reduce(array, function, initialValue)

The Reduce() function returns a single value generated by reducing an array of values. The function parameter has two arguments, previous reduced value and current array value. The initalValue parameter specifies the initial value used for the first reduce iteration.

Example:

  • The following example does a sum of all elements in the array with the initial value of 1. Because the array is empty, the returned value is the initial one: 1.
Reduce(
  AsArray(),
  Function(prev, current, Add(prev, current)),
  1
)
  • The same example as the above one, but with a defined array of three elements. The result will be number 6.
Reduce(
  AsArray(1, 2, 3),
  Function(prev, current, Add(prev, current)),
  0
)
  • The following example joins all letters from an array into a single text "ABC".
Reduce(
  AsArray("A", "B", "C"),
  Function(prev, current, Format("{}{}", prev, current)),
  ""
)

Inputs:

  • array: List[any]
  • function: Function
  • initalValue: any

Outputs:

  • any

All(array, function)

Returns True if the function yields Truthy value for all elements of the given array.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Function argument function has one input argument which is the item of the array.

Example:

  • All(AsArray(1, 2, 3, 4), Function(item, Greater(item, 2))) will return False.
  • All(AsArray(1, 2, 1, 1), Function(item, Less(item, 3))) will return True.

Inputs:

  • array: List[any]
  • function: Function

Outputs:

  • boolean

GSS built-in Array functions also include:

Any(array, function)

Returns True if the function yields Truthy value for any element of the given array.

In GSS, there are six Falsy values: False , 0 , "" , Null , [] (empty array), and {} (empty map). Everything else is considered Truthy.

Function argument function has one input argument which is the item of the array.

Example:

  • Any(AsArray(1, 2, 3, 4), Function(item, Greater(item, 2))) will return True.
  • Any(AsArray(1, 2, 1, 1), Function(item, Greater(item, 3))) will return False.

Inputs:

  • array: List[any]
  • function: Function

Outputs:

  • boolean

Uniq(array)

Returns an array of unique elements of the given array.

Example:

  • Uniq(AsArray(2,1,1,2,1,3,1)) will return [2, 1, 3].
  • Uniq(AsArray("1", "1", 1, True, True, 1)) will return ["1", 1, True].

Inputs:

  • array: List[any]

Outputs:

  • List[any]

Reverse(array)

Returns an array with reversed elements of the given array.

Example:

  • Reverse(AsArray(1, 2, 3)) will return [3, 2, 1].

Inputs:

  • array: List[any]

Outputs:

  • List[any]

Sort(array)

Returns an array with sorted items. The sort works only on arrays with primitive types: strings, numbers, and booleans.

Example:

  • Sort(AsArray(3, 2, 1, 8, 3)) will return [1, 2, 3, 3, 8].

Inputs:

  • array: List[string] | List[boolean] | List[number]

Outputs:

  • List[string] | List[boolean] | List[number]

Next(iterator)

Returns the next item in the iterator. If iterator has no items, it returns Null.

Example:

  • Next(AsIterator(AsArray(3, 2, 1))) will return 3.

Inputs:

  • iterator: Iterator[any]

Outputs:

  • any | null

Type functions

AsArray(value...)

Creates and returns an array of given values. The function can be used to convert Iterator back to the array with AsArray(AsIterator(AsArray(1, 2))).

Examples:

  • AsArray("Alfa", "Bravo", "Charlie", "Delta", "Echo") -> ["Alfa", "Bravo", "Charlie", "Delta", "Echo"]
  • AsArray(AsIterator(AsArray(1, 2, 3))) -> [1, 2, 3].

Inputs:

  • value1: any
  • value2: any
  • valueN: any

Outputs:

  • List[any]

AsMap(key, value, ...)

Creates and returns a map of given pairs of keys and values. There must be an even number of inputs because each key should have its own value. Keys must be type of string. Values can be any type.

Example:

  • AsMap("1", 10, "2", 20) -> {"1": 10, "2": 20}

Inputs:

  • key1: string
  • value1: any
  • keyN: string
  • valueN: any

Outputs:

  • Map[string, any]

AsIterator(array)

Creates and returns an iterator of given array. Iterator values can be used only once with Next function until all values have been used.

Example:

  • AsIterator(AsArray(1, 2, 3)) -> (1, 2, 3)

Inputs:

  • array: List[any]

Outputs:

  • Iterator[any]

AsNumber(value)

Parses the given string or boolean and returns a number. The string should contain only one number in base 10 and nothing else. Boolean True returns number 1. Boolean False returns number 0.

Example:

  • AsNumber("8") will return number 8.

Inputs:

  • value: string | number | boolean

Outputs:

  • number

AsText(value)

Returns a textual representation of a given value.

Example:

  • AsText(Property(node, "age")) will return node.age as string.

Inputs:

  • value: any

Outputs:

  • string

TypeOf(value)

Returns the type of a given value. Type is returned as a string. Following types are used in GSS:

  • "number" - represents numbers
  • "boolean" - represents booleans (True and False)
  • "string" - represents textual values
  • "Null" - represents null value (Null)
  • "Color" - represents colors
  • "Node" - represents graph node
  • "Edge" - represents graph relationship
  • "Graph" - represents graph
  • "List" - represents an array object (e.g. [1, 2, 3])
  • "Iterator" - represents an iterator object (e.g. (1, 2, 3))
  • "Map" - represents a map object (e.g. { "name": "GSS" })
  • "Function" - represents function object

Example:

  • TypeOf(Property(node, "name")) returns string.

Inputs:

  • value: any

Outputs:

  • string

IsArray(value)

Returns True if the input value is an array, otherwise False.

Examples:

  • IsArray(10.2) returns False.
  • IsArray(AsArray(1, 2, 3)) returns True.

Inputs:

  • value: any

Outputs:

  • boolean

IsMap(value)

Returns True if the input value is a map, otherwise False.

Examples:

  • IsMap(10.2) returns False.
  • IsMap(AsMap("key", "value")) returns True.

Inputs:

  • value: any

Outputs:

  • boolean

IsIterator(value)

Returns True if the input value is an iterator, otherwise False.

Examples:

  • IsIterator(AsArray(1, 2, 3)) returns False.
  • IsIterator(AsIterator(AsArray(1, 2, 3))) returns True.

Inputs:

  • value: any

Outputs:

  • boolean

IsNumber(value)

Returns True if the input value is a number, otherwise False.

Example:

  • IsNumber(10.2) returns True.

Inputs:

  • value: any

Outputs:

  • boolean

IsBoolean(value)

Returns True if the input value is a boolean, otherwise False.

Example:

  • IsBoolean(False) returns True.

Inputs:

  • value: any

Outputs:

  • boolean

IsString(value)

Returns True if the input value is a string, otherwise False.

Example:

  • IsString("text") returns True.

Inputs:

  • value: any

Outputs:

  • boolean

IsNull(value)

Returns True if the input value is a Null, otherwise False.

Example:

  • IsNull(Null) returns True.

Inputs:

  • value: any

Outputs:

  • boolean

GSS built-in functions also include:

Utility functions

Define(name, value)

Binds the given value to the given name. Names can be redefined.

Example:

  • Define(city, "London") will set the value of the city to London.

Inputs:

  • name: Variable
  • value: any

Function(arg..., body)

Creates a function. body is the expression to evaluate when the function is called. All arguments except body are argument names of the function to create. When the created function is called names arg1, arg2, ... are bound to function arguments and available in the body expression. This function is most useful in combination with Define.

Examples:

Define(makeGreeting, Function(firstName, Format("Hello, {}!", firstName)))
makeGreeting("World") // -> Hello, World!
Define(pow, Function(x, n, If(Equals(n, 1), x, Mul(x, pow(x, Sub(n, 1))))))
pow(2, 10) // -> 1024

Inputs:

  • arg1: Variable
  • argN: Variable
  • body: any

Outputs:

  • Function

Execute(expression...)

Executes all expressions given as arguments. The function comes in handy when there are set of commands that should be executed, e.g. setting several items on the map with Set and returning the last value.

Example:

Define(map, AsMap())
Define(mapKeys, Execute(
  Set(map, "key1", "value1"),
  Set(map, "key2", "value2"),
  MapKeys(map),
))

Variable map will be {"key1": "value1", "key2": "value2"}. Execution returns the last value of the variable mapKeys which is an array of keys: ["key1", "key2"].

Inputs:

  • expression1: Expression
  • expressionN: Expression

Outputs:

  • any

Get(object, key, defaultValue?)

If obj is a List, returns the element with index key of list obj (indexing is zero based). If obj is a Map, returns the value for key key. If obj is a string, returns the letter with index key of string obj (indexing is zero based). If obj is a Node, returns the value for key key. If obj is a Relationship, returns the value for key key.

In case of invalid input or missing value, it returns defaultValue or Null if default value is not defined.

Examples:

  • Get(AsArray(3,6,7,3), 2) returns number 7.
  • Get(Property(node, "map"), "year") will get the property year` from the map of node properties.

Inputs:

  • object: List | Map | string | Node | Relationship
  • key: number | string
  • defaultValue?: any

Outputs:

  • any

Set(object, key, value)

If obj is a List, sets the value with index key (indexing is zero based). Value will be returned on successful set. If index is out of ranges of the list, nothing will be set, and Null will be returned.

If obj is a Map, sets the value for key key. Key must be a string type. Input value will be returned.

Examples:

  • Define(array, AsArray(1, 2, 3)) Set(array, 1, 5) returns number 5 and array will be [1, 5, 3].
  • Define(map, AsMap()) Set(map, "key", "value") returns "value" and map will be {"key": "value"}.

Inputs:

  • object: List | Map
  • key: number | string
  • value: any

Outputs:

  • any | null

Del(map, key)

Removes a value from a map under key key. Removed value will be returned. If key was missing in a map, Null will be returned.

Examples:

  • Define(map, AsMap("a", 1, "b", 2)) Del(map, "a") returns 1 and map will be {"b": 2}.
  • Define(map, AsMap("a", 1)) Del(map, "b") returns Null and map will be {"a": 1}.

Inputs:

  • map: Map[string, any]
  • key: string

Outputs:

  • any | null

Size(value)

If value is of type List or Map, returns its size. If value is of type string, returns its length. If value is of type Node, returns the size of node properties. If value is of type Relationship, returns the size of relationship properties. If value is of type Graph, returns the size of the graph (nodes and relationships)

Example:

  • Size(Property(node, "name")) returns the size of the node's name property.

Inputs:

  • value: List | Map | string | Node | Relationship | Graph

Outputs:

  • number

Coalesce(value...)

Returns the first non-null value. In case of empty call or all values being Null, Null will be returned.

Example:

  • Coalesce() returns Null
  • Coalesce(Null, 1, False) returns 1

Inputs:

  • value1: any
  • valueN: any

Outputs:

  • any | null

GSS built-in objects also include:

Variables

Graph Style Script has a few built-in variables that you can use.

node

The variable node is bound to the graph node for which the style directive @NodeStyle is being evaluated. Graph node is of type Map and has all information about the node (properties, labels, id).

In the following example, you can see the usage of the variable node within the @NodeStyle directive.

@NodeStyle {
  label: Property(node, "name")
  size: Mul(Size(Edges(node)), 5)
}

If node is used outside @NodeStyle directive, a compile error will be thrown.

edge

The variable edge is bound to the graph relationship for which the style directive @EdgeStyle is being evaluated. Graph relationship is of type Map and has all information about the relationship (properties, type, start, end, id).

In the following example, you can see the usage of the variable edge within the @EdgeStyle directive.

@EdgeStyle {
  label: Format("From node {}", Property(StartNode(edge), "name"))
  size: AsNumber(Property(edge, "importance"))
}

If edge is used outside @EdgeStyle directive, a compile error will be thrown.

graph

The variable graph is bound to the overall graph that contains nodes and edges. It can be useful to get the total count of nodes and edges with the following functions: NodeCount(graph) and EdgeCount(graph).

In the following example, you can see the usage of the variable graph in the directive context (@NodeStyle, @EdgeStyle) and global context (variable EDGE_COUNT);

// Global context acts like a cache because the
// following expression will be evaluated only once
Define(EDGE_COUNT, EdgeCount(graph))

@NodeStyle {
  size: Sqrt(NodeCount(graph))
}

@EdgeStyle {
  width: If(Greater(EDGE_COUNT, 1000), 1, 2)
}

The graph variable is not bound to any of the directives (@NodeStyle, @EdgeStyle) so you can use it wherever you want in the Graph Style Script code.

GSS consists of directives such as @NodeStyle, @EdgeStyle and @ViewStyle.

Directive properties

@ViewStyle directive

@ViewStyle directive is used for defining style properties of a general graph view: link distance, view, physics, repel force, etc. You can read more about each property in the following sections.

@ViewStyle

Here is the list of all properties that can be defined in the @ViewStyle directive, along with their expected types.

collision-radius: number

Sets the margin radius for each node from its centre. If node size is 10 and collision-radius is set to 20, it means there will be 10 spaces left around each node. No other node can be in that space.

The default collision-radius is 15.

Example:

  • collision-radius: 15 sets the margin radius for each node from its centre to 15.

repel-force: number

Sets the strength of repel force between all nodes. If positive, it adds a force that moves nodes away from each other, if negative, it moves nodes towards each other.

The default repel-force is -100.

Example:

  • repel-force: -100 sets the repel force between all nodes to -100.

link-distance: number

Sets the minimum required distance between two connected nodes from their centres.

The default link-distance is 30. If node sizes are 20 and link distance is 30, nodes might overlap because the minimum distance from one node centre to another is 20 + 20 = 40.

Example:

  • link-distance: 30 sets the minimum required distance to 30.

physics-enabled: boolean

Enables or disables physics which is a real-time simulation for graph node positions. When physics is enabled, the graph is not static anymore.

Examples:

  • physics-enabled: True enables the physics.
  • physics-enabled: Greater(NodeCount(graph), 100) enables the physics for graphs with more than 100 nodes.

background-color: Color

Sets the background color of the canvas.

Examples:

  • background-color: #DDDDDD sets the background color of the canvas to light gray.
  • background-color: black sets the background color of the canvas to black.

view: string: "default" | "map"

Sets the current graph view that can be either "default" or "map". The "default" view is a graph visualization on a blank background. The "map" view is a graph visualization with a map as a background where each node needs to provide latitude and longitude to be positioned on the map.

The default view is "default".

Examples:

  • view: "default" sets the view to the default view.
  • view: "map" sets the view to the map view that will be shown only if at least one node has required geo information: latitude and longitude.

@ViewStyle.Map directive

@ViewStyle.Map directive is a subset of @ViewStyle because it defines additional style properties for a graph view when there is a map background. Style properties of the @ViewStyle.Map directive are used to style the background map.

@ViewStyle.Map

Here is the list of all properties that can be defined in the @ViewStyle.Map directive, along with their expected types.

tile-layer: string: "detailed" | "light" | "dark" | "basic" | "satellite"

Sets the map tile for the map background. The default map tile is "light".

Examples:

  • tile-layer: "dark" sets the map tile to be type "dark".

GSS edge directive is:

@EdgeStyle

Here is the list of all properties that can be defined in the @EdgeStyle directive, along with their expected types.

arrow-size: Number

Sets the size of the arrow on the relationship line end.

Examples:

  • arrow-size: 10 sets the arrow size to be 10 pixels.

color: Color

Sets the background color of an element.

Examples:

  • color: #FF0000 sets the background color of the element to red.
  • color: limegreen sets the background color of the element to lime green.

color-hover: Color

Sets the background color of an element on mouse hover event.

Examples:

  • color-hover: #FF0000 sets the background color of the shape to red on mouse hover event.
  • color-hover: limegreen sets the background color of the shape to lime green on mouse hover event.

color-selected: Color

Sets the background color of an element on mouse select event.

Examples:

  • color-selected: #FF0000 sets the background color of the shape to red on mouse select event.
  • color-selected: limegreen sets the background color of the shape to lime green on mouse select event.

font-background-color: Color

Sets the background color of an element's label (text). Text can be defined with property label.

Examples:

  • font-background-color: #FF0000 sets the text background color to red.
  • font-background-color: limegreen sets the text background color to lime green.

font-color: Color

Sets the color of the element's label (text). Text can be defined with property label.

Examples:

  • font-color: #FF0000 sets the text color to red.
  • font-color: limegreen sets the text color to lime green.

font-family: String

Sets a font family for the element's text. Text can be defined with property label.

Examples:

  • font-family: "sans-serif" sets the text family font to sans-serif.
  • font-family: "cursive" sets the text family font to cursive.

font-size: Number

Sets the size of the element's text. Text can be defined with property label.

Example:

  • font-size: 10 sets the size of the font to 10 pixels.

label: String

Sets the element's text label. The text is shown below the element (node or relationship).

Examples:

  • label: "Text" sets the text "Text" as a label for every single element.
  • label: Property(edge, "quantity") sets the text for the element's label dynamically by using the edge property "quantity".

shadow-color: Color

Sets the color of the element's shadow.

Examples:

  • shadow-color: #FF0000 sets the shadow color to red.
  • shadow-color: limegreen sets the shadow color to lime green.

shadow-size: Number

Sets the blur size of the element's shadow. If the value is 0, the shadow will be a solid color defined by the property shadow-color.

Examples:

  • shadow-size: 5 indicates that the shadow will be diffused across 5 pixels.

shadow-offset-x: Number

Sets the horizontal offset of the element's shadow. A positive value puts the shadow on the right side of the shape, a negative value puts the shadow on the left side of the shape.

Examples:

  • shadow-offset-x: 0 indicates that the shadow is exactly behind the shape.
  • shadow-offset-x: 20 indicates that the shadow starts 20 pixels to the right.

shadow-offset-y: Number

Sets the vertical offset of the element's shadow. A positive value puts the shadow below the shape, a negative value puts the shadow above the shape.

Examples:

  • shadow-offset-y: 0 indicates that the shadow is exactly behind the shape.
  • shadow-offset-y: 20 indicates that the shadow starts 20 pixels below the shape position.

width: Number

Sets the width of the relationship line.

Example:

  • width: 2 indicates that the width of the relationship line will be 2 pixels wide.

width-hover: Number

Sets the width of the relationship line on mouse hover event.

Example:

  • width-hover: 2 indicates that the width of the relationship will be 2 pixels wide on mouse hover event.

width-selected: Number

Sets the width of the relationship line on mouse select event.

Examples:

  • width-selected: 2 indicates that the width of the relationship will be 2 pixels wide on mouse select event.

z-index: number

Sets the stack order of an element, similar to the CSS z-index. The element with the highest z-index will be rendered on top of every other element.

Example:

  • z-index: 100 sets the element's z-index.

GSS node directive is:

@NodeStyle

Here is the list of all properties that can be defined in the @NodeStyle directive, along with their expected types.

border-color: Color

Sets a border color.

Examples:

  • border-color: #FF0000 sets the border color to red.
  • border-color: limegreen sets the border color to lime green.

border-color-hover: Color

Sets a border color that is applied on mouse hover event.

Examples:

  • border-color-hover: #FF0000 sets the border color to red on mouse hover event.
  • border-color-hover: limegreen sets the border color to lime green on mouse hover event.

border-color-selected: Color

Sets a border color that is applied on mouse select event.

Examples:

  • border-color-selected: #FF0000 sets the border color to red on mouse select event.
  • border-color-selected: limegreen sets the border color to lime green on mouse select event.

border-width: Number

Sets the border width.

Example:

  • border-width: 2 sets the border width to 2 pixels.

border-width-selected: Number

Sets the border width that is applied on mouse select event.

Example:

  • border-width-selected: 10 sets the border width to 10 pixels on mouse select event.

color: Color

Sets the background color of an element.

Examples:

  • color: #FF0000 sets the background color of the element to red.
  • color: limegreen sets the background color of the element to lime green.

color-hover: Color

Sets the background color of an element on mouse hover event.

Examples:

  • color-hover: #FF0000 sets the background color of the element to red on mouse hover event.
  • color-hover: limegreen sets the background color of the element to lime green on mouse hover event.

color-selected: Color

Sets the background color of an element on mouse select event.

Examples:

  • color-selected: #FF0000 sets the background color of the element to red on mouse select event.
  • color-selected:limegreen sets the background color of the element to lime green on mouse select event.

font-background-color: Color

Sets the background color of the element's label (text). Text can be defined with property label.

Examples:

  • font-background-color: #FF0000 sets the text background color to red.
  • font-background-color: limegreen sets the text background color to lime green.

font-color: Color

Sets the color of the element's label (text). Text can be defined with property label.

Examples:

  • font-color: #FF0000 sets the text color to red.
  • font-color: limegreen sets the text color to lime green.

font-family: String

Sets a font family for the element's label (text). Text can be defined with property label.

Examples:

  • font-family: "sans-serif" sets the text family font to sans-serif.
  • font-family: "cursive" sets the text family font to cursive.

font-size: Number

Sets the size of the element's text. Text can be defined with property label.

Example:

  • font-size: 10 sets the size of the font to 10 pixels.

image-url: String

Sets the element's background to be an image from the image URL. Supported format are png, jpeg, gif (static, not dynamic), webp or base 64 encoded image using inline data:image/png;base64. It will override the value defined with the property color.

Examples:

  • image-url: "https://download.memgraph.com/asset/images/memgraph-logo.png" sets the element's background to be an image of the Memgraph logo.
  • image-url: Property(node, "profile_image") sets the element's background to be an image from the URL that is fetched from the node property "profile_image".

image-url-selected: String

Sets the element's background to be an image from the image URL on mouse select event. Supported format are png, jpeg, gif (static, not dynamic), webp or base 64 encoded image using inline data:image/png;base64. It will override the value defined with the property color-selected.

Example:

  • image-url-selected: "https://download.memgraph.com/asset/images/memgraph-logo-5f60e83d.jpeg" sets the element's background to be an image of the Memgraph logo.

Check property image-url for more details and examples.

label: String

Sets the element's text label. The text is shown below the element (node or relationship).

Examples:

  • label: "Text" sets the text "Text" as a label for every single element.
  • label: Property(node, "name") sets the text for the element's label dynamically by using the node property "name".

shadow-color: Color

Sets the color for the element's shadow.

Examples:

  • shadow-color: #FF0000 sets the shadow color to red.
  • shadow-color: limegreen sets the shadow color to lime green.

shadow-size: Number

Sets the blur size of the element's shadow. If the value is 0, the shadow will be a solid color defined by the property shadow-color.

Example:

  • shadow-size: 5 indicates that the shadow will be diffused across 5 pixels.

shadow-offset-x: Number

Sets the horizontal offset of the element's shadow. A positive value puts the shadow on the right side of the element, a negative value puts the shadow on the left side of the element.

Examples:

  • shadow-offset-x: 0 indicates that the shadow is exactly behind the element.
  • shadow-offset-x: 20 indicates that the shadow starts 20 pixels to the right.

shadow-offset-y: Number

Sets the vertical offset of the element's shadow. A positive value puts the shadow below the element, a negative value puts the shadow above the element.

Examples:

  • shadow-offset-y: 0 indicates that the shadow is exactly behind the element.
  • shadow-offset-y: 20 indicates that the shadow starts 20 pixels below the element position.

shape: String

Sets the shape of the element. The default shape for the node is "dot". Possible values are: "dot", "square", "diamond", "triangle", "triangleDown", "star"

Examples:

  • shape: "square" indicates that the shape of the element will be a square.

size: Number

Sets the size of the element.

Example:

  • size: 10 indicates that the radius of the element will be 10 pixels.

z-index: number

Sets the stack order of an element, similar to the CSS z-index. The element with the highest z-index will be rendered on top of every other element.

Example:

  • z-index: 100 sets the element's z-index.

Graph Style Script language usage

This guide will show you how to easily get started with the Graph Style Script language. GSS is a language for customizing the visual display of graphs. For a complete list of available features consult the Style script reference guide.

Graph example

In this guide, we will use an example graph with European countries and cities. The data can be found here. Countries have the label Country, while cities have the label City. All nodes have the property name. Cities have many additional properties, including country (containing country) and drinks_USD (average drink price).

Setting graph labels

We want to label country nodes with country names, and city nodes with city names and containing country names. To achieve that we can use two directives. The first one selects countries and the second one selects cities.

@NodeStyle HasLabel(node, "Country") {
  label: Property(node, "name")
}

@NodeStyle HasLabel(node, "City") {
    label: Format("{cityName}, {countryName}",
                  Property(node, "name"),
                  Property(node, "country"))
}

In the case of the Format function, content inside the curly braces is ignored but can be helpful for clarity.

Setting node images

It would be nice to display flags in the country nodes. This can be achieved using URLs of flag images. There is a website that hosts many world flags so we can use images from there. Their API expects a country name as a part of the URL path so we will make the following directive.

@NodeStyle HasLabel(node, "Country") {
  image-url: Format("https://cdn.countryflags.com/thumbs/{}/flag-800.png",
                    LowerCase(Property(node, "name")))
}

Unfortunately, this won't work for all countries. Flags for England and Scotland cannot be found on the website because they aren't real countries. So we can get around that by providing custom directives below the general one above.

@NodeStyle Equals(Property(node, "name"), "England") {
   image-url: "https://upload.wikimedia.org/wikipedia/en/thumb/b/be/Flag_of_England.svg/2560px-Flag_of_England.svg.png"
}

@NodeStyle Equals(Property(node, "name"), "Scotland") {
  image-url: "https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Flag_of_Scotland.svg/1200px-Flag_of_Scotland.svg.png"
 }

Also, URLs for a country name with whitespace inside them don't so we also have to provide custom URLs for the Czech Republic and Bosnia and Herzegovina.

@NodeStyle Equals(Property(node, "name"), "Bosnia and Herzegovina") {
   image-url: "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/Flag_of_Bosnia_and_Herzegovina.svg/1200px-Flag_of_Bosnia_and_Herzegovina.svg.png"
 }

 @NodeStyle Equals(Property(node, "name"), "Czech Republic") {
   image-url: "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Flag_of_the_Czech_Republic.svg/2560px-Flag_of_the_Czech_Republic.svg.png"
 }

Now all the country nodes have their flags displayed.

Highlighting interesting nodes

We can highlight nodes with low drink prices in the following way. We want to use a beer image and a bigger size along with a red shadow.

@NodeStyle And(
     HasLabel(node, "City"),
     Less(Property(node, "drinks_USD"), 5)) {
  size: 50
  image-url: "https://www.sciencenews.org/wp-content/uploads/2020/05/050620_mt_beer_feat-1028x579.jpg"
  shadow-color: red
 }

Caching results for faster performance

To normalize some value, for example, the size or width of all the nodes or relationships in the graph, find the minimum and maximum values of all nodes. For example, a node labled "Person"has the propertyagethat holds the age information of a particular person. We want the node propertysize` to be 5 for the youngest person and 20 for the oldest one in the presented graph. All other node sizes should be normalized within that range.

One of the solutions could look like this:

// Size range min/max variables
Define(MIN_SIZE, 5)
Define(MAX_SIZE, 20)
Define(PROP_NAME, "age")
Define(SIZE_RANGE, Sub(MAX_SIZE, MIN_SIZE))

// A set of utility functions
// Create a new array of property values from an array of nodes
Define(GetProperties, Function(nodes, propName,
  Map(nodes, Function(singleNode, Property(singleNode, propName)))
))
// Keep only the numeric values from an array of values
Define(KeepNumericValues, Function(values,
  Filter(values, Function(value, IsNumber(value)))
))

// Functions to find min and max value in the input nodes
Define(GetMaxValue, Function(nodes,
  Max(KeepNumericValues(GetProperties(nodes, PROP_NAME)))
))
Define(GetMinValue, Function(nodes,
  Min(KeepNumericValues(GetProperties(nodes, PROP_NAME)))
))

// Normalize function that receives two inputs: node (n) and
// graph (g) and returns normalized value into a range
// [MIN_SIZE, MAX_SIZE]
Define(Normalize, Function(n, g,
  Add(
    MIN_SIZE,
    Mul(
      SIZE_RANGE,
      Div(
        Sub(Property(n, PROP_NAME), GetMinValue(Nodes(g))),
        Sub(GetMaxValue(Nodes(g)), GetMinValue(Nodes(g)))
      )
    )
  )
))

// For all nodes with the label "Person" and numeric property "age"
@NodeStyle And(HasLabel(node, "Person"), IsNumber(Property(node, PROP_NAME))) {
  color: white
  size: Normalize(node, graph)
  width: Div(Normalize(node, graph), 5)
  label: Format("Age: {}", AsText(Property(node, PROP_NAME)))
}

Using Graph Style Script to style different nodes by its size

The problem with the solution above is slow performance. The Normalize function is called twice for each node in the graph view. Each Normalize call iterates through all nodes three times: two times for GetMinValue and once for GetMaxValue. For small graphs, you won't see a difference in performance but as the number of nodes rises the performance issues will follow.

To solve this issue, cache the results by calculating outside of @NodeStyle and @EdgeStyle directives where the variable graph is also available. Inside the @NodeStyle directive, a local variable can be used to store the normalized value and use it with size and width properties thus calling the Normalize function only once.

Check the improved GSS code below:

// Size range min/max variables
Define(MIN_SIZE, 5)
Define(MAX_SIZE, 20)
Define(PROP_NAME, "age")
Define(SIZE_RANGE, Sub(MAX_SIZE, MIN_SIZE))

// A set of utility functions
// Create a new array of property values from an array of nodes
Define(GetProperties, Function(nodes, propName,
  Map(nodes, Function(singleNode, Property(singleNode, propName)))
))
// Keep only the numeric values from an array of values
Define(KeepNumericValues, Function(values,
  Filter(values, Function(value, IsNumber(value)))
))

// Variables MAX_VALUE and MIN_VALUE will hold the max and min
// values of all node properties.
// The If statement is used to handle errors when there are no values to calculate
// min and max from.
Define(MAX_VALUE, If(
  Greater(NodeCount(graph), 0),
  Max(KeepNumericValues(GetProperties(Nodes(graph), PROP_NAME))),
  0
))
Define(MIN_VALUE, If(
  Greater(NodeCount(graph), 0),
  Min(KeepNumericValues(GetProperties(Nodes(graph), PROP_NAME))),
  0
))

// Normalize function that receives one inputs: node and
// returns normalized value into a range [MIN_SIZE, MAX_SIZE]
Define(Normalize, Function(n,
  Add(
    MIN_SIZE,
    Mul(
      SIZE_RANGE,
      Div(
        Sub(Property(n, PROP_NAME), MIN_VALUE),
        Sub(MAX_VALUE, MIN_VALUE)
      )
    )
  )
))

// For all the nodes with label "Person" and numeric property "age"
@NodeStyle And(HasLabel(node, "Person"), IsNumber(Property(node, PROP_NAME))) {
  // Local variable used to cache a result from function Normalize
  Define(NORM, Normalize(node))

  color: white
  size: NORM
  width: Div(NORM, 5)
  label: Format("Age: {}", AsText(Property(node, PROP_NAME)))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment