diff --git a/docs/k8s-minikube.md b/docs/k8s-minikube.md index 39bba01c4..dc957a6d7 100644 --- a/docs/k8s-minikube.md +++ b/docs/k8s-minikube.md @@ -39,15 +39,22 @@ kubectl create clusterrolebinding dashboard-admin-sa --clusterrole=cluster-admin kubectl get secrets kubectl describe secret dashboard-admin-sa-token-***** ``` -* enter the k8s dashboard: go to http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/. +* enter the k8s dashboard: go + to http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/. + +## Install example Helm Charts -## Install example Helm Charts * helm repo add bitnami https://charts.bitnami.com/bitnami * helm install redis bitnami/redis --set serviceType=NodePort * helm install nivio-wordpress bitnami/wordpress +## Change URL in K8s config file + +* change URL under sources to K8s API URL + ## Start nivio + ``` SEED=$(pwd)./src/test/resources/example/example_k8s.yml java -jar target/nivio.jar ``` diff --git a/docs/source/inc_labels.rst b/docs/source/inc_labels.rst index a501de5da..65d5ffc48 100644 --- a/docs/source/inc_labels.rst +++ b/docs/source/inc_labels.rst @@ -1,10 +1,11 @@ * ``capability`` The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence. -* ``color`` A hex color code to override the inherited group color +* ``color`` A hex color code (items inherit group colors as default) * ``costs`` Running costs of the item. * ``fill`` Background image (for displaying purposes). * ``frameworks`` A comma-separated list of frameworks as key-value pairs (key is name, value is version). * ``health`` Description of the item's health status. * ``icon`` Icon/image (for displaying purposes). +* ``label`` A custom label (like a note, but very short). * ``layer`` A technical layer. * ``lifecycle`` A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``). * ``note`` A custom note. @@ -14,6 +15,6 @@ * ``software`` Software/OS name. * ``stability`` Description of the item's stability. * ``team`` Name of the responsible team (e.g. technical owner). -* ``type`` The type (service, database, queue, load balancer, etc.). * ``version`` The version (e.g. software version or protocol version). -* ``visibility`` Visibility to other items. \ No newline at end of file +* ``visibility`` Visibility to other items. +* ``weight`` Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given. \ No newline at end of file diff --git a/docs/source/model.rst b/docs/source/model.rst index b40b9367e..54b8f6e2e 100644 --- a/docs/source/model.rst +++ b/docs/source/model.rst @@ -109,3 +109,4 @@ Service references are required to describe a ``provider`` relation or ``dataflo - target: anothergroup/anotherservice format: json type: dataflow + label: Data Sync diff --git a/docs/source/output.rst b/docs/source/output.rst index 8e02e96e0..a9315fedf 100644 --- a/docs/source/output.rst +++ b/docs/source/output.rst @@ -46,19 +46,14 @@ like "account". - identifier: bar type: account -The following types are translated icons to maintain backward compatibility: - -* CACHE -> "flash-circle" -* CONTAINER -> "inbox" -* FIREWALL -> "wall" -* HUMANUSER -> "account" -* INTERFACE -> "connection" -* KEYVALUESTORE -> "keyvaluestore" -* LOADBALANCER -> "loadbalancer" -* MESSAGEQUEUE -> "tray-full" -* MOBILECLIENT -> "cellphone" -* VOLUME -> "harddisk" -* WEBSERVICE -> "application" +Alternatively you can use any icon name on the icon field. + +.. code-block:: yaml + :linenos: + + items: + - identifier: bar + icon: flash-circle Vendor Logos ^^^^^^^^^^^^^ diff --git a/docs/source/schema/.openapi-generator/VERSION b/docs/source/schema/.openapi-generator/VERSION index acf69b48b..e230c8396 100644 --- a/docs/source/schema/.openapi-generator/VERSION +++ b/docs/source/schema/.openapi-generator/VERSION @@ -1 +1 @@ -5.1.0 \ No newline at end of file +5.3.0 \ No newline at end of file diff --git a/docs/source/schema/Models/Branding.rst b/docs/source/schema/Models/Branding.rst index 277189d29..4c5d95fe5 100644 --- a/docs/source/schema/Models/Branding.rst +++ b/docs/source/schema/Models/Branding.rst @@ -18,9 +18,4 @@ Map branding (tweaks visuals) - A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map. - optional, defaults to null - https://acme.com/css/acme.css - * - mapLogo - - String - - A resolvable URL pointing to an image. This image is included (embedded as data-url) in the generated SVG map. - - optional, defaults to null - - https://acme.com/images/logo.png diff --git a/docs/source/schema/Models/GroupDescription.rst b/docs/source/schema/Models/GroupDescription.rst index f81c1df1f..43813ec4c 100644 --- a/docs/source/schema/Models/GroupDescription.rst +++ b/docs/source/schema/Models/GroupDescription.rst @@ -13,43 +13,33 @@ A group of items. Could be used as bounded context, for instance. - Remarks - Example - * - labels - - Map - - Labels related to the group. - - optional, defaults to null - - null - * - identifier - - String - - A unique identifier for the group (also used as name). Descriptions are merged based on the identifier. - - **required**, defaults to null - - shipping - * - owner - - String - - The business owner of the group. - - optional, defaults to null - - null - * - description + * - color - String - - A brief description. + - The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed. - optional, defaults to null - - null + - 05ffaa * - contact - String - A contact method, preferably email. - optional, defaults to null - null - * - color - - String - - The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed. - - optional, defaults to null - - 05ffaa * - contains - List - A list of item identifiers or SQL-like queries to easily assign items to this group. - optional, defaults to null - identifier LIKE 'DB1' - * - name + * - description + - String + - A brief description. + - optional, defaults to null + - null + * - identifier - String + - A unique identifier for the group (also used as name). Descriptions are merged based on the identifier. + - **required**, defaults to null + - shipping + * - labels + - Map - - optional, defaults to null - null @@ -58,4 +48,14 @@ A group of items. Could be used as bounded context, for instance. - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. - optional, defaults to null - github: https://github.com/dedica-team/nivio + * - name + - String + - + - optional, defaults to null + - null + * - owner + - String + - The business owner of the group. + - optional, defaults to null + - null diff --git a/docs/source/schema/Models/InterfaceDescription.rst b/docs/source/schema/Models/InterfaceDescription.rst index 40fb7cbdc..5cc0fd2d8 100644 --- a/docs/source/schema/Models/InterfaceDescription.rst +++ b/docs/source/schema/Models/InterfaceDescription.rst @@ -13,6 +13,11 @@ Describes a low-level interface of an item. - Remarks - Example + * - deprecated + - Boolean + - + - optional, defaults to null + - null * - description - String - A brief description. @@ -23,22 +28,17 @@ Describes a low-level interface of an item. - The payload format. - optional, defaults to null - null - * - url + * - name - String - - A URL describing the endpoint. + - - optional, defaults to null - null - * - protection + * - parameters - String - - A description of the interface protection method. - - optional, defaults to null - - null - * - deprecated - - Boolean - - optional, defaults to null - null - * - name + * - path - String - - optional, defaults to null @@ -48,9 +48,9 @@ Describes a low-level interface of an item. - - optional, defaults to null - null - * - path + * - protection - String - - + - A description of the interface protection method. - optional, defaults to null - null * - summary @@ -58,9 +58,9 @@ Describes a low-level interface of an item. - - optional, defaults to null - null - * - parameters + * - url - String - - + - A URL describing the endpoint. - optional, defaults to null - null diff --git a/docs/source/schema/Models/ItemDescription.rst b/docs/source/schema/Models/ItemDescription.rst index 18a1c4582..3cc3fb852 100644 --- a/docs/source/schema/Models/ItemDescription.rst +++ b/docs/source/schema/Models/ItemDescription.rst @@ -13,24 +13,19 @@ List of configuration sources. Handled in the given order, latter extend/overwri - Remarks - Example - * - labels - - Map - - Key-value pair labels for an item. - - optional, defaults to null - - null - * - identifier + * - address - String - - Immutable unique identifier (maybe use an URN). Primary means to identify items in searches. - - **required**, defaults to null + - The technical address of the item (should be an URI). Taken into account when matching relation endpoints. + - optional, defaults to null - null - * - name + * - color - String - - A human readable name/title. The name is considered when items are searched. + - Overrides the group color. Use an HTML hex color code without the leading hash. - optional, defaults to null - - my beautiful service - * - owner + - 4400FF + * - contact - String - - The business owner of the item. Preferably use an email address. + - The primary way to contact a responsible person or team. Preferably use an email address. - optional, defaults to null - johnson@acme.com * - description @@ -38,51 +33,61 @@ List of configuration sources. Handled in the given order, latter extend/overwri - A brief description. - optional, defaults to null - null - * - contact - - String - - The primary way to contact a responsible person or team. Preferably use an email address. + * - frameworks + - Map + - The parts used to create the item. Usually refers to technical frameworks. - optional, defaults to null - - johnson@acme.com + - java: 8 * - group - String - The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to common. - optional, defaults to null - shipping + * - icon + - String + - An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work). + - optional, defaults to null + - null + * - identifier + - String + - Immutable unique identifier (maybe use an URN). Primary means to identify items in searches. + - **required**, defaults to null + - null * - interfaces - Set - A collection of low level interfaces. Can be used to describe HTTP API endpoints for instance. - optional, defaults to null - null - * - providedBy - - List - - A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations. + * - labels + - Map + - - optional, defaults to null - - shipping-mysqldb - * - icon + - null + * - lifecycle - String - - An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work). + - The lifecycle state of an item. - optional, defaults to null - null - * - color - - String - - Overrides the group color. Use an HTML hex color code without the leading hash. + * - links + - Map + - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. - optional, defaults to null - - 4400FF - * - address + - github: https://github.com/dedica-team/nivio + * - name - String - - The technical address of the item (should be an URI). Taken into account when matching relation endpoints. + - A human readable name/title. The name is considered when items are searched. - optional, defaults to null - - null - * - type + - my beautiful service + * - owner - String - - The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. + - The business owner of the item. Preferably use an email address. - optional, defaults to null - - service|database|volume - * - lifecycle - - String - - The lifecycle state of an item. + - johnson@acme.com + * - providedBy + - List + - A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations. - optional, defaults to null - - null + - shipping-mysqldb * - status - List - A list of statuses that works like hardcoded KPIs. @@ -93,19 +98,14 @@ List of configuration sources. Handled in the given order, latter extend/overwri - A list of statuses that works like hardcoded KPIs. - optional, defaults to null - null - * - frameworks - - Map - - The parts used to create the item. Usually refers to technical frameworks. - - optional, defaults to null - - java: 8 * - tags - List - - optional, defaults to null - null - * - links - - Map - - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. + * - type + - String + - The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon. - optional, defaults to null - - github: https://github.com/dedica-team/nivio + - service|database|volume diff --git a/docs/source/schema/Models/KPIConfig.rst b/docs/source/schema/Models/KPIConfig.rst index 8838e6fc9..4e17e0997 100644 --- a/docs/source/schema/Models/KPIConfig.rst +++ b/docs/source/schema/Models/KPIConfig.rst @@ -18,11 +18,21 @@ The configuration of landscape specific key performance indicators that derive s - Description of the purpose of the KPI - optional, defaults to null - null + * - enabled + - Boolean + - A flag indicating that the KPI is active. Can be used to disable default KPIs. + - optional, defaults to null + - null * - label - String - Key of the label to evaluate - - optional, defaults to null + - **required**, defaults to null - costs + * - matches + - Map + - A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers. + - optional, defaults to null + - RED: BAD;err.* * - messageTemplate - String - Template for the displayed message, containing a placeholder for the assessed value '%s @@ -33,14 +43,4 @@ The configuration of landscape specific key performance indicators that derive s - A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers. - optional, defaults to null - GREEN: 0;99.999999 - * - matches - - Map - - A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers. - - optional, defaults to null - - RED: BAD;err.* - * - enabled - - Boolean - - A flag indicating that the KPI is active. Can be used to disable default kpis. - - optional, defaults to null - - null diff --git a/docs/source/schema/Models/LandscapeConfig.rst b/docs/source/schema/Models/LandscapeConfig.rst index d52a9e346..8a34baab4 100644 --- a/docs/source/schema/Models/LandscapeConfig.rst +++ b/docs/source/schema/Models/LandscapeConfig.rst @@ -13,11 +13,21 @@ Configuration of key performance indicators (i.e. status indicators) and layouti - Remarks - Example + * - branding + - Branding + - + - optional, defaults to null + - null * - greedy - Boolean - Flag that enables instant creation items based relation targets that cannot be found in the sources. - optional, defaults to null - null + * - groupBlacklist + - List + - Names or patterns of groups that should be excluded from the landscape. Used to improve automatic scanning results. + - optional, defaults to null + - .*infra.* * - groupLayoutConfig - LayoutConfig - @@ -28,24 +38,14 @@ Configuration of key performance indicators (i.e. status indicators) and layouti - - optional, defaults to null - null - * - groupBlacklist - - List - - Names or patterns of groups that should be excluded from the landscape. Used to improve automatic scanning results. + * - kpis + - Map + - Key performance indicator configs. Each KPI must have a unique identifier. - optional, defaults to null - - .*infra.* + - null * - labelBlacklist - List - Names or patterns of labels that should be ignored. Used to improve automatic scanning results. - optional, defaults to null - .*COMPOSITION.* - * - branding - - Branding - - - - optional, defaults to null - - null - * - kpis - - Map - - Key performance indicator configs. Each KPI must have a unique identifier. - - optional, defaults to null - - null diff --git a/docs/source/schema/Models/LandscapeDescription.rst b/docs/source/schema/Models/LandscapeDescription.rst index c887e1a45..696678ffe 100644 --- a/docs/source/schema/Models/LandscapeDescription.rst +++ b/docs/source/schema/Models/LandscapeDescription.rst @@ -13,15 +13,15 @@ LandscapeDescription - Remarks - Example - * - identifier + * - color - String - - Immutable unique identifier. Maybe use an URN. - - **required**, defaults to null + - + - optional, defaults to null - null - * - name - - String - - Human readable name. - - **required**, defaults to null + * - config + - LandscapeConfig + - + - optional, defaults to null - null * - contact - String @@ -33,54 +33,29 @@ LandscapeDescription - A brief description of the landscape. - optional, defaults to null - null - * - owner - - String - - The business owner (person or team), preferably an email address. - - optional, defaults to null - - null - * - templates - - Map - - Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items. - - optional, defaults to null - - null - * - sources - - List - - - - optional, defaults to null - - null - * - config - - LandscapeConfig - - - - optional, defaults to null - - null * - groups - Map - Description of item groups (optional, can also be given in sources). - optional, defaults to null - null - * - labels - - Map - - Additional labels for the landscape. - - optional, defaults to null - - null - * - color + * - icon - String - - optional, defaults to null - null - * - icon + * - identifier - String - - - - optional, defaults to null + - Immutable unique identifier. Maybe use an URN. + - **required**, defaults to null - null * - items - List - List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc. - optional, defaults to null - null - * - partial - - Boolean - - marks that the landscape is not complete, but an update + * - labels + - Map + - - optional, defaults to null - null * - links @@ -88,4 +63,29 @@ LandscapeDescription - Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component. - optional, defaults to null - github: https://github.com/dedica-team/nivio + * - name + - String + - Human readable name. + - **required**, defaults to null + - null + * - owner + - String + - The business owner (person or team), preferably an email address. + - optional, defaults to null + - null + * - partial + - Boolean + - marks that the landscape is not complete, but an update + - optional, defaults to null + - null + * - sources + - List + - + - optional, defaults to null + - null + * - templates + - Map + - Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items. + - optional, defaults to null + - null diff --git a/docs/source/schema/Models/LayoutConfig.rst b/docs/source/schema/Models/LayoutConfig.rst index 843ee8bb8..51461cf3d 100644 --- a/docs/source/schema/Models/LayoutConfig.rst +++ b/docs/source/schema/Models/LayoutConfig.rst @@ -13,11 +13,6 @@ Layout configuration. See https://jgraph.github.io/mxgraph/java/docs/com/mxgraph - Remarks - Example - * - maxIterations - - Integer - - The maximum number of iterations. More iterations theoretically lead to better results. - - optional, defaults to null - - null * - forceConstantFactor - Float - A factor to influence the attracting and repulsive forces in a layout. @@ -28,6 +23,11 @@ Layout configuration. See https://jgraph.github.io/mxgraph/java/docs/com/mxgraph - A factor to influence maximum distance where forces are applied. - optional, defaults to null - null + * - maxIterations + - Integer + - The maximum number of iterations. More iterations theoretically lead to better results. + - optional, defaults to null + - null * - minDistanceLimitFactor - Float - A factor to influence minimum distance where forces are applied. diff --git a/docs/source/schema/Models/Link.rst b/docs/source/schema/Models/Link.rst index dad30c0bd..661f826ec 100644 --- a/docs/source/schema/Models/Link.rst +++ b/docs/source/schema/Models/Link.rst @@ -13,62 +13,62 @@ A link to an external resource. Contains a href (URL) plus various attributes fo - Remarks - Example - * - rel + * - basicAuthPassword - String - - hateoas relation type + - - optional, defaults to null - null - * - href - - String - - The link target. - - **required**, defaults to null - - null - * - hreflang + * - basicAuthUsername - String - - hateoas language + - - optional, defaults to null - null - * - media + * - deprecation - String - - hateoas media type + - deprecation info (typically used in OpenAPI specs) - optional, defaults to null - null - * - title + * - headerTokenName - String - - hateoas title + - - optional, defaults to null - null - * - type + * - headerTokenValue - String - - optional, defaults to null - null - * - deprecation + * - href - String - - deprecation info (typically used in OpenAPI specs) + - The link target. + - **required**, defaults to null + - null + * - hreflang + - String + - hateoas language - optional, defaults to null - null - * - name + * - media - String - - HateOAS / OpenAPI name + - hateoas media type - optional, defaults to null - null - * - basicAuthUsername + * - name - String - - + - HateOAS / OpenAPI name - optional, defaults to null - null - * - basicAuthPassword + * - rel - String - - + - hateoas relation type - optional, defaults to null - null - * - headerTokenName + * - title - String - - + - hateoas title - optional, defaults to null - null - * - headerTokenValue + * - type - String - - optional, defaults to null diff --git a/docs/source/schema/Models/SourceReference.rst b/docs/source/schema/Models/SourceReference.rst index f406e9dae..edafa9c71 100644 --- a/docs/source/schema/Models/SourceReference.rst +++ b/docs/source/schema/Models/SourceReference.rst @@ -13,62 +13,72 @@ This is a reference to a configuration file. - Remarks - Example - * - rel + * - assignTemplates + - Map + - A map with template identifier as key and item identifier matchers as value + - optional, defaults to null + - endOfLife: [web, "java6*"] + * - basicAuthPassword - String - - hateoas relation type + - - optional, defaults to null - null - * - href + * - basicAuthUsername - String - - The link target. - - **required**, defaults to null + - + - optional, defaults to null - null - * - hreflang + * - deprecation - String - - hateoas language + - deprecation info (typically used in OpenAPI specs) - optional, defaults to null - null - * - media + * - format - String - - hateoas media type + - The input format. - optional, defaults to null - null - * - title + * - headerTokenName - String - - hateoas title + - - optional, defaults to null - null - * - type + * - headerTokenValue - String - - optional, defaults to null - null - * - deprecation + * - href - String - - deprecation info (typically used in OpenAPI specs) + - The link target. + - **required**, defaults to null + - null + * - hreflang + - String + - hateoas language - optional, defaults to null - null - * - name + * - media - String - - HateOAS / OpenAPI name + - hateoas media type - optional, defaults to null - null - * - basicAuthUsername + * - name - String - - + - HateOAS / OpenAPI name - optional, defaults to null - null - * - basicAuthPassword + * - rel - String - - + - hateoas relation type - optional, defaults to null - null - * - headerTokenName + * - title - String - - + - hateoas title - optional, defaults to null - null - * - headerTokenValue + * - type - String - - optional, defaults to null @@ -78,14 +88,4 @@ This is a reference to a configuration file. - A URL, but can also be a relative path. - optional, defaults to null - ./a/items.yaml - * - format - - String - - The input format. - - optional, defaults to null - - null - * - assignTemplates - - Map - - A map with template identifier as key and item identifier matchers as value - - optional, defaults to null - - endOfLife: [web, "java6*"] diff --git a/docs/source/schema/spec.json b/docs/source/schema/spec.json index 60951921a..b00846365 100644 --- a/docs/source/schema/spec.json +++ b/docs/source/schema/spec.json @@ -15,11 +15,6 @@ "type" : "string", "description" : "A resolvable URL pointing to a CSS stylesheet. This stylesheet is included in the generated SVG map. Use is to style the appearance of the map.", "example" : "https://acme.com/css/acme.css" - }, - "mapLogo" : { - "type" : "string", - "description" : "A resolvable URL pointing to an image. This image is included (embedded as data-url) in the generated SVG map.", - "example" : "https://acme.com/images/logo.png" } }, "description" : "Map branding (tweaks visuals)" @@ -28,36 +23,15 @@ "required" : [ "identifier" ], "type" : "object", "properties" : { - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Labels related to the group." - }, - "description" : "Labels related to the group." - }, - "identifier" : { - "type" : "string", - "description" : "A unique identifier for the group (also used as name). Descriptions are merged based on the identifier.", - "example" : "shipping" - }, - "owner" : { - "type" : "string", - "description" : "The business owner of the group." - }, - "description" : { + "color" : { "type" : "string", - "description" : "A brief description." + "description" : "The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed.", + "example" : "05ffaa" }, "contact" : { "type" : "string", "description" : "A contact method, preferably email." }, - "color" : { - "type" : "string", - "description" : "The HTML (hexcode only!) color used to draw the group and its items. If no color is given, one is computed.", - "example" : "05ffaa" - }, "contains" : { "type" : "array", "description" : "A list of item identifiers or SQL-like queries to easily assign items to this group.", @@ -68,8 +42,21 @@ "example" : "identifier LIKE 'DB1'" } }, - "name" : { - "type" : "string" + "description" : { + "type" : "string", + "description" : "A brief description." + }, + "identifier" : { + "type" : "string", + "description" : "A unique identifier for the group (also used as name). Descriptions are merged based on the identifier.", + "example" : "shipping" + }, + "labels" : { + "type" : "object", + "additionalProperties" : { + "type" : "string" + }, + "writeOnly" : true }, "links" : { "type" : "object", @@ -78,6 +65,13 @@ }, "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", "example" : "github: https://github.com/dedica-team/nivio" + }, + "name" : { + "type" : "string" + }, + "owner" : { + "type" : "string", + "description" : "The business owner of the group." } }, "description" : "A group of items. Could be used as bounded context, for instance." @@ -85,6 +79,9 @@ "InterfaceDescription" : { "type" : "object", "properties" : { + "deprecated" : { + "type" : "boolean" + }, "description" : { "type" : "string", "description" : "A brief description." @@ -93,32 +90,29 @@ "type" : "string", "description" : "The payload format." }, - "url" : { - "type" : "string", - "description" : "A URL describing the endpoint.", - "format" : "url" - }, - "protection" : { - "type" : "string", - "description" : "A description of the interface protection method." - }, - "deprecated" : { - "type" : "boolean" - }, "name" : { "type" : "string" }, - "payload" : { + "parameters" : { "type" : "string" }, "path" : { "type" : "string" }, - "summary" : { + "payload" : { "type" : "string" }, - "parameters" : { + "protection" : { + "type" : "string", + "description" : "A description of the interface protection method." + }, + "summary" : { "type" : "string" + }, + "url" : { + "type" : "string", + "description" : "A URL describing the endpoint.", + "format" : "url" } }, "description" : "Describes a low-level interface of an item." @@ -127,43 +121,49 @@ "required" : [ "identifier" ], "type" : "object", "properties" : { - "labels" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "Key-value pair labels for an item." - }, - "description" : "Key-value pair labels for an item." - }, - "identifier" : { - "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "address" : { "type" : "string", - "description" : "Immutable unique identifier (maybe use an URN). Primary means to identify items in searches." + "description" : "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." }, - "name" : { + "color" : { "type" : "string", - "description" : "A human readable name/title. The name is considered when items are searched.", - "example" : "my beautiful service" + "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", + "example" : "4400FF" }, - "owner" : { + "contact" : { "type" : "string", - "description" : "The business owner of the item. Preferably use an email address.", + "description" : "The primary way to contact a responsible person or team. Preferably use an email address.", "example" : "johnson@acme.com" }, "description" : { "type" : "string", "description" : "A brief description." }, - "contact" : { - "type" : "string", - "description" : "The primary way to contact a responsible person or team. Preferably use an email address.", - "example" : "johnson@acme.com" + "frameworks" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "example" : "java: 8" + }, + "description" : "The parts used to create the item. Usually refers to technical frameworks.", + "writeOnly" : true, + "example" : "java: 8" }, "group" : { "type" : "string", "description" : "The identifier of the group this item belongs in. Every item requires to be member of a group internally, so if nothing is given, the value is set to common.", "example" : "shipping" }, + "icon" : { + "type" : "string", + "description" : "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." + }, + "identifier" : { + "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "type" : "string", + "description" : "Immutable unique identifier (maybe use an URN). Primary means to identify items in searches." + }, "interfaces" : { "uniqueItems" : true, "type" : "array", @@ -172,6 +172,37 @@ "$ref" : "#/components/schemas/InterfaceDescription" } }, + "labels" : { + "type" : "object", + "additionalProperties" : { + "type" : "string" + }, + "writeOnly" : true + }, + "lifecycle" : { + "type" : "string", + "description" : "The lifecycle state of an item.", + "writeOnly" : true, + "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] + }, + "links" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/Link" + }, + "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example" : "github: https://github.com/dedica-team/nivio" + }, + "name" : { + "type" : "string", + "description" : "A human readable name/title. The name is considered when items are searched.", + "example" : "my beautiful service" + }, + "owner" : { + "type" : "string", + "description" : "The business owner of the item. Preferably use an email address.", + "example" : "johnson@acme.com" + }, "providedBy" : { "type" : "array", "description" : "A collection of identifiers which are providers for this item (i.e. hard dependencies that are required). This is a convenience field to build relations.", @@ -182,24 +213,6 @@ "example" : "shipping-mysqldb" } }, - "icon" : { - "type" : "string", - "description" : "An icon name or URL to set the displayed map icon. The default icon set is https://materialdesignicons.com/ and all names can be used (aliases do not work)." - }, - "color" : { - "type" : "string", - "description" : "Overrides the group color. Use an HTML hex color code without the leading hash.", - "example" : "4400FF" - }, - "address" : { - "type" : "string", - "description" : "The technical address of the item (should be an URI). Taken into account when matching relation endpoints." - }, - "type" : { - "type" : "string", - "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", - "example" : "service|database|volume" - }, "status" : { "type" : "array", "description" : "A list of statuses that works like hardcoded KPIs.", @@ -226,52 +239,47 @@ "description" : "A list of statuses that works like hardcoded KPIs." } }, - "frameworks" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "example" : "java: 8" - }, - "description" : "The parts used to create the item. Usually refers to technical frameworks.", - "writeOnly" : true, - "example" : "java: 8" - }, - "lifecycle" : { - "type" : "string", - "description" : "The lifecycle state of an item.", - "writeOnly" : true, - "enum" : [ "PLANNED", "INTEGRATION", "TEST", "PRODUCTION", "END_OF_LIFE", "EOL" ] - }, "tags" : { "type" : "array", "items" : { "type" : "string" } }, - "links" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/Link" - }, - "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example" : "github: https://github.com/dedica-team/nivio" + "type" : { + "type" : "string", + "description" : "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", + "example" : "service|database|volume" } }, "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc." }, "KPIConfig" : { + "required" : [ "label" ], "type" : "object", "properties" : { "description" : { "type" : "string", "description" : "Description of the purpose of the KPI" }, + "enabled" : { + "type" : "boolean", + "description" : "A flag indicating that the KPI is active. Can be used to disable default KPIs." + }, "label" : { "type" : "string", "description" : "Key of the label to evaluate", "example" : "costs" }, + "matches" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "description" : "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", + "example" : "RED: BAD;err.*" + }, + "description" : "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", + "example" : "RED: BAD;err.*" + }, "messageTemplate" : { "type" : "string", "description" : "Template for the displayed message, containing a placeholder for the assessed value '%s", @@ -286,20 +294,6 @@ }, "description" : "A map of number based ranges that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate upper and lower bounds. Tries to evaluate label values as numbers.", "example" : "GREEN: 0;99.999999" - }, - "matches" : { - "type" : "object", - "additionalProperties" : { - "type" : "string", - "description" : "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", - "example" : "RED: BAD;err.*" - }, - "description" : "A map of string based matchers that determine the resulting status (GREEN|YELLOW|ORANGE|RED|BROWN). Use a semicolon to separate matchers.", - "example" : "RED: BAD;err.*" - }, - "enabled" : { - "type" : "boolean", - "description" : "A flag indicating that the KPI is active. Can be used to disable default kpis." } }, "description" : "The configuration of landscape specific key performance indicators that derive status information from landscape components. Usually the KPIs work on labels" @@ -307,16 +301,13 @@ "LandscapeConfig" : { "type" : "object", "properties" : { + "branding" : { + "$ref" : "#/components/schemas/Branding" + }, "greedy" : { "type" : "boolean", "description" : "Flag that enables instant creation items based relation targets that cannot be found in the sources." }, - "groupLayoutConfig" : { - "$ref" : "#/components/schemas/LayoutConfig" - }, - "itemLayoutConfig" : { - "$ref" : "#/components/schemas/LayoutConfig" - }, "groupBlacklist" : { "type" : "array", "description" : "Names or patterns of groups that should be excluded from the landscape. Used to improve automatic scanning results.", @@ -327,6 +318,19 @@ "example" : ".*infra.*" } }, + "groupLayoutConfig" : { + "$ref" : "#/components/schemas/LayoutConfig" + }, + "itemLayoutConfig" : { + "$ref" : "#/components/schemas/LayoutConfig" + }, + "kpis" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/KPIConfig" + }, + "description" : "Key performance indicator configs. Each KPI must have a unique identifier." + }, "labelBlacklist" : { "type" : "array", "description" : "Names or patterns of labels that should be ignored. Used to improve automatic scanning results.", @@ -336,16 +340,6 @@ "description" : "Names or patterns of labels that should be ignored. Used to improve automatic scanning results.", "example" : ".*COMPOSITION.*" } - }, - "branding" : { - "$ref" : "#/components/schemas/Branding" - }, - "kpis" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/KPIConfig" - }, - "description" : "Key performance indicator configs. Each KPI must have a unique identifier." } }, "description" : "Configuration of key performance indicators (i.e. status indicators) and layouting tweaks." @@ -354,14 +348,11 @@ "required" : [ "identifier", "name" ], "type" : "object", "properties" : { - "identifier" : { - "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", - "type" : "string", - "description" : "Immutable unique identifier. Maybe use an URN." + "color" : { + "type" : "string" }, - "name" : { - "type" : "string", - "description" : "Human readable name." + "config" : { + "$ref" : "#/components/schemas/LandscapeConfig" }, "contact" : { "type" : "string", @@ -371,78 +362,75 @@ "type" : "string", "description" : "A brief description of the landscape." }, - "owner" : { - "type" : "string", - "description" : "The business owner (person or team), preferably an email address." - }, - "templates" : { + "groups" : { "type" : "object", "additionalProperties" : { - "$ref" : "#/components/schemas/ItemDescription" + "$ref" : "#/components/schemas/GroupDescription" }, - "description" : "Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items." + "description" : "Description of item groups (optional, can also be given in sources)." }, - "sources" : { + "icon" : { + "type" : "string" + }, + "identifier" : { + "pattern" : "^[a-zA-Z0-9\\.\\:_-]{2,256}$", + "type" : "string", + "description" : "Immutable unique identifier. Maybe use an URN." + }, + "items" : { "type" : "array", + "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", "writeOnly" : true, "items" : { - "$ref" : "#/components/schemas/SourceReference" + "$ref" : "#/components/schemas/ItemDescription" } }, - "config" : { - "$ref" : "#/components/schemas/LandscapeConfig" - }, - "groups" : { + "labels" : { "type" : "object", "additionalProperties" : { - "$ref" : "#/components/schemas/GroupDescription" + "type" : "string" }, - "description" : "Description of item groups (optional, can also be given in sources)." + "writeOnly" : true }, - "labels" : { + "links" : { "type" : "object", "additionalProperties" : { - "type" : "string", - "description" : "Additional labels for the landscape." + "$ref" : "#/components/schemas/Link" }, - "description" : "Additional labels for the landscape." + "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", + "example" : "github: https://github.com/dedica-team/nivio" }, - "items" : { - "type" : "array", - "description" : "List of configuration sources. Handled in the given order, latter extend/overwrite earlier values like items etc.", - "writeOnly" : true, - "items" : { - "$ref" : "#/components/schemas/ItemDescription" - } + "name" : { + "type" : "string", + "description" : "Human readable name." + }, + "owner" : { + "type" : "string", + "description" : "The business owner (person or team), preferably an email address." }, "partial" : { "type" : "boolean", "description" : "marks that the landscape is not complete, but an update" }, - "icon" : { - "type" : "string" - }, - "color" : { - "type" : "string" + "sources" : { + "type" : "array", + "writeOnly" : true, + "items" : { + "$ref" : "#/components/schemas/SourceReference" + } }, - "links" : { + "templates" : { "type" : "object", "additionalProperties" : { - "$ref" : "#/components/schemas/Link" + "$ref" : "#/components/schemas/ItemDescription" }, - "description" : "Key-value pairs of related links. Some keys like 'github' cause that the endpoint data is parsed and added to to corresponding landscape component.", - "example" : "github: https://github.com/dedica-team/nivio" + "description" : "Item descriptions to be used as templates. All values except identifier and name will be applied to the assigned items." } } }, "LayoutConfig" : { "type" : "object", "properties" : { - "maxIterations" : { - "type" : "integer", - "description" : "The maximum number of iterations. More iterations theoretically lead to better results.", - "format" : "int32" - }, "forceConstantFactor" : { "type" : "number", "description" : "A factor to influence the attracting and repulsive forces in a layout.", @@ -453,6 +441,11 @@ "description" : "A factor to influence maximum distance where forces are applied.", "format" : "float" }, + "maxIterations" : { + "type" : "integer", + "description" : "The maximum number of iterations. More iterations theoretically lead to better results.", + "format" : "int32" + }, "minDistanceLimitFactor" : { "type" : "number", "description" : "A factor to influence minimum distance where forces are applied.", @@ -465,9 +458,25 @@ "required" : [ "href" ], "type" : "object", "properties" : { - "rel" : { + "basicAuthPassword" : { "type" : "string", - "description" : "hateoas relation type" + "writeOnly" : true + }, + "basicAuthUsername" : { + "type" : "string", + "writeOnly" : true + }, + "deprecation" : { + "type" : "string", + "description" : "deprecation info (typically used in OpenAPI specs)" + }, + "headerTokenName" : { + "type" : "string", + "writeOnly" : true + }, + "headerTokenValue" : { + "type" : "string", + "writeOnly" : true }, "href" : { "type" : "string", @@ -482,28 +491,60 @@ "type" : "string", "description" : "hateoas media type" }, + "name" : { + "type" : "string", + "description" : "HateOAS / OpenAPI name" + }, + "rel" : { + "type" : "string", + "description" : "hateoas relation type" + }, "title" : { "type" : "string", "description" : "hateoas title" }, "type" : { "type" : "string" + } + }, + "description" : "A link to an external resource. Contains a href (URL) plus various attributes for authentication and/or hateoas.", + "example" : "github: https://github.com/dedica-team/nivio" + }, + "SourceReference" : { + "required" : [ "href" ], + "type" : "object", + "properties" : { + "assignTemplates" : { + "type" : "object", + "additionalProperties" : { + "type" : "array", + "description" : "A map with template identifier as key and item identifier matchers as value", + "example" : "endOfLife: [web, \"java6*\"]", + "items" : { + "type" : "string", + "description" : "A map with template identifier as key and item identifier matchers as value", + "example" : "endOfLife: [web, \"java6*\"]" + } + }, + "description" : "A map with template identifier as key and item identifier matchers as value", + "example" : "endOfLife: [web, \"java6*\"]" }, - "deprecation" : { - "type" : "string", - "description" : "deprecation info (typically used in OpenAPI specs)" - }, - "name" : { + "basicAuthPassword" : { "type" : "string", - "description" : "HateOAS / OpenAPI name" + "writeOnly" : true }, "basicAuthUsername" : { "type" : "string", "writeOnly" : true }, - "basicAuthPassword" : { + "deprecation" : { "type" : "string", - "writeOnly" : true + "description" : "deprecation info (typically used in OpenAPI specs)" + }, + "format" : { + "type" : "string", + "description" : "The input format.", + "enum" : [ "nivio", "csv", "k8s", "rancher", "docker-compose-v2" ] }, "headerTokenName" : { "type" : "string", @@ -512,18 +553,6 @@ "headerTokenValue" : { "type" : "string", "writeOnly" : true - } - }, - "description" : "A link to an external resource. Contains a href (URL) plus various attributes for authentication and/or hateoas.", - "example" : "github: https://github.com/dedica-team/nivio" - }, - "SourceReference" : { - "required" : [ "href" ], - "type" : "object", - "properties" : { - "rel" : { - "type" : "string", - "description" : "hateoas relation type" }, "href" : { "type" : "string", @@ -538,61 +567,25 @@ "type" : "string", "description" : "hateoas media type" }, - "title" : { - "type" : "string", - "description" : "hateoas title" - }, - "type" : { - "type" : "string" - }, - "deprecation" : { - "type" : "string", - "description" : "deprecation info (typically used in OpenAPI specs)" - }, "name" : { "type" : "string", "description" : "HateOAS / OpenAPI name" }, - "basicAuthUsername" : { - "type" : "string", - "writeOnly" : true - }, - "basicAuthPassword" : { + "rel" : { "type" : "string", - "writeOnly" : true + "description" : "hateoas relation type" }, - "headerTokenName" : { + "title" : { "type" : "string", - "writeOnly" : true + "description" : "hateoas title" }, - "headerTokenValue" : { - "type" : "string", - "writeOnly" : true + "type" : { + "type" : "string" }, "url" : { "type" : "string", "description" : "A URL, but can also be a relative path.", "example" : "./a/items.yaml" - }, - "format" : { - "type" : "string", - "description" : "The input format.", - "enum" : [ "nivio", "csv", "k8s", "rancher", "docker-compose-v2" ] - }, - "assignTemplates" : { - "type" : "object", - "additionalProperties" : { - "type" : "array", - "description" : "A map with template identifier as key and item identifier matchers as value", - "example" : "endOfLife: [web, \"java6*\"]", - "items" : { - "type" : "string", - "description" : "A map with template identifier as key and item identifier matchers as value", - "example" : "endOfLife: [web, \"java6*\"]" - } - }, - "description" : "A map with template identifier as key and item identifier matchers as value", - "example" : "endOfLife: [web, \"java6*\"]" } }, "description" : "This is a reference to a configuration file." diff --git a/pom.xml b/pom.xml index a8a098c59..6ee8b647e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,12 +5,12 @@ de.bonndan nivio - 0.4.0 + 0.4.1 org.springframework.boot spring-boot-starter-parent - 2.2.13.RELEASE + 2.5.2 jar @@ -19,13 +19,15 @@ 1.11 11 5.4.0 - 2.24.0 + 3.11.2 + 0.20.1 0.8.6 ${project.basedir}/src/main/app v12.18.2 v1.22.4 - 1.10.0 + 1.12.0 8.8.2 + 2.12.5 dedica-team_nivio dedica-team https://sonarcloud.io @@ -50,11 +52,17 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml + ${jackson.version} com.fasterxml.jackson.core jackson-databind - 2.11.2 + ${jackson.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} javax.xml.bind @@ -71,44 +79,56 @@ org.springframework.boot spring-boot-starter-test test - + + + org.junit + junit + + + org.mockito + mockito-core + - com.vaadin.external.google - android-json + org.mockito + mockito-all org.junit.jupiter junit-jupiter-api - 5.4.0 + ${junit-jupiter.version} test org.junit.jupiter junit-jupiter-engine - 5.4.0 + ${junit-jupiter.version} test - + + com.googlecode.json-simple + json-simple + 1.1.1 + org.mockito mockito-junit-jupiter - 2.25.0 + ${mockito.version} test com.tngtech.archunit archunit-junit5 - 0.19.0 + ${archunit.version} test com.tngtech.archunit archunit - 0.14.1 + ${archunit.version} test @@ -167,7 +187,7 @@ io.fabric8 kubernetes-client - 5.0.2 + 5.8.0 io.fabric8 @@ -228,27 +248,27 @@ com.opencsv opencsv - 5.4 + 5.5.2 org.springdoc springdoc-openapi-ui - 1.5.8 + 1.5.10 org.kohsuke github-api - 1.130 + 1.133 org.gitlab4j gitlab4j-api - 4.16.0 + 4.18.0 @@ -261,7 +281,7 @@ org.openapitools openapi-generator - 5.1.0 + 5.3.0 @@ -323,15 +343,15 @@ maven-surefire-plugin 2.22.2 - - + + + **/*Test.java + + --> @@ -400,9 +420,33 @@ + + io.github.git-commit-id + git-commit-id-maven-plugin + 5.0.0 + + + validate + + revision + + + + + yyyyMMdd-HHmmss + false + + + maven-resources-plugin 3.0.1 + + + ^ + + false + position-sphinx-build diff --git a/src/main/app/copy-icons.js b/src/main/app/copy-icons.js index 0165c67ce..7c9dab09a 100644 --- a/src/main/app/copy-icons.js +++ b/src/main/app/copy-icons.js @@ -1,7 +1,10 @@ #!/usr/bin/env node const fs = require('fs-extra'); -// Async with promises: fs.copy('node_modules/@mdi/svg/svg', '../resources/static/icons/svg') .then(() => console.log('Icons copied successfully!')) .catch((err) => console.error(err)); + +fs.copy('node_modules/@mdi/svg/meta.json', '../resources/static/icons/meta.json') + .then(() => console.log('Icon meta.json list copied successfully!')) + .catch((err) => console.error(err)); diff --git a/src/main/app/package.json b/src/main/app/package.json index 7d113ed5e..abee4f8f4 100644 --- a/src/main/app/package.json +++ b/src/main/app/package.json @@ -1,42 +1,42 @@ { "name": "nivio", - "version": "0.4.0", + "version": "0.4.1", "private": true, "homepage": "./", "dependencies": { - "@material-ui/core": "^4.11.4", + "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.57", "@mdi/svg": "^5.9.55", "@stomp/stompjs": "^5.4.4", "@types/dateformat": "^3.0.1", - "@types/jest": "^26.0.23", - "@types/node": "^14.17.3", - "@types/react": "^16.14.6", - "@types/react-dom": "^16.9.13", - "@types/react-html-parser": "^2.0.1", - "@types/react-router-dom": "^5.1.7", - "@types/react-svg-pan-zoom": "^3.3.1", - "@types/react-transition-group": "^4.4.1", - "axios": "^0.21.1", + "@types/jest": "^26.0.24", + "@types/node": "^14.17.18", + "@types/react": "^16.14.15", + "@types/react-dom": "^16.9.14", + "@types/react-html-parser": "^2.0.2", + "@types/react-router-dom": "^5.3.0", + "@types/react-svg-pan-zoom": "^3.3.2", + "@types/react-transition-group": "^4.4.3", + "axios": "^0.21.4", "classnames": "^2.3.0", "dateformat": "^3.0.3", "fs-extra": "^9.1.0", "html-react-parser": "^0.14.3", "react": "^16.14.0", "react-dom": "^16.14.0", - "react-router-dom": "^5.2.0", + "react-router-dom": "^5.3.0", "react-scripts": "^4.0.3", "react-svg-pan-zoom-loader": "^1.4.1", "react-transition-group": "^4.4.2", "svg-path-properties": "^1.0.10", - "typescript": "~3.9.9" + "typescript": "~3.9.10" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.1", "@testing-library/react": "^10.4.7", "@testing-library/user-event": "^12.0.11", - "prettier": "^2.0.5" + "prettier": "^2.4.1" }, "scripts": { "dev": "react-scripts start", diff --git a/src/main/app/src/App.tsx b/src/main/app/src/App.tsx index 07f85bb2a..ecdf07773 100644 --- a/src/main/app/src/App.tsx +++ b/src/main/app/src/App.tsx @@ -7,9 +7,10 @@ import Man from './Components/Manual/Man'; import Layout from './Components/Layout/Layout'; import { Routes } from './interfaces'; import { Box, CssBaseline, Theme } from '@material-ui/core'; -import { createMuiTheme, ThemeOptions, ThemeProvider } from '@material-ui/core/styles'; +import { createTheme, ThemeOptions, ThemeProvider } from '@material-ui/core/styles'; import { get } from './utils/API/APIClient'; import defaultThemeVariables from './Resources/styling/theme'; +import { FrontendMappingProvider } from './Context/FrontendMappingContext'; interface Config { baseUrl: string; @@ -30,6 +31,7 @@ const App: React.FC = () => { const [pageTitle, setPageTitle] = useState(''); const [logo, setLogo] = useState(''); const [message, setMessage] = useState(''); + const [version, setVersion] = useState(); const [theme, setTheme] = useState(); useEffect(() => { @@ -41,7 +43,7 @@ const App: React.FC = () => { color = '#' + color; } } else { - console.log('falling back to default color', defaultColor); + console.debug('falling back to default color', defaultColor); } return color; }; @@ -53,6 +55,7 @@ const App: React.FC = () => { const front = getColorSafely(index.config.brandingForeground, '#22F2C2'); const secondary = getColorSafely(index.config.brandingSecondary, '#eeeeee'); setMessage(index.config.brandingMessage); + setVersion(index.config.version); const tv: ThemeOptions = defaultThemeVariables; if (!tv.palette) return; @@ -77,7 +80,7 @@ const App: React.FC = () => { if (index.config.brandingLogoUrl && index.config.brandingLogoUrl.length) { setLogo(index.config.brandingLogoUrl); } - setTheme(createMuiTheme(tv)); + setTheme(createTheme(tv)); }); }, [setTheme, setLogo]); @@ -86,50 +89,57 @@ const App: React.FC = () => { } return ( - - - - - - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - - - - + + + + + + + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + + + + + ); }; diff --git a/src/main/app/src/Components/Events/Events.tsx b/src/main/app/src/Components/Events/Events.tsx index b3d9b2273..4fa6f94e8 100644 --- a/src/main/app/src/Components/Events/Events.tsx +++ b/src/main/app/src/Components/Events/Events.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { get } from '../../utils/API/APIClient'; import { Card, CardHeader } from '@material-ui/core'; import CardContent from '@material-ui/core/CardContent'; diff --git a/src/main/app/src/Components/Help/HelpTooltip.test.tsx b/src/main/app/src/Components/Help/HelpTooltip.test.tsx index 00a861c8e..f5225e83c 100644 --- a/src/main/app/src/Components/Help/HelpTooltip.test.tsx +++ b/src/main/app/src/Components/Help/HelpTooltip.test.tsx @@ -5,11 +5,9 @@ import HelpTooltip from './HelpTooltip'; import { fireEvent, render, waitFor } from '@testing-library/react'; it('should render HelpTooltip with given content', () => { - const baseDom = render( - foo} /> - ); + const baseDom = render(foo} />); const icon = baseDom.getByLabelText('help'); fireEvent.mouseOver(icon); - waitFor(() => expect(baseDom.findByText("foo")).toBeInTheDocument()) + waitFor(() => expect(baseDom.findByText('foo')).toBeInTheDocument()); }); diff --git a/src/main/app/src/Components/Help/HelpTooltip.tsx b/src/main/app/src/Components/Help/HelpTooltip.tsx index bbcfbca8e..53e346195 100644 --- a/src/main/app/src/Components/Help/HelpTooltip.tsx +++ b/src/main/app/src/Components/Help/HelpTooltip.tsx @@ -11,7 +11,7 @@ const HtmlTooltip = withStyles((theme: Theme) => ({ tooltip: { backgroundColor: theme.palette.primary.main, fontSize: theme.typography.pxToRem(14), - boxShadow: '2px 2px 5px black' + boxShadow: '2px 2px 5px black', }, }))(Tooltip); @@ -23,7 +23,9 @@ const HtmlTooltip = withStyles((theme: Theme) => ({ * @constructor */ const HelpTooltip: React.FC = ({ content, style }) => { - return } style={style} aria-label={'help'}/>; + return ( + } style={style} aria-label={'help'} /> + ); }; -export default HelpTooltip; \ No newline at end of file +export default HelpTooltip; diff --git a/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.test.tsx b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.test.tsx new file mode 100644 index 000000000..f642b1b33 --- /dev/null +++ b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.test.tsx @@ -0,0 +1,44 @@ +import { render } from '@testing-library/react'; +import React from 'react'; +import KPIConfigLayout from './KPIConfigLayout'; +import { IKpi } from '../../../interfaces'; + +describe('', () => { + const kpi: IKpi = { + description: + "Turns yellow if the 'scale' label is zero. Turns orange or red if is also is a data sink or provider.", + enabled: true, + ranges: { + GREEN: { + maximum: 'Infinity', + minimum: '1.0', + }, + YELLOW: { + description: 'scaled to zero', + maximum: '0.0', + minimum: '0.0', + }, + ORANGE: { + description: 'data sink scaled to zero', + maximum: '0.0', + minimum: '0.0', + }, + RED: { + description: 'provider scaled to zero', + maximum: '0.0', + minimum: '0.0', + }, + }, + matches: { + GREEN: ['All conditions are met.'], + RED: ['One condition is not met.'], + }, + }; + + it('should display', () => { + const { getByText, queryByText } = render(); + expect(getByText('fooKPI')).toBeInTheDocument(); + expect(getByText('All conditions are met.')).toBeInTheDocument(); + expect(getByText('[1.0 → Infinity]')).toBeInTheDocument(); + }); +}); diff --git a/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx new file mode 100644 index 000000000..4c7e123bb --- /dev/null +++ b/src/main/app/src/Components/Landscape/Dashboard/KPIConfigLayout.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { IKpi } from '../../../interfaces'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + Table, + TableBody, + TableCell, + TableRow, +} from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import StatusChip from '../../StatusChip/StatusChip'; +import { ExpandMore } from '@material-ui/icons'; + +interface Props { + name: string; + kpi: IKpi; +} + +/** + * Displays the configuration of a single KPI. + * + * @param name kpi name + * @param kpi + * @constructor + */ +const KPIConfigLayout: React.FC = ({ name, kpi }) => { + let ranges: JSX.Element[] = []; + if (kpi.ranges) { + for (let key of Object.keys(kpi.ranges)) { + const range = kpi.ranges[key]; + const rangeText = + range.minimum === range.maximum ? range.minimum : `${range.minimum} → ${range.maximum}`; + ranges.push( + + + + + + + {`[${rangeText}]`} {range.description ?? ''} + + + + ); + } + } + let matches: JSX.Element[] = []; + if (kpi.matches) { + for (let key of Object.keys(kpi.matches)) { + const matchers = kpi.matches[key]; + matches.push( + + + + + + {matchers.join(', ')} + + + ); + } + } + + return ( + + + } + aria-controls={'panel_kpi' + name + 'bh-content'} + id={'panel_kpi' + name + 'bh-header'} + > + {name} + + +
{kpi.description}
+
+ + {ranges.length ? ( + + {ranges} +
+ ) : null} + {matches.length ? ( + + {matches} +
+ ) : null} +
+
+
+ ); +}; +export default KPIConfigLayout; diff --git a/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx b/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx index 2cb2d1893..15aa1b444 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/LandscapeWatcher.tsx @@ -51,7 +51,7 @@ const LandscapeWatcher: React.FC = ({ setSidebarContent, ...props }) => { return ( ', () => { - it('should display', () => { const { getByText } = render( {}} onGroupClick={() => {}} /> ); - expect(getByText('Warnings')).toBeInTheDocument(); + expect(getByText('Status')).toBeInTheDocument(); }); it('should display an assessment', () => { diff --git a/src/main/app/src/Components/Landscape/Dashboard/StatusBar.tsx b/src/main/app/src/Components/Landscape/Dashboard/StatusBar.tsx index fc0f4db01..b19df02d2 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/StatusBar.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/StatusBar.tsx @@ -1,7 +1,7 @@ -import React, { useState, useEffect, useContext } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import StatusBarLayout from './StatusBarLayout'; -import { ILandscape, IAssessment, IItem, IGroup } from '../../../interfaces'; +import { IAssessment, IGroup, IItem, ILandscape } from '../../../interfaces'; import Group from '../Modals/Group/Group'; import Item from '../Modals/Item/Item'; import { LocateFunctionContext } from '../../../Context/LocateFunctionContext'; diff --git a/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx b/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx index 0b6b89162..509e6bd37 100644 --- a/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx +++ b/src/main/app/src/Components/Landscape/Dashboard/StatusBarLayout.tsx @@ -2,13 +2,26 @@ import React, { useContext, useState } from 'react'; import { IGroup } from '../../../interfaces'; import StatusChip from '../../StatusChip/StatusChip'; import Button from '@material-ui/core/Button'; -import { Card, CardHeader, Table, TableBody, TableCell, TableRow } from '@material-ui/core'; +import { + AppBar, + Card, + CardHeader, + Tab, + Table, + TableBody, + TableCell, + TableRow, + Tabs, +} from '@material-ui/core'; import { LandscapeContext } from '../../../Context/LandscapeContext'; import componentStyles from '../../../Resources/styling/ComponentStyles'; import IconButton from '@material-ui/core/IconButton'; -import { Close } from '@material-ui/icons'; +import { Close, Settings, Warning } from '@material-ui/icons'; import ItemAvatar from '../Modals/Item/ItemAvatar'; import GroupAvatar from '../Modals/Group/GroupAvatar'; +import { a11yProps, TabPanel } from '../Utils/TabUtils'; +import CardContent from '@material-ui/core/CardContent'; +import KPIConfigLayout from './KPIConfigLayout'; interface Props { onItemClick: Function; @@ -22,6 +35,7 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { const context = useContext(LandscapeContext); const componentClasses = componentStyles(); const [visible, setVisible] = useState(true); + const [currentTab, setCurrentTab] = React.useState(0); const getItems = (group: IGroup) => { return group.items.map((item) => { @@ -34,7 +48,6 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { assessmentSummary.status === 'UNDEFINED' ) return null; - if (!assessmentSummary.maxField) return null; return ( @@ -50,7 +63,7 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { {item.name || item.identifier} - + {assessmentSummary.message} @@ -95,7 +108,10 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { {group.name} - + {groupAssessment.message} @@ -103,11 +119,27 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { }); }; + const changeTab = (event: React.ChangeEvent<{}>, newValue: number) => { + setCurrentTab(newValue); + }; + if (!visible) return null; + + const kpiConfig = context.landscape?.kpis; + let kpis: JSX.Element[] = []; + if (kpiConfig) { + for (let key of Object.keys(kpiConfig)) { + const kpiConfigElement = kpiConfig[key]; + if (kpiConfigElement.enabled) { + kpis.push(); + } + } + } + return ( { @@ -118,12 +150,42 @@ const StatusBarLayout: React.FC = ({ onItemClick, onGroupClick }) => { } /> - - - {context.landscape ? getGroups(context.landscape.groups) : null} - {context.landscape?.groups.map((group) => getItems(group))} - -
+ + + } + label={'warnings'} + style={{ minWidth: 50 }} + title={'Warnings'} + {...a11yProps(0, 'statusbar')} + /> + } + label={'kpis'} + style={{ minWidth: 50 }} + title={'KPIs'} + {...a11yProps(1, 'statusbar')} + /> + + + + + + + {context.landscape ? getGroups(context.landscape.groups) : null} + {context.landscape?.groups.map((group) => getItems(group))} + +
+
+ + {kpis} + +
); }; diff --git a/src/main/app/src/Components/Landscape/Map/Map.css b/src/main/app/src/Components/Landscape/Map/Map.css index d87e1f3e6..22fcea247 100644 --- a/src/main/app/src/Components/Landscape/Map/Map.css +++ b/src/main/app/src/Components/Landscape/Map/Map.css @@ -1,144 +1,221 @@ - .landscapeMapContainer .map .title { - fill: rgba(255, 255, 255, 0.75); + fill: rgba(255, 255, 255, 0.75); +} + +@media screen { + .title { + display: none; + } + + .logo { + display: none; + } } + .landscapeMapContainer .map .details { - border: 1px solid #3f51b5; - border-radius: 10px; - background-color: white; + border: 1px solid #3f51b5; + border-radius: 10px; + background-color: white; +} + +.landscapeMapContainer .map .item:hover { + cursor: pointer; +} + +.map g.relation { + cursor: pointer; } -.landscapeMapContainer .map .item { - cursor: pointer; + +.map g.groupArea { + cursor: pointer; +} + +.map g.label { + cursor: pointer; +} + +.map g.item.unselected:hover circle { + stroke: #c0c0c0; +} + +.map g.item.unselected:hover polygon { + stroke: #c0c0c0; +} + +/* hexagon */ +.map g.groupArea.unselected polygon { + fill-opacity: 0.05; +} + +.map g.item.unselected circle { + stroke: grey; +} + +.map g.relation.unselected path { + stroke: grey; +} + +.map g.relation.unselected circle { + fill: grey; +} + +.map g.relation.unselected polygon { + fill: grey; } .landscapeMapContainer .map g .group { - fill-opacity: 0.4; - stroke: #3f51b5; + fill-opacity: 0.4; + stroke: #3f51b5; } .landscapeMapContainer .map g .label text { - fill: rgba(255, 255, 255, 0.75); - cursor: pointer; + fill: rgba(255, 255, 255, 0.75); + cursor: pointer; } + .landscapeMapContainer .map g .label rect { - fill-opacity: 1; - stroke-width: 0.1em; + fill-opacity: 1; + stroke-width: 0.1em; } + .landscapeMapContainer .map g .item_shortName { - fill: #000; + fill: #000; } + .landscapeMapContainer .map path { - stroke-opacity: 0.8; - stroke-linecap: round; - stroke-linejoin: round; + stroke-opacity: 0.8; + stroke-linecap: round; + stroke-linejoin: round; } + .landscapeMapContainer .ReactSVGPanZoom svg g rect { - fill: transparent; + fill: transparent; } + @-o-keyframes highlightLabel { - 0% { - stroke-width: 5px; - } - 50% { - stroke-width: 40px; - stroke: white; - } - to { - stroke-width: 5px; - } + 0% { + stroke-width: 5px; + } + 50% { + stroke-width: 40px; + stroke: white; + } + to { + stroke-width: 5px; + } } + @-webkit-keyframes highlightLabel { - 0% { - stroke-width: 5px; - } - 50% { - stroke-width: 40px; - stroke: white; - } - to { - stroke-width: 5px; - } + 0% { + stroke-width: 5px; + } + 50% { + stroke-width: 40px; + stroke: white; + } + to { + stroke-width: 5px; + } } + @keyframes highlightLabel { - 0% { - stroke-width: 5px; - } - 50% { - stroke-width: 40px; - stroke: white; - } - to { - stroke-width: 5px; - } + 0% { + stroke-width: 5px; + } + 50% { + stroke-width: 40px; + stroke: white; + } + to { + stroke-width: 5px; + } } + @-o-keyframes highlightRelation { - 0% { - stroke-width: 5px; - stroke: #000; - } - 50% { - stroke-width: 40px; - stroke: white; - } - to { - stroke: #000; - stroke-width: 5px; - } + 0% { + stroke-width: 5px; + stroke: #000; + } + 50% { + stroke-width: 13; + stroke: white; + } + to { + stroke: #000; + stroke-width: 5px; + } } + @-webkit-keyframes highlightRelation { - 0% { - stroke-width: 5px; - stroke: #000; - } - 50% { - stroke-width: 40px; - stroke: white; - } - to { - stroke: #000; - stroke-width: 5px; - } + 0% { + stroke-width: 5px; + stroke: #000; + } + 50% { + stroke-width: 13; + stroke: white; + } + to { + stroke: #000; + stroke-width: 5px; + } } + @keyframes highlightRelation { - 0% { - stroke-width: 5px; - stroke: #000; - } - 50% { - stroke-width: 40px; - stroke: white; - } - to { - stroke: #000; - stroke-width: 5px; - } + 0% { + stroke-width: 5px; + stroke: #000; + } + 50% { + stroke-width: 13; + stroke: white; + } + to { + stroke: #000; + stroke-width: 5px; + } } + .landscapeMapContainer .highlightLabel { - /* box-shadow: 0 0 0 2px #FF4081; - */ - -webkit-animation: highlightLabel 1s linear; - -o-animation: highlightLabel 1s linear; - animation: highlightLabel 1s linear; - -webkit-animation-iteration-count: 2; - -o-animation-iteration-count: 2; - animation-iteration-count: 2; + /* box-shadow: 0 0 0 2px #FF4081; + */ + -webkit-animation: highlightLabel 1s linear; + -o-animation: highlightLabel 1s linear; + animation: highlightLabel 1s linear; + -webkit-animation-iteration-count: 2; + -o-animation-iteration-count: 2; + animation-iteration-count: 2; } + .landscapeMapContainer .highlightRelation { - /* box-shadow: 0 0 0 2px #FF4081; - */ - -webkit-animation: highlightRelation 1s linear; - -o-animation: highlightRelation 1s linear; - animation: highlightRelation 1s linear; - -webkit-animation-iteration-count: 2; - -o-animation-iteration-count: 2; - animation-iteration-count: 2; + /* box-shadow: 0 0 0 2px #FF4081; + */ + -webkit-animation: highlightRelation 1s linear; + -o-animation: highlightRelation 1s linear; + animation: highlightRelation 1s linear; + -webkit-animation-iteration-count: 1.5; + -o-animation-iteration-count: 1.5; + animation-iteration-count: 1.5; } + .landscapeMapContainer .with-transition { - z-index: 2; + z-index: 2; } + .landscapeMapContainer .with-transition svg > g { - transition: transform 1s ease-out; + transition: transform 1s ease-out; } + .landscapeMapContainer .showHighlight { - z-index: 2; + z-index: 2; +} + +.landscapeMapContainer .map g.groupArea.unselected:hover polygon { + fill-opacity: 0.2; +} + +.map g.relation.unselected path:hover { + stroke: #c0c0c0; + stroke-width: 13; + stroke-opacity: 1; } diff --git a/src/main/app/src/Components/Landscape/Map/Map.tsx b/src/main/app/src/Components/Landscape/Map/Map.tsx index b07f09c3e..8d1d77a06 100644 --- a/src/main/app/src/Components/Landscape/Map/Map.tsx +++ b/src/main/app/src/Components/Landscape/Map/Map.tsx @@ -194,7 +194,6 @@ const Map: React.FC = ({ setSidebarContent, setPageTitle }) => { }; const loadMap = useCallback(() => { - console.debug('loading map'); const route = withBasePath(`/render/${identifier}/map.svg`); get(route).then((svg) => { const parser = new DOMParser(); @@ -247,13 +246,9 @@ const Map: React.FC = ({ setSidebarContent, setPageTitle }) => { * Reload map on notification messages. */ useEffect(() => { - if ( - landscapeContext.notification?.type === 'ProcessingFinishedEvent' && - landscapeContext.notification?.landscape === landscapeContext.identifier - ) { - loadMap(); - } - }, [landscapeContext.notification, landscapeContext.identifier, loadMap]); + console.debug('reloading map', landscapeContext.assessment); + loadMap(); + }, [landscapeContext.assessment, landscapeContext.identifier, loadMap]); useEffect(() => { let timeout: NodeJS.Timeout; diff --git a/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx b/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx index 85949a78f..1405290d1 100644 --- a/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx +++ b/src/main/app/src/Components/Landscape/Map/MapRelation/MapRelation.tsx @@ -1,14 +1,15 @@ -import React, { useContext, useState } from 'react'; -import { Card, CardHeader, Table, TableBody, TableCell, TableRow } from '@material-ui/core'; +import React, {useContext, useState} from 'react'; +import {Card, CardHeader, Table, TableBody, TableCell, TableRow} from '@material-ui/core'; import CardContent from '@material-ui/core/CardContent'; -import { IItem, IRelation } from '../../../../interfaces'; +import {IItem, IRelation} from '../../../../interfaces'; import Typography from '@material-ui/core/Typography'; import IconButton from '@material-ui/core/IconButton'; -import { LocateFunctionContext } from '../../../../Context/LocateFunctionContext'; +import {LocateFunctionContext} from '../../../../Context/LocateFunctionContext'; import componentStyles from '../../../../Resources/styling/ComponentStyles'; import ItemAvatar from '../../Modals/Item/ItemAvatar'; -import { Close, HelpRounded } from '@material-ui/icons'; -import { LandscapeContext } from '../../../../Context/LandscapeContext'; +import {Close, HelpRounded} from '@material-ui/icons'; +import {LandscapeContext} from '../../../../Context/LandscapeContext'; +import {getLabels} from '../../Utils/utils'; interface Props { source: IItem; @@ -32,6 +33,8 @@ const MapRelation: React.FC = ({ source, target, relation }) => { const sourceTitle = source.name || source.identifier; const targetTitle = target.name || target.identifier; const title = sourceTitle + ' to ' + targetTitle; + const labels = relation ? getLabels(relation) : null; + const sourceStatus = landscapeContext.getAssessmentSummary(source.fullyQualifiedIdentifier); const targetStatus = landscapeContext.getAssessmentSummary(target.fullyQualifiedIdentifier); @@ -81,6 +84,13 @@ const MapRelation: React.FC = ({ source, target, relation }) => {
+ {labels ? ( + <> + Labels + {labels} + + ) : null} +
Source
{ // @ts-ignore diff --git a/src/main/app/src/Components/Landscape/Modals/Group/Group.test.tsx b/src/main/app/src/Components/Landscape/Modals/Group/Group.test.tsx index 3c968be06..046485497 100644 --- a/src/main/app/src/Components/Landscape/Modals/Group/Group.test.tsx +++ b/src/main/app/src/Components/Landscape/Modals/Group/Group.test.tsx @@ -4,10 +4,7 @@ import Group from './Group'; it('should render landscape group component', () => { const group = { identifier: 'foo', name: 'foo', fullyQualifiedIdentifier: 'bar/foo', items: [] }; - const assessments = { - results: {}, - date: '', - }; - const { getByText } = render(); + + const { getByText } = render(); expect(getByText('foo')).toBeInTheDocument(); }); diff --git a/src/main/app/src/Components/Landscape/Modals/Group/Group.tsx b/src/main/app/src/Components/Landscape/Modals/Group/Group.tsx index e6372a601..b11f96044 100644 --- a/src/main/app/src/Components/Landscape/Modals/Group/Group.tsx +++ b/src/main/app/src/Components/Landscape/Modals/Group/Group.tsx @@ -115,7 +115,7 @@ const Group: React.FC = ({ group }) => {

Status - + {assessment.message}

diff --git a/src/main/app/src/Components/Landscape/Modals/Group/GroupAvatar.tsx b/src/main/app/src/Components/Landscape/Modals/Group/GroupAvatar.tsx index 16a62c4b7..fa82f8c43 100644 --- a/src/main/app/src/Components/Landscape/Modals/Group/GroupAvatar.tsx +++ b/src/main/app/src/Components/Landscape/Modals/Group/GroupAvatar.tsx @@ -17,7 +17,7 @@ const GroupAvatar: React.FC = ({ group, statusColor }) => { return ( = ({ group, statusColor }) => { ); }; - -export default GroupAvatar; \ No newline at end of file +export default GroupAvatar; diff --git a/src/main/app/src/Components/Landscape/Modals/Item/Item.test.tsx b/src/main/app/src/Components/Landscape/Modals/Item/Item.test.tsx index e6067cbc8..7dd803616 100644 --- a/src/main/app/src/Components/Landscape/Modals/Item/Item.test.tsx +++ b/src/main/app/src/Components/Landscape/Modals/Item/Item.test.tsx @@ -1,41 +1,60 @@ import React from 'react'; -import { render } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; +import * as APIClient from '../../../../utils/API/APIClient'; import Item from './Item'; +import { IItem } from '../../../../interfaces'; +describe('', () => { + const IRelations = { + source: 'foo', + target: 'foo', + description: 'foo', + format: 'foo', + name: 'foo', + id: 'foo', + direction: 'foo', + labels: {}, + }; + const Irelations = { foo: IRelations }; + const useItem: IItem = { + identifier: 'foo', + group: 'foo', + name: 'foo', + owner: 'foo', + description: 'foo', + contact: 'foo', + relations: Irelations, + interfaces: [], + labels: { foo: 'foo' }, + type: 'foo', + fullyQualifiedIdentifier: 'foo', + tags: [], + color: 'foo', + icon: 'foo', + _links: { homepage: { href: 'http://acme.com' } }, + }; -it('should avoid displaying undefined and null value', () => { - const IRelations = { - source: "foo", - target: "foo", - description: "foo", - format: "foo", - name: "foo", - id: "foo", - direction: "foo", - } - const Irelations = { "foo": IRelations } - const useItem = { - identifier: "foo", - group: "foo", - name: "foo", - owner: "foo", - description: "foo", - contact: "foo", - relations: Irelations, - interfaces: [], - labels: { "foo": "foo" }, - type: "foo", - fullyQualifiedIdentifier: "foo", - tags: [], - color: "foo", - icon: "foo", + it('should avoid displaying undefined and null value', () => { + const mock = jest.spyOn(APIClient, 'get'); + mock.mockReturnValue(Promise.resolve(useItem)); - } - const { queryByText } = render(); + const { queryByText } = render(); expect(queryByText('foo (undefined foo), format: foo')).toBeNull(); expect(queryByText('undefined')).toBeNull(); expect(queryByText('null')).toBeNull(); + }); + it('should display links', async () => { + //given + const mock = jest.spyOn(APIClient, 'get'); + mock.mockReturnValue(Promise.resolve(useItem)); -}); \ No newline at end of file + //when + const { container, getByText } = render(); + + //then + await waitFor(() => expect(mock).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(getByText('homepage')).toBeInTheDocument()); + }); +}); diff --git a/src/main/app/src/Components/Landscape/Modals/Item/Item.tsx b/src/main/app/src/Components/Landscape/Modals/Item/Item.tsx index 51f7c46dc..7ef77bc2a 100644 --- a/src/main/app/src/Components/Landscape/Modals/Item/Item.tsx +++ b/src/main/app/src/Components/Landscape/Modals/Item/Item.tsx @@ -23,7 +23,7 @@ import { import { get } from '../../../../utils/API/APIClient'; import CardContent from '@material-ui/core/CardContent'; import { IAssessmentProps, IItem } from '../../../../interfaces'; -import { getItem, getLabels, getLabelsWithPrefix } from '../../Utils/utils'; +import { getItem, getLabelsWithPrefix, getMappedLabels } from '../../Utils/utils'; import StatusChip from '../../../StatusChip/StatusChip'; import IconButton from '@material-ui/core/IconButton'; import { Close, Details, ExpandMore, Info, MoreVertSharp, Power } from '@material-ui/icons'; @@ -141,12 +141,9 @@ const Item: React.FC = ({ fullyQualifiedItemIdentifier, small }) => { }; useEffect(() => { - const reset = (item: IItem) => { - setItem(item); - }; if (!item && fullyQualifiedItemIdentifier) { get(`/api/${fullyQualifiedItemIdentifier}`).then((loaded) => { - reset(loaded); + setItem(loaded); }); } }, [item, fullyQualifiedItemIdentifier]); @@ -231,7 +228,7 @@ const Item: React.FC = ({ fullyQualifiedItemIdentifier, small }) => { setValue(newValue); }; - const labels = item ? getLabels(item) : null; + const labels = item ? getMappedLabels(item) : null; const extend = ( <> {small ? ( @@ -381,7 +378,7 @@ const Item: React.FC = ({ fullyQualifiedItemIdentifier, small }) => { {assessmentStatus.length > 0 ? ( <>
- Assessment + Status {assessmentStatus}
diff --git a/src/main/app/src/Components/Landscape/Modals/Item/ItemAvatar.tsx b/src/main/app/src/Components/Landscape/Modals/Item/ItemAvatar.tsx index 059cb3d70..2cf86260a 100644 --- a/src/main/app/src/Components/Landscape/Modals/Item/ItemAvatar.tsx +++ b/src/main/app/src/Components/Landscape/Modals/Item/ItemAvatar.tsx @@ -2,7 +2,7 @@ import { IItem } from '../../../../interfaces'; import React from 'react'; import { getItemIcon } from '../../Utils/utils'; import Avatar from '@material-ui/core/Avatar'; -import StatusBadge from "../../Utils/StatusBadge"; +import StatusBadge from '../../Utils/StatusBadge'; interface Props { item: IItem; @@ -15,7 +15,7 @@ interface Props { const ItemAvatar: React.FC = ({ item, statusColor }) => { return ( = ({ item, statusColor }) => { ); }; - -export default ItemAvatar; \ No newline at end of file +export default ItemAvatar; diff --git a/src/main/app/src/Components/Landscape/Modals/Log/Log.tsx b/src/main/app/src/Components/Landscape/Modals/Log/Log.tsx index 6f5a04f9d..d75b5d924 100644 --- a/src/main/app/src/Components/Landscape/Modals/Log/Log.tsx +++ b/src/main/app/src/Components/Landscape/Modals/Log/Log.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { ILandscape } from '../../../../interfaces'; import { get } from '../../../../utils/API/APIClient'; diff --git a/src/main/app/src/Components/Landscape/Overview/Overview.test.tsx b/src/main/app/src/Components/Landscape/Overview/Overview.test.tsx index 65f0afe33..fb8f99ccf 100644 --- a/src/main/app/src/Components/Landscape/Overview/Overview.test.tsx +++ b/src/main/app/src/Components/Landscape/Overview/Overview.test.tsx @@ -6,10 +6,8 @@ import { MemoryRouter } from 'react-router-dom'; it('should render LandscapeOverview component', () => { const { getByText } = render( - { }} setSidebarContent={() => { }} welcomeMessage={'foo'}/> + {}} setSidebarContent={() => {}} welcomeMessage={'foo'} /> ); expect(getByText('Loading landscapes ...')).toBeInTheDocument(); }); - - diff --git a/src/main/app/src/Components/Landscape/Overview/Overview.tsx b/src/main/app/src/Components/Landscape/Overview/Overview.tsx index 35fcd4734..1e4e5d729 100644 --- a/src/main/app/src/Components/Landscape/Overview/Overview.tsx +++ b/src/main/app/src/Components/Landscape/Overview/Overview.tsx @@ -1,13 +1,13 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, {useCallback, useEffect, useState} from 'react'; -import { ILandscape, ILandscapeLinks } from '../../../interfaces'; +import {ILandscape, ILandscapeLinks} from '../../../interfaces'; import OverviewLayout from './OverviewLayout'; -import { get } from '../../../utils/API/APIClient'; +import {get} from '../../../utils/API/APIClient'; import Events from '../../Events/Events'; -import { createStyles, darken, Theme } from '@material-ui/core'; -import { Redirect } from 'react-router-dom'; +import {createStyles, darken, Theme} from '@material-ui/core'; +import {Redirect} from 'react-router-dom'; import makeStyles from '@material-ui/core/styles/makeStyles'; -import { withBasePath } from '../../../utils/API/BasePath'; +import {withBasePath} from '../../../utils/API/BasePath'; import Avatar from '@material-ui/core/Avatar'; /** diff --git a/src/main/app/src/Components/Landscape/Overview/OverviewLayout.test.tsx b/src/main/app/src/Components/Landscape/Overview/OverviewLayout.test.tsx index 9bb21a488..493750c8c 100644 --- a/src/main/app/src/Components/Landscape/Overview/OverviewLayout.test.tsx +++ b/src/main/app/src/Components/Landscape/Overview/OverviewLayout.test.tsx @@ -2,52 +2,48 @@ import React from 'react'; import { render } from '@testing-library/react'; import OverviewLayout from './OverviewLayout'; import { MemoryRouter } from 'react-router-dom'; -import { ILandscape, IItem, IGroup } from '../../../interfaces'; +import { IGroup, IItem, ILandscape } from '../../../interfaces'; + const items: IItem[] = [ - { - contact: 'marvin', - group: 'test', - owner: 'daniel', - fullyQualifiedIdentifier: 'fullTestIdentifier', - identifier: 'testIdentifier', - name: 'testIdentifier', - description: 'testDescription', - relations: {}, - labels: {}, - tags: [], - type: 'service', - icon: '', - }, + { + contact: 'marvin', + group: 'test', + owner: 'daniel', + fullyQualifiedIdentifier: 'fullTestIdentifier', + identifier: 'testIdentifier', + name: 'testIdentifier', + description: 'testDescription', + relations: {}, + labels: {}, + tags: [], + type: 'service', + icon: '', + }, ]; const groups: IGroup[] = [ - { - fullyQualifiedIdentifier: 'groupIdentifier', - name: 'groupName', - items: items, - identifier: 'groupIdentifier', - }, + { + fullyQualifiedIdentifier: 'groupIdentifier', + name: 'groupName', + items: items, + identifier: 'groupIdentifier', + }, ]; const landscapes: ILandscape = { - name: 'landscapeTestName', - identifier: 'testIdentifier', - description: 'testIdentifier', - groups: groups, - contact: 'marvin', - owner: 'daniel', - fullyQualifiedIdentifier: 'fullTestIdentifier', + name: 'landscapeTestName', + identifier: 'testIdentifier', + description: 'testIdentifier', + groups: groups, + contact: 'marvin', + owner: 'daniel', + fullyQualifiedIdentifier: 'fullTestIdentifier', }; it('should render LandscapeOverview component', () => { - - - const { getByText } = render( - - { }} /> - - ); - expect(getByText('landscapeTestName')).toBeInTheDocument(); + const { getByText } = render( + + {}} /> + + ); + expect(getByText('landscapeTestName')).toBeInTheDocument(); }); - - - diff --git a/src/main/app/src/Components/Landscape/Overview/OverviewLayout.tsx b/src/main/app/src/Components/Landscape/Overview/OverviewLayout.tsx index 452a82c2d..acdfa5b06 100644 --- a/src/main/app/src/Components/Landscape/Overview/OverviewLayout.tsx +++ b/src/main/app/src/Components/Landscape/Overview/OverviewLayout.tsx @@ -18,7 +18,7 @@ const useStyles = makeStyles((theme: Theme) => overview: { marginLeft: 10, width: 'calc(100% - 300px)', - paddingTop: 0 + paddingTop: 0, }, card: { marginBottom: 5, @@ -54,7 +54,6 @@ const OverviewLayout: React.FC = ({ landscapes, setSidebarContent }) => { let content: ReactElement[] = [Loading landscapes...]; if (Array.isArray(landscapes) && landscapes.length) { - content = landscapes.map((landscape) => { let itemCount = 0; landscape.groups?.forEach((group) => (itemCount += group.items.length)); @@ -123,7 +122,6 @@ const OverviewLayout: React.FC = ({ landscapes, setSidebarContent }) => { ); }); - } return ( diff --git a/src/main/app/src/Components/Landscape/Search/Facets.test.tsx b/src/main/app/src/Components/Landscape/Search/Facets.test.tsx index 4ed19685a..dde1e8fc0 100644 --- a/src/main/app/src/Components/Landscape/Search/Facets.test.tsx +++ b/src/main/app/src/Components/Landscape/Search/Facets.test.tsx @@ -51,7 +51,7 @@ describe('', () => { const { container, queryByText, getByText } = render( ); - fireEvent.click(getByTitle(container, "KPIs")); + fireEvent.click(getByTitle(container, 'KPIs')); expect(queryByText('owner')).toBeNull(); expect(getByText('security')).toBeInTheDocument(); diff --git a/src/main/app/src/Components/Landscape/Search/Facets.tsx b/src/main/app/src/Components/Landscape/Search/Facets.tsx index 9d5be6f56..c55c0d830 100644 --- a/src/main/app/src/Components/Landscape/Search/Facets.tsx +++ b/src/main/app/src/Components/Landscape/Search/Facets.tsx @@ -46,7 +46,8 @@ const Facets: React.FC = ({ facets, addFacet, saveSearch }) => { addFacet(facet.dim, lv.label); }} variant={'default'} - color={'primary'} style={{margin: 1}} + color={'primary'} + style={{ margin: 1 }} size={'small'} key={facet.dim + '' + lv.label} label={lv.label} @@ -94,9 +95,9 @@ const Facets: React.FC = ({ facets, addFacet, saveSearch }) => { const exportCurrent = () => { const elementById = document.getElementById('report-title'); // @ts-ignore - const title = elementById != null ? elementById.value :''; - saveSearch({reportType: 'owners', title: title}) - } + const title = elementById != null ? elementById.value : ''; + saveSearch({ reportType: 'owners', title: title }); + }; return ( <> @@ -142,11 +143,18 @@ const Facets: React.FC = ({ facets, addFacet, saveSearch }) => { -
-
- + +
+
+
- ); }; diff --git a/src/main/app/src/Components/Landscape/Search/Help.tsx b/src/main/app/src/Components/Landscape/Search/Help.tsx index a0d407252..2ce6b1257 100644 --- a/src/main/app/src/Components/Landscape/Search/Help.tsx +++ b/src/main/app/src/Components/Landscape/Search/Help.tsx @@ -24,4 +24,4 @@ const SearchHelp: React.FC = () => { ); }; -export default SearchHelp; \ No newline at end of file +export default SearchHelp; diff --git a/src/main/app/src/Components/Landscape/Search/Search.test.tsx b/src/main/app/src/Components/Landscape/Search/Search.test.tsx index 3ead23e0c..9feb0addc 100644 --- a/src/main/app/src/Components/Landscape/Search/Search.test.tsx +++ b/src/main/app/src/Components/Landscape/Search/Search.test.tsx @@ -7,9 +7,9 @@ import landscapeContextValue from '../../../utils/testing/LandscapeContextValue' describe('', () => { it('should render', () => { const { getByText } = render( - - {}} setSidebarContent={() => {}} /> - + + {}} setSidebarContent={() => {}} /> + ); expect(getByText('Search')).toBeInTheDocument(); }); diff --git a/src/main/app/src/Components/Landscape/Search/Search.tsx b/src/main/app/src/Components/Landscape/Search/Search.tsx index 7f7ce83ec..f5d8c460b 100644 --- a/src/main/app/src/Components/Landscape/Search/Search.tsx +++ b/src/main/app/src/Components/Landscape/Search/Search.tsx @@ -132,9 +132,9 @@ const Search: React.FC = ({ setSidebarContent, showSearch }) => if (identifier == null) { return; } - const result: IFacet[] | null = await get( - '/api/landscape/' + identifier + '/facets/' - ).catch((reason) => console.warn(reason)); + const result: IFacet[] | null = await get('/api/landscape/' + identifier + '/facets/').catch( + (reason) => console.warn(reason) + ); if (!result) return; setFacets(result); @@ -164,10 +164,7 @@ const Search: React.FC = ({ setSidebarContent, showSearch }) =>
- } - /> + } /> showSearch(false)} title={'Close search'}> diff --git a/src/main/app/src/Components/Landscape/Utils/MappedString.tsx b/src/main/app/src/Components/Landscape/Utils/MappedString.tsx new file mode 100644 index 000000000..7115a10a4 --- /dev/null +++ b/src/main/app/src/Components/Landscape/Utils/MappedString.tsx @@ -0,0 +1,16 @@ +import React, { useContext } from 'react'; +import { FrontendMappingContext } from '../../../Context/FrontendMappingContext'; + +interface Props { + mapKey: string; +} + +const MappedString: React.FC = ({ mapKey }) => { + const map = useContext(FrontendMappingContext); + if (map.frontendMapping.has(mapKey)) { + return <>{map.frontendMapping.get(mapKey)}; + } else { + return <>{mapKey}; + } +}; +export default MappedString; diff --git a/src/main/app/src/Components/Landscape/Utils/StatusBadge.tsx b/src/main/app/src/Components/Landscape/Utils/StatusBadge.tsx index 71fe6b68d..d148a0e2c 100644 --- a/src/main/app/src/Components/Landscape/Utils/StatusBadge.tsx +++ b/src/main/app/src/Components/Landscape/Utils/StatusBadge.tsx @@ -36,4 +36,4 @@ const StatusBadge = withStyles((theme: Theme) => }) )(Badge); -export default StatusBadge; \ No newline at end of file +export default StatusBadge; diff --git a/src/main/app/src/Components/Landscape/Utils/TabUtils.tsx b/src/main/app/src/Components/Landscape/Utils/TabUtils.tsx index 55bf8305b..0c3b6ce86 100644 --- a/src/main/app/src/Components/Landscape/Utils/TabUtils.tsx +++ b/src/main/app/src/Components/Landscape/Utils/TabUtils.tsx @@ -29,4 +29,4 @@ export const TabPanel = function (props: TabPanelProps) { {value === index && {children}}
); -}; \ No newline at end of file +}; diff --git a/src/main/app/src/Components/Landscape/Utils/utils.test.tsx b/src/main/app/src/Components/Landscape/Utils/utils.test.tsx index 1dcd244c2..c3c74648b 100644 --- a/src/main/app/src/Components/Landscape/Utils/utils.test.tsx +++ b/src/main/app/src/Components/Landscape/Utils/utils.test.tsx @@ -1,7 +1,10 @@ import { IItem } from '../../../interfaces'; import { render } from '@testing-library/react'; import React from 'react'; -import { getLabels, getLabelsWithPrefix } from './utils'; +import { getLabels, getLabelsWithPrefix, getMappedLabels } from './utils'; +import { getByText } from '@testing-library/dom/types/queries'; +import { FrontendMappingContext } from '../../../Context/FrontendMappingContext'; +import frontendMappingContextType from '../../../utils/testing/FrontendMappingContextType'; const item: IItem = { contact: 'marvin', @@ -18,6 +21,7 @@ const item: IItem = { 'icon': 'hiu', 'framework.java': '8', 'framework.react': '84711', + 'shortname': 'END_OF_LIFE', }, tags: [], type: 'service', @@ -49,3 +53,15 @@ describe('getLabelsWithPrefix', () => { expect(queryByText('color')).not.toBeInTheDocument(); }); }); + +describe('frontendMapping', () => { + it('should map the labels from the mapping API', () => { + const { getByText } = render( + + {getMappedLabels(item)} + + ); + expect(getByText('short name')).toBeInTheDocument(); + expect(getByText('end of life')).toBeInTheDocument(); + }); +}); diff --git a/src/main/app/src/Components/Landscape/Utils/utils.tsx b/src/main/app/src/Components/Landscape/Utils/utils.tsx index 5675c0198..39f18915e 100644 --- a/src/main/app/src/Components/Landscape/Utils/utils.tsx +++ b/src/main/app/src/Components/Landscape/Utils/utils.tsx @@ -1,6 +1,7 @@ import React, { ReactElement } from 'react'; -import { IGroup, IItem, ILandscape } from '../../../interfaces'; +import { IGroup, IItem, ILandscape, IRelation } from '../../../interfaces'; import { Button, Link, List, ListItem, ListItemText } from '@material-ui/core'; +import MappedString from './MappedString'; /** * Find an item by its fully qualified identifier. @@ -29,10 +30,7 @@ export const getItem = (landscape: ILandscape, fullyQualifiedIdentifier: string) * @param landscape object * @param fullyQualifiedIdentifier string to identify the group */ -export const getGroup = ( - landscape: ILandscape, - fullyQualifiedIdentifier: string -): IGroup | null => { +export const getGroup = (landscape: ILandscape, fullyQualifiedIdentifier: string): IGroup | null => { let group: IGroup | null = null; for (let i = 0; i < landscape.groups.length; i++) { let value = landscape.groups[i]; @@ -72,7 +70,7 @@ export const getLinks = (element: IGroup | IItem): ReactElement[] => { return links; }; -export const getLabels = (element: IGroup | IItem) => { +export const getLabels = (element: IGroup | IItem | IRelation) => { let labels: ReactElement[] = []; if (!element?.labels) { return null; @@ -107,6 +105,41 @@ export const getLabels = (element: IGroup | IItem) => { return {labels}; }; +export const getMappedLabels = (element: IGroup | IItem | IRelation) => { + let labels: ReactElement[] = []; + if (!element?.labels) { + return null; + } + Object.keys(element.labels).forEach((key) => { + if (element && element.labels && element.labels[key]) { + if ( + key.startsWith('icon') || + key.startsWith('fill') || + key.startsWith('tag') || + key.startsWith('framework') || + key.startsWith('network') || + key === 'color' + ) + return; + if (element.labels[key] === '*') return; + + labels.push( + + } + secondary={} + title={element.labels[key]} + /> + + ); + } + }); + if (labels.length === 0) { + return null; + } + return {labels}; +}; + /** * Returns only the labels having the given prefix. * @param prefix the label prefix to filter for diff --git a/src/main/app/src/Components/Layout/Layout.tsx b/src/main/app/src/Components/Layout/Layout.tsx index 6d0e3c737..2b23b8f44 100644 --- a/src/main/app/src/Components/Layout/Layout.tsx +++ b/src/main/app/src/Components/Layout/Layout.tsx @@ -1,9 +1,9 @@ -import React, { ReactElement } from "react"; +import React, { ReactElement } from 'react'; -import Navigation from "../Navigation/Navigation"; -import { Drawer, Theme } from "@material-ui/core"; -import { createStyles, makeStyles } from "@material-ui/core/styles"; -import Search from "../Landscape/Search/Search"; +import Navigation from '../Navigation/Navigation'; +import { Drawer, Theme } from '@material-ui/core'; +import { createStyles, makeStyles } from '@material-ui/core/styles'; +import Search from '../Landscape/Search/Search'; interface Props { children: string | ReactElement | ReactElement[]; @@ -11,6 +11,7 @@ interface Props { setSidebarContent: Function; pageTitle?: string; logo?: string; + version?: string; } const searchSupportWidth = 360; @@ -19,39 +20,39 @@ const sidebarWidth = 280; const useStyles = makeStyles((theme: Theme) => createStyles({ root: { - display: "flex" + display: 'flex', }, sideBar: { - position: "absolute", + position: 'absolute', right: 0, top: 5, width: sidebarWidth, - overflow: "auto", - maxHeight: "calc(100vh - 50px)", - zIndex: 5000 + overflow: 'auto', + maxHeight: 'calc(100vh - 50px)', + zIndex: 5000, }, outer: { - display: "flex", - flexDirection: "row" + display: 'flex', + flexDirection: 'row', }, content: { - position: 'relative' + position: 'relative', }, flexItem: { flexShrink: 1, - flexGrow: 1 + flexGrow: 1, }, main: { flexShrink: 1, flexGrow: 2, - width: "1000px" + width: '1000px', }, searchSupport: { backgroundColor: theme.palette.primary.dark, width: searchSupportWidth, - padding: 5 - } + padding: 5, + }, }) ); @@ -60,12 +61,13 @@ const useStyles = makeStyles((theme: Theme) => * @param param0 */ const Layout: React.FC = ({ - children, - sidebarContent, - setSidebarContent, - pageTitle, - logo - }) => { + children, + sidebarContent, + setSidebarContent, + pageTitle, + logo, + version, +}) => { const classes = useStyles(); const [searchSupport, setSearchSupport] = React.useState(false); @@ -74,6 +76,7 @@ const Layout: React.FC = ({
= ({
{ setSearchSupport(false); diff --git a/src/main/app/src/Components/Manual/Man.css b/src/main/app/src/Components/Manual/Man.css index 08db3c8a4..1b117fbb2 100644 --- a/src/main/app/src/Components/Manual/Man.css +++ b/src/main/app/src/Components/Manual/Man.css @@ -4,4 +4,4 @@ a.reference.external { .highlight { background-color: #333333; -} \ No newline at end of file +} diff --git a/src/main/app/src/Components/Manual/Man.test.tsx b/src/main/app/src/Components/Manual/Man.test.tsx index 5c7ff9ff5..79569ac83 100644 --- a/src/main/app/src/Components/Manual/Man.test.tsx +++ b/src/main/app/src/Components/Manual/Man.test.tsx @@ -1,10 +1,9 @@ import React from 'react'; -import { render, RenderResult } from '@testing-library/react'; +import { render } from '@testing-library/react'; import Man from './Man'; import { MemoryRouter } from 'react-router-dom'; import * as APIClient from './../../utils/API/APIClient'; -import { act } from 'react-dom/test-utils'; import { unmountComponentAtNode } from 'react-dom'; let container: HTMLElement; diff --git a/src/main/app/src/Components/Manual/Man.tsx b/src/main/app/src/Components/Manual/Man.tsx index 8836c0814..cdd83c8aa 100644 --- a/src/main/app/src/Components/Manual/Man.tsx +++ b/src/main/app/src/Components/Manual/Man.tsx @@ -1,6 +1,5 @@ -import React, { useState, useEffect, Fragment, useCallback } from 'react'; -import { Link } from 'react-router-dom'; -import { useParams } from 'react-router-dom'; +import React, { Fragment, useCallback, useEffect, useState } from 'react'; +import { Link, useParams } from 'react-router-dom'; import ReactHtmlParser, { domToReact } from 'html-react-parser'; import { get } from '../../utils/API/APIClient'; @@ -23,7 +22,7 @@ const useStyles = makeStyles((theme: Theme) => }, emptyManualContainer: { flexGrow: 1, - } + }, }) ); @@ -38,7 +37,9 @@ interface Props { const Man: React.FC = ({ setSidebarContent, setPageTitle }) => { const classes = useStyles(); const [html, setHtml] = useState( - This manual page doesn't exist. :( + + This manual page doesn't exist. :( + ); let { usage } = useParams<{ usage: string }>(); if (usage == null || typeof usage == 'undefined') usage = 'index'; @@ -46,74 +47,9 @@ const Man: React.FC = ({ setSidebarContent, setPageTitle }) => { const [side, setSide] = useState(null); const [emptyManual, setemptyManual] = useState(false); - const handleSphinxSidebar = useCallback((domNode: DomElement) => { - const replaceSphinx = (domNode: DomElement) => { - // Handle Links - if (domNode.name === 'a' && domNode.attribs && domNode.children && domNode.children[0]) { - let href = domNode.attribs['href']; - const linkText = domNode.children[0].data; - if (href.indexOf('http') !== -1 && href.indexOf('http-api') === -1) { - return; - } - - // Remove anchors - if (href.indexOf('#') !== -1) { - if ( - (href.includes('#custom-er-branding') || - href.includes('#graph') || - href.includes('#http-api')) && - usage !== 'output.html' // Have to handle output.html abit different for our sidebar - ) { - href = 'output.html'; - } else { - return {linkText}; // Convert to span if page is opened - } - } - - return ( - { - setTopic(href); - }} - > - {linkText} - - ); - } - }; - // @ts-ignore - const domToReact1: JSX.Element = domToReact([domNode]); - const html = renderToString(domToReact1); - const reactHtmlParser = ReactHtmlParser(html, { replace: replaceSphinx }); - setSide(reactHtmlParser); - }, [usage, classes]); - - useEffect(() => { - setSidebarContent(null); - setPageTitle('Manual'); - }, [setSidebarContent, setPageTitle]); - - useEffect(() => { - if (!usage?.includes('.html')) { - setTopic(usage + '.html'); - } - }, [usage]); - - useEffect(() => { - setSidebarContent(side); - }, [side, setSidebarContent]); - - - useEffect(() => { - get(`/docs/${topic}`).then((response) => { - const replaceFunc = (domNode: DomElement) => { - if (domNode.attribs && domNode.attribs.class === 'sphinxsidebar') { - handleSphinxSidebar(domNode); - return ; - } - + const handleSphinxSidebar = useCallback( + (domNode: DomElement) => { + const replaceSphinx = (domNode: DomElement) => { // Handle Links if (domNode.name === 'a' && domNode.attribs && domNode.children && domNode.children[0]) { let href = domNode.attribs['href']; @@ -138,6 +74,7 @@ const Man: React.FC = ({ setSidebarContent, setPageTitle }) => { return ( { setTopic(href); @@ -147,38 +84,115 @@ const Man: React.FC = ({ setSidebarContent, setPageTitle }) => { ); } + }; + // @ts-ignore + const domToReact1: JSX.Element = domToReact([domNode]); + const html = renderToString(domToReact1); + const reactHtmlParser = ReactHtmlParser(html, { replace: replaceSphinx }); + setSide(reactHtmlParser); + }, + [usage, classes] + ); - // Remove Nivio Text because its already in our header - if (domNode.attribs && domNode.attribs.class === 'logo') { - return ; - } + useEffect(() => { + setSidebarContent(null); + setPageTitle('Manual'); + }, [setSidebarContent, setPageTitle]); + + useEffect(() => { + if (!usage?.includes('.html')) { + setTopic(usage + '.html'); + } + }, [usage]); + + useEffect(() => { + setSidebarContent(side); + }, [side, setSidebarContent]); - // Remove Anchors in titles, wont work with HashRouter - if (domNode.name && domNode.name.includes('h') && domNode.children && domNode.children[1]) { + useEffect(() => { + get(`/docs/${topic}`) + .then((response) => { + const replaceFunc = (domNode: DomElement) => { + if (domNode.attribs && domNode.attribs.class === 'sphinxsidebar') { + handleSphinxSidebar(domNode); + return ; + } + + // Handle Links + if (domNode.name === 'a' && domNode.attribs && domNode.children && domNode.children[0]) { + let href = domNode.attribs['href']; + const linkText = domNode.children[0].data; + if (href.indexOf('http') !== -1 && href.indexOf('http-api') === -1) { + return; + } + + // Remove anchors + if (href.indexOf('#') !== -1) { + if ( + (href.includes('#custom-er-branding') || + href.includes('#graph') || + href.includes('#http-api')) && + usage !== 'output.html' // Have to handle output.html abit different for our sidebar + ) { + href = 'output.html'; + } else { + return {linkText}; // Convert to span if page is opened + } + } + + return ( + { + setTopic(href); + }} + > + {linkText} + + ); + } + + // Remove Nivio Text because its already in our header + if (domNode.attribs && domNode.attribs.class === 'logo') { + return ; + } + + // Remove Anchors in titles, wont work with HashRouter if ( - domNode.children[1].children && - domNode.children[1].children[0].data && - domNode.children[1].children[0].data === '¶' + domNode.name && + domNode.name.includes('h') && + domNode.children && + domNode.children[1] ) { - domNode.children[1] = ; + if ( + domNode.children[1].children && + domNode.children[1].children[0].data && + domNode.children[1].children[0].data === '¶' + ) { + domNode.children[1] = ; + } } + }; + const parser = new DOMParser(); + const parsedHtml = parser.parseFromString(response, 'text/html'); + const body = parsedHtml.querySelector('body'); + + if (body) { + const reactHtmlParser: JSX.Element | JSX.Element[] = ReactHtmlParser(body.innerHTML, { + replace: replaceFunc, + }); + setHtml(reactHtmlParser); + setemptyManual(true); } - }; - const parser = new DOMParser(); - const parsedHtml = parser.parseFromString(response, 'text/html'); - const body = parsedHtml.querySelector('body'); - - if (body) { - const reactHtmlParser: JSX.Element | JSX.Element[] = ReactHtmlParser(body.innerHTML, { - replace: replaceFunc, - }); - setHtml(reactHtmlParser); - setemptyManual(true); - } - }).catch(reason => console.error(reason)); + }) + .catch((reason) => console.error(reason)); }, [topic, usage, handleSphinxSidebar]); - return {html}; + return ( + + {html} + + ); }; export default Man; diff --git a/src/main/app/src/Components/Navigation/Navigation.test.tsx b/src/main/app/src/Components/Navigation/Navigation.test.tsx index f941e59fa..9e3c35aac 100644 --- a/src/main/app/src/Components/Navigation/Navigation.test.tsx +++ b/src/main/app/src/Components/Navigation/Navigation.test.tsx @@ -2,10 +2,11 @@ import React from 'react'; import { render } from '@testing-library/react'; import Navigation from './Navigation'; import { MemoryRouter } from 'react-router-dom'; -import { TextEncoder, TextDecoder } from 'util' -global.TextEncoder = TextEncoder +import { TextDecoder, TextEncoder } from 'util'; + +global.TextEncoder = TextEncoder; // @ts-ignore -global.TextDecoder = TextDecoder +global.TextDecoder = TextDecoder; it('should render Home link', () => { const { getByText } = render( diff --git a/src/main/app/src/Components/Navigation/Navigation.tsx b/src/main/app/src/Components/Navigation/Navigation.tsx index 6d0d16e36..f1867c77e 100644 --- a/src/main/app/src/Components/Navigation/Navigation.tsx +++ b/src/main/app/src/Components/Navigation/Navigation.tsx @@ -1,13 +1,13 @@ import React, { useContext } from 'react'; import { - Typography, - Theme, - createStyles, Box, + createStyles, Menu, MenuItem, - withStyles, MenuProps, + Theme, + Typography, + withStyles, } from '@material-ui/core'; import { Link } from 'react-router-dom'; @@ -51,6 +51,7 @@ interface Props { searchSupport: boolean; pageTitle?: string; logo?: string; + version?: string; } /** @@ -62,6 +63,7 @@ const Navigation: React.FC = ({ searchSupport, pageTitle, logo, + version, }) => { const classes = useStyles(); const componentClasses = componentStyles(); @@ -124,6 +126,9 @@ const Navigation: React.FC = ({ Help + + nivio {version} + {pageTitle} diff --git a/src/main/app/src/Components/Notification/Notification.tsx b/src/main/app/src/Components/Notification/Notification.tsx index 67e545dc7..674cd8f1c 100644 --- a/src/main/app/src/Components/Notification/Notification.tsx +++ b/src/main/app/src/Components/Notification/Notification.tsx @@ -1,10 +1,10 @@ -import React, { ReactElement, useContext, useEffect, useState } from 'react'; +import React, {ReactElement, useContext, useEffect, useState} from 'react'; import IconButton from '@material-ui/core/IconButton'; -import { Badge } from '@material-ui/core'; -import { Notifications } from '@material-ui/icons'; +import {Badge} from '@material-ui/core'; +import {Notifications} from '@material-ui/icons'; import Changes from './Changes'; import componentStyles from '../../Resources/styling/ComponentStyles'; -import { LandscapeContext } from '../../Context/LandscapeContext'; +import {LandscapeContext} from '../../Context/LandscapeContext'; interface Props { setSidebarContent: Function; @@ -16,12 +16,10 @@ interface Props { * */ const Notification: React.FC = ({ setSidebarContent }) => { - const classes = componentStyles(); const [newChanges, setNewChanges] = useState(false); const [renderedChanges, setRenderedChanges] = useState(null); const landscapeContext = useContext(LandscapeContext); - /** * render changes, @@ -33,7 +31,13 @@ const Notification: React.FC = ({ setSidebarContent }) => { }, [landscapeContext.notification]); return ( - + borderRadius: 5, backgroundColor: theme.palette.secondary.dark, display: 'flex', - justifyContent: 'center' + justifyContent: 'center', }, green: { backgroundColor: 'green', diff --git a/src/main/app/src/Context/FrontendMappingContext.tsx b/src/main/app/src/Context/FrontendMappingContext.tsx new file mode 100644 index 000000000..0a0b47eb4 --- /dev/null +++ b/src/main/app/src/Context/FrontendMappingContext.tsx @@ -0,0 +1,31 @@ +import React, { useEffect, useState } from 'react'; +import { get } from '../utils/API/APIClient'; + +export interface FrontendMappingContextType { + frontendMapping: Map; +} + +export const FrontendMappingContext = React.createContext({ + frontendMapping: new Map(), +}); + +const FrontendMappingProvider: React.FC = ({ children }) => { + const [frontendMapping, setFrontendMapping] = useState(new Map()); + + useEffect(() => { + get(`/api/mapping`).then((response) => { + setFrontendMapping(new Map(Object.entries(response))); + }); + }); + + return ( + + {children} + + ); +}; +export { FrontendMappingProvider }; diff --git a/src/main/app/src/Context/LandscapeContext.tsx b/src/main/app/src/Context/LandscapeContext.tsx index ee8b6360e..bf9b1eb44 100644 --- a/src/main/app/src/Context/LandscapeContext.tsx +++ b/src/main/app/src/Context/LandscapeContext.tsx @@ -55,7 +55,7 @@ const LandscapeContextProvider: React.FC<{}> = (props) => { const subscriptions: StompSubscription[] = []; const eventSubscription = client.subscribe('/topic/events', (message) => { const notificationMessage: INotificationMessage = JSON.parse(message.body); - if (notificationMessage.type === 'ProcessingFinishedEvent') { + if (notificationMessage.type === 'LayoutChangedEvent') { setNotification(notificationMessage); } }); @@ -89,11 +89,11 @@ const LandscapeContextProvider: React.FC<{}> = (props) => { get(`/api/${identifier}`).then((response) => { setLandscape(response); - console.debug(`Loaded landscape data for ${identifier}`); + console.debug(`Loaded landscape data after identifier change: ${identifier}`); }); get(`/assessment/${identifier}`).then((response) => { setAssessment(response); - console.debug(`Loaded assessment data for ${identifier}`); + console.debug(`Loaded assessment data after identifier change: ${identifier}`); }); }, [identifier]); @@ -107,8 +107,8 @@ const LandscapeContextProvider: React.FC<{}> = (props) => { } get(`/assessment/${identifier}`).then((response) => { + console.debug(`Loaded assessment data for ${identifier}`, response); setAssessment(response); - console.debug(`Loaded assessment data for ${identifier}`); }); }, [identifier, notification]); diff --git a/src/main/app/src/Context/LocateFunctionContext.tsx b/src/main/app/src/Context/LocateFunctionContext.tsx index b3c7cca6e..9f569640c 100644 --- a/src/main/app/src/Context/LocateFunctionContext.tsx +++ b/src/main/app/src/Context/LocateFunctionContext.tsx @@ -6,6 +6,7 @@ export interface LocateFunctionContextType { locateFunction: (fqi: string) => void; setLocateFunction: (locateFunction: () => void) => void; } + export const LocateFunctionContext = React.createContext({ locateFunction: initialLocateFunction, setLocateFunction: () => {}, @@ -15,9 +16,8 @@ export const LocateFunctionContext = React.createContext = (props) => { - const [locateFunction, setLocateFunction] = useState<(fqi: string) => void>( - initialLocateFunction - ); + const [locateFunction, setLocateFunction] = + useState<(fqi: string) => void>(initialLocateFunction); return ( ; labelBlacklist?: Array; branding?: IBranding; - kpis?: IKpis; } export interface IKpis { @@ -54,11 +54,17 @@ export interface IKpi { } export interface IRanges { - [key: string]: string; + [key: string]: IRange; +} + +export interface IRange { + minimum: string; + maximum: string; + description?: string; } export interface IMatches { - [key: string]: string; + [key: string]: string[]; } export interface IBranding { @@ -83,7 +89,6 @@ export interface IGroup { fullyQualifiedIdentifier: string; labels?: ILabels; _links?: ILinks; - links?: ILinks; items: IItem[]; } @@ -103,7 +108,6 @@ export interface IItem { tags: Array; color?: string; icon: string; - links?: Object; _links?: ILinks; } @@ -133,6 +137,7 @@ export interface IRelation { name: string; id: string; direction: string; + labels: ILabels; } export interface ILabels { @@ -169,10 +174,10 @@ export interface IAssessmentResults { } export interface IAssessmentProps { + identifier: string; field: string; status: string; message: string; - maxField?: string; summary: boolean; } diff --git a/src/main/app/src/labels.json b/src/main/app/src/labels.json index a38b4beab..4edfa1454 100644 --- a/src/main/app/src/labels.json +++ b/src/main/app/src/labels.json @@ -1 +1,22 @@ -{"capability":"The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.","color":"A hex color code to override the inherited group color","costs":"Running costs of the item.","fill":"Background image (for displaying purposes).","frameworks":"A comma-separated list of frameworks as key-value pairs (key is name, value is version).","health":"Description of the item's health status.","icon":"Icon/image (for displaying purposes).","layer":"A technical layer.","lifecycle":"A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).","note":"A custom note.","scale":"Number of instances.","security":"Description of the item's security status.","shortname":"Abbreviated name.","software":"Software/OS name.","stability":"Description of the item's stability.","team":"Name of the responsible team (e.g. technical owner).","type":"The type (service, database, queue, load balancer, etc.).","version":"The version (e.g. software version or protocol version).","visibility":"Visibility to other items."} \ No newline at end of file +{ + "capability": "The capability the service provides for the business or, in case of infrastructure, the technical capability like enabling service discovery, configuration, secrets, or persistence.", + "color": "A hex color code (items inherit group colors as default)", + "costs": "Running costs of the item.", + "fill": "Background image (for displaying purposes).", + "frameworks": "A comma-separated list of frameworks as key-value pairs (key is name, value is version).", + "health": "Description of the item's health status.", + "icon": "Icon/image (for displaying purposes).", + "label": "A custom label (like a note, but very short).", + "layer": "A technical layer.", + "lifecycle": "A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``).", + "note": "A custom note.", + "scale": "Number of instances.", + "security": "Description of the item's security status.", + "shortname": "Abbreviated name.", + "software": "Software/OS name.", + "stability": "Description of the item's stability.", + "team": "Name of the responsible team (e.g. technical owner).", + "version": "The version (e.g. software version or protocol version).", + "visibility": "Visibility to other items.", + "weight": "Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given." +} diff --git a/src/main/app/src/utils/testing/FrontendMappingContextType.ts b/src/main/app/src/utils/testing/FrontendMappingContextType.ts new file mode 100644 index 000000000..397c9d5a8 --- /dev/null +++ b/src/main/app/src/utils/testing/FrontendMappingContextType.ts @@ -0,0 +1,9 @@ +import { FrontendMappingContextType } from '../../Context/FrontendMappingContext'; + +const frontendMappingContextType: FrontendMappingContextType = { + frontendMapping: new Map([ + ['shortname', 'short name'], + ['END_OF_LIFE', 'end of life'], + ]), +}; +export default frontendMappingContextType; diff --git a/src/main/app/src/utils/testing/LandscapeContextValue.ts b/src/main/app/src/utils/testing/LandscapeContextValue.ts index 43f6315c8..d2109ec84 100644 --- a/src/main/app/src/utils/testing/LandscapeContextValue.ts +++ b/src/main/app/src/utils/testing/LandscapeContextValue.ts @@ -42,6 +42,7 @@ const assessments: IAssessment = { results: { 'test/groupA/foo': [ { + identifier: 'test/groupA/foo', field: 'foo', status: 'yellow', message: 'bar', @@ -50,19 +51,19 @@ const assessments: IAssessment = { ], 'test/groupA': [ { + identifier: 'test/groupA', field: 'foo', status: 'yellow', message: 'bar', - maxField: 'foo', summary: true, }, ], 'test': [ { + identifier: 'test', field: 'overall', status: 'yellow', message: 'The landscape is somehow broken.', - maxField: 'foo', summary: true, }, ], @@ -80,4 +81,4 @@ const landscapeContextValue: LandscapeContextType = { notification: null, }; -export default landscapeContextValue; \ No newline at end of file +export default landscapeContextValue; diff --git a/src/main/app/yarn.lock b/src/main/app/yarn.lock index 57538f86d..7e7b083a3 100644 --- a/src/main/app/yarn.lock +++ b/src/main/app/yarn.lock @@ -1312,6 +1312,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.13": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" + integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/runtime@^7.8.7": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" @@ -1657,14 +1664,14 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@material-ui/core@^4.11.4": - version "4.11.4" - resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.4.tgz#4fb9fe5dec5dcf780b687e3a40cff78b2b9640a4" - integrity sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg== +"@material-ui/core@^4.12.3": + version "4.12.3" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.12.3.tgz#80d665caf0f1f034e52355c5450c0e38b099d3ca" + integrity sha512-sdpgI/PL56QVsEJldwEe4FFaFTLUqN+rd7sSZiRCdx2E/C7z5yK0y/khAWVBH24tXwto7I1hCzNWfJGZIYJKnw== dependencies: "@babel/runtime" "^7.4.4" "@material-ui/styles" "^4.11.4" - "@material-ui/system" "^4.11.3" + "@material-ui/system" "^4.12.1" "@material-ui/types" "5.1.0" "@material-ui/utils" "^4.11.2" "@types/react-transition-group" "^4.2.0" @@ -1715,10 +1722,10 @@ jss-plugin-vendor-prefixer "^10.5.1" prop-types "^15.7.2" -"@material-ui/system@^4.11.3": - version "4.11.3" - resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.3.tgz#466bc14c9986798fd325665927c963eb47cc4143" - integrity sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw== +"@material-ui/system@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.12.1.tgz#2dd96c243f8c0a331b2bb6d46efd7771a399707c" + integrity sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw== dependencies: "@babel/runtime" "^7.4.4" "@material-ui/utils" "^4.11.2" @@ -2153,10 +2160,10 @@ jest-diff "^25.2.1" pretty-format "^25.2.1" -"@types/jest@^26.0.23": - version "26.0.23" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.23.tgz#a1b7eab3c503b80451d019efb588ec63522ee4e7" - integrity sha512-ZHLmWMJ9jJ9PTiT58juykZpL7KjwJywFN3Rr2pTSkyQfydf/rk22yS7W8p5DaVUMQ2BQC7oYiU3FjbTM/mYrOA== +"@types/jest@^26.0.24": + version "26.0.24" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" + integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== dependencies: jest-diff "^26.0.0" pretty-format "^26.0.0" @@ -2186,10 +2193,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.24.tgz#b0f86f58564fa02a28b68f8b55d4cdec42e3b9d6" integrity sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA== -"@types/node@^14.17.3": - version "14.17.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.4.tgz#218712242446fc868d0e007af29a4408c7765bc0" - integrity sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A== +"@types/node@^14.17.18": + version "14.17.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.27.tgz#5054610d37bb5f6e21342d0e6d24c494231f3b85" + integrity sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -2216,25 +2223,25 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react-dom@^16.9.13": - version "16.9.13" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.13.tgz#5898f0ee68fe200685e6b61d3d7d8828692814d0" - integrity sha512-34Hr3XnmUSJbUVDxIw/e7dhQn2BJZhJmlAaPyPwfTQyuVS9mV/CeyghFcXyvkJXxI7notQJz8mF8FeCVvloJrA== +"@types/react-dom@^16.9.14": + version "16.9.14" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.14.tgz#674b8f116645fe5266b40b525777fc6bb8eb3bcd" + integrity sha512-FIX2AVmPTGP30OUJ+0vadeIFJJ07Mh1m+U0rxfgyW34p3rTlXI+nlenvAxNn4BP36YyI9IJ/+UJ7Wu22N1pI7A== dependencies: "@types/react" "^16" -"@types/react-html-parser@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/react-html-parser/-/react-html-parser-2.0.1.tgz#2d9002ac5bf1adf9aff8eae77ace5488bd78c98d" - integrity sha512-Lyw0AtG3gahw78CX2pzmzhKaoZCfJNzzuhhPsFVhzFrylMv8NaCmzYaPKglMv3RRHpwBbHuMOkVx0HiwGZKgSA== +"@types/react-html-parser@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/react-html-parser/-/react-html-parser-2.0.2.tgz#9b7e1b99657967e614aebf3f87d78a3fd0a1602c" + integrity sha512-avS2QzBMCUTGO2+gi3rWG6WreuU8zhf4b5CbS11itYlvLbwt5wmxBqQN4/f2z/JR/6Kvdt8ohAxhztb8XQHdPQ== dependencies: "@types/htmlparser2" "*" "@types/react" "*" -"@types/react-router-dom@^5.1.7": - version "5.1.7" - resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.7.tgz#a126d9ea76079ffbbdb0d9225073eb5797ab7271" - integrity sha512-D5mHD6TbdV/DNHYsnwBTv+y73ei+mMjrkGrla86HthE4/PVvL1J94Bu3qABU+COXzpL23T1EZapVVpwHuBXiUg== +"@types/react-router-dom@^5.3.0": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.1.tgz#76700ccce6529413ec723024b71f01fc77a4a980" + integrity sha512-UvyRy73318QI83haXlaMwmklHHzV9hjl3u71MmM6wYNu0hOVk9NLTa0vGukf8zXUqnwz4O06ig876YSPpeK28A== dependencies: "@types/history" "*" "@types/react" "*" @@ -2248,10 +2255,10 @@ "@types/history" "*" "@types/react" "*" -"@types/react-svg-pan-zoom@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/react-svg-pan-zoom/-/react-svg-pan-zoom-3.3.1.tgz#ae210ffd20422515eaf5d54bfa8fe374be585b1e" - integrity sha512-N10C2gGqs6apsnTmmddCbAlNwb5VuX1DvosPV7NOmPPrSaKjMIRdgJ4luj9qipGHzafUU/T2JtM87RgvO/V+XA== +"@types/react-svg-pan-zoom@^3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@types/react-svg-pan-zoom/-/react-svg-pan-zoom-3.3.2.tgz#58a259db7c4c211880cc3c0759ed6f7c8aafe3bc" + integrity sha512-q1PVNhwaM8FaIv73hFfKgvqGzaExTtx9aBUi75lAJPK7TIhw8Ql990oE4RHQjIUmmxWU/lE/RSbv2c+2W/K5Sg== dependencies: "@types/react" "*" @@ -2262,10 +2269,10 @@ dependencies: "@types/react" "*" -"@types/react-transition-group@^4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.1.tgz#e1a3cb278df7f47f17b5082b1b3da17170bd44b1" - integrity sha512-vIo69qKKcYoJ8wKCJjwSgCTM+z3chw3g18dkrDfVX665tMH7tmbDxEAnPdey4gTlwZz5QuHGzd+hul0OVZDqqQ== +"@types/react-transition-group@^4.4.3": + version "4.4.3" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.3.tgz#b0994da0a7023d67dbb4a8910a62112bc00d5688" + integrity sha512-fUx5muOWSYP8Bw2BUQ9M9RK9+W1XBK/7FLJ8PTQpnpTEkn0ccyMffyEQvan4C3h53gHdx7KE5Qrxi/LnUGQtdg== dependencies: "@types/react" "*" @@ -2285,10 +2292,10 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/react@^16.14.6": - version "16.14.8" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.8.tgz#4aee3ab004cb98451917c9b7ada3c7d7e52db3fe" - integrity sha512-QN0/Qhmx+l4moe7WJuTxNiTsjBwlBGHqKGvInSQCBdo7Qio0VtOqwsC0Wq7q3PbJlB0cR4Y4CVo1OOe6BOsOmA== +"@types/react@^16.14.15": + version "16.14.17" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.17.tgz#c57fcfb05efa6423f5b65fcd4a75f63f05b162bf" + integrity sha512-pMLc/7+7SEdQa9A+hN9ujI8blkjFqYAZVqh3iNXqdZ0cQ8TIR502HMkNJniaOGv9SAgc47jxVKoiBJ7c0AakvQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -3040,12 +3047,12 @@ axe-core@^4.0.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.2.tgz#7cf783331320098bfbef620df3b3c770147bc224" integrity sha512-V+Nq70NxKhYt89ArVcaNL9FDryB3vQOd+BFXZIfO3RP6rwtj+2yqqqdHEkacutglPaZLkJeuXKCjCJDMGPtPqg== -axios@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== +axios@^0.21.4: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: - follow-redirects "^1.10.0" + follow-redirects "^1.14.0" axobject-query@^2.2.0: version "2.2.0" @@ -5716,11 +5723,16 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@^1.0.0, follow-redirects@^1.10.0: +follow-redirects@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7" integrity sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg== +follow-redirects@^1.14.0: + version "1.14.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.3.tgz#6ada78118d8d24caee595595accdc0ac6abd022e" + integrity sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -8860,9 +8872,9 @@ path-key@^3.0.0, path-key@^3.1.0: integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-to-regexp@0.1.7: version "0.1.7" @@ -9691,10 +9703,10 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -prettier@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" - integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== +prettier@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c" + integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA== pretty-bytes@^5.3.0: version "5.6.0" @@ -10030,25 +10042,25 @@ react-refresh@^0.8.3: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== -react-router-dom@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" - integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA== +react-router-dom@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" + integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== dependencies: - "@babel/runtime" "^7.1.2" + "@babel/runtime" "^7.12.13" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.2.0" + react-router "5.2.1" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" - integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw== +react-router@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" + integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== dependencies: - "@babel/runtime" "^7.1.2" + "@babel/runtime" "^7.12.13" history "^4.9.0" hoist-non-react-statics "^3.1.0" loose-envify "^1.3.1" @@ -11667,9 +11679,9 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3: integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-arraybuffer@^1.0.0: version "1.0.1" @@ -11865,10 +11877,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@~3.9.9: - version "3.9.9" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674" - integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w== +typescript@~3.9.10: + version "3.9.10" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== unbox-primitive@^1.0.0: version "1.0.0" @@ -12004,9 +12016,9 @@ url-loader@4.1.1: schema-utils "^3.0.0" url-parse@^1.4.3, url-parse@^1.4.7: - version "1.5.1" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b" - integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q== + version "1.5.3" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" + integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" diff --git a/src/main/java/de/bonndan/nivio/api/ApiController.java b/src/main/java/de/bonndan/nivio/api/ApiController.java index bbd9bffd5..30998d9aa 100644 --- a/src/main/java/de/bonndan/nivio/api/ApiController.java +++ b/src/main/java/de/bonndan/nivio/api/ApiController.java @@ -4,6 +4,10 @@ import de.bonndan.nivio.input.ProcessLog; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.model.*; +import de.bonndan.nivio.output.dto.GroupApiModel; +import de.bonndan.nivio.output.dto.ItemApiModel; +import de.bonndan.nivio.output.dto.LandscapeApiModel; +import de.bonndan.nivio.util.FrontendMapping; import org.apache.lucene.facet.FacetResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,8 +20,10 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; @RestController @RequestMapping(path = ApiController.PATH) @@ -30,14 +36,17 @@ public class ApiController { private final LandscapeRepository landscapeRepository; private final LinkFactory linkFactory; private final IndexingDispatcher indexingDispatcher; + private final FrontendMapping frontendMapping; public ApiController(LandscapeRepository landscapeRepository, LinkFactory linkFactory, - IndexingDispatcher indexingDispatcher + IndexingDispatcher indexingDispatcher, + FrontendMapping frontendMapping ) { this.landscapeRepository = landscapeRepository; this.linkFactory = linkFactory; this.indexingDispatcher = indexingDispatcher; + this.frontendMapping = frontendMapping; } /** @@ -57,15 +66,15 @@ public Index index() { */ @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/{landscapeIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity landscape(@PathVariable String landscapeIdentifier) { + public ResponseEntity landscape(@PathVariable String landscapeIdentifier) { Landscape landscape = landscapeRepository.findDistinctByIdentifier(landscapeIdentifier).orElse(null); if (landscape == null) { return ResponseEntity.notFound().build(); } - //TODO this modifies the landscape components by adding SELF links - linkFactory.setLandscapeLinksRecursive(landscape); - return new ResponseEntity<>(landscape, HttpStatus.OK); + LandscapeApiModel landscapeApiModel = new LandscapeApiModel(landscape); + linkFactory.setLandscapeLinksRecursive(landscapeApiModel); + return new ResponseEntity<>(landscapeApiModel, HttpStatus.OK); } /** @@ -73,19 +82,19 @@ public ResponseEntity landscape(@PathVariable String landscapeIdentif */ @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/{landscapeIdentifier}/{groupIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity group(@PathVariable String landscapeIdentifier, - @PathVariable String groupIdentifier + public ResponseEntity group(@PathVariable String landscapeIdentifier, + @PathVariable String groupIdentifier ) { Landscape landscape = landscapeRepository.findDistinctByIdentifier(landscapeIdentifier).orElse(null); if (landscape == null) { return ResponseEntity.notFound().build(); } - //TODO this modifies the landscape components by adding SELF links Optional group = landscape.getGroup(groupIdentifier); if (group.isPresent()) { - linkFactory.setGroupLinksRecursive(group.get()); - return new ResponseEntity<>(group.get(), HttpStatus.OK); + GroupApiModel groupItem = new GroupApiModel(group.get(), landscape.getItems().retrieve(group.get().getItems())); + linkFactory.setGroupLinksRecursive(groupItem); + return new ResponseEntity<>(groupItem, HttpStatus.OK); } else { return ResponseEntity.notFound().build(); } @@ -96,9 +105,9 @@ public ResponseEntity group(@PathVariable String landscapeIdentifier, */ @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/{landscapeIdentifier}/{groupIdentifier}/{itemIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity item(@PathVariable String landscapeIdentifier, - @PathVariable String groupIdentifier, - @PathVariable String itemIdentifier + public ResponseEntity item(@PathVariable String landscapeIdentifier, + @PathVariable String groupIdentifier, + @PathVariable String itemIdentifier ) { Landscape landscape = landscapeRepository.findDistinctByIdentifier(landscapeIdentifier).orElse(null); if (landscape == null) { @@ -109,16 +118,17 @@ public ResponseEntity item(@PathVariable String landscapeIdentifier, if (item.isEmpty()) { return ResponseEntity.notFound().build(); } - Item item1 = item.get(); - linkFactory.setItemSelfLink(item1); - return new ResponseEntity<>(item1, HttpStatus.OK); + Group group = landscape.getGroup(groupIdentifier).orElseThrow(); + ItemApiModel apiModel = new ItemApiModel(item.get(), group); + linkFactory.setItemSelfLink(apiModel); + return new ResponseEntity<>(apiModel, HttpStatus.OK); } /** * Creates a new landscape */ @PostMapping(path = "/landscape") - public ResponseEntity create(@RequestBody String body) throws URISyntaxException { + public ResponseEntity create(@RequestBody String body) { LandscapeDescription env = indexingDispatcher.createFromBody(body); Optional uriForDTO = getURIForDTO(env); return uriForDTO @@ -131,7 +141,7 @@ public ResponseEntity addItems( @PathVariable String identifier, @RequestHeader(name = "format") String format, @RequestBody String body - ) throws URISyntaxException { + ) { LandscapeDescription dto = indexingDispatcher.createFromBodyItems(identifier, format, body); Optional uriForDTO = getURIForDTO(dto); return uriForDTO @@ -153,15 +163,19 @@ public ResponseEntity log(@PathVariable String identifier) { @CrossOrigin(methods = RequestMethod.GET) @GetMapping(path = "/landscape/{identifier}/search/{query}", produces = "application/json") - public ResponseEntity> search(@PathVariable String identifier, @PathVariable String query) { + public ResponseEntity> search(@PathVariable String identifier, @PathVariable String query) { Landscape landscape = landscapeRepository.findDistinctByIdentifier(identifier).orElse(null); if (landscape == null) { return ResponseEntity.notFound().build(); } + Map groups = landscape.getGroups(); try { - return new ResponseEntity<>(landscape.search(query), HttpStatus.OK); + Set results = landscape.search(query).stream() + .map(item -> new ItemApiModel(item, groups.get(item.getGroup()))) + .collect(Collectors.toSet()); + return new ResponseEntity<>(results, HttpStatus.OK); } catch (RuntimeException error) { LOGGER.error("Search query '{}' in landscape {} failed: {}", query, landscape, error.getMessage(), error); return ResponseEntity.badRequest().build(); @@ -182,11 +196,24 @@ public ResponseEntity> facets(@PathVariable String identifier) } + @CrossOrigin(methods = RequestMethod.GET) + @GetMapping(path = "/mapping", produces = "application/json") + public ResponseEntity> mapping() { + return new ResponseEntity<>(frontendMapping.getKeys(), HttpStatus.OK); + } + + + @CrossOrigin(methods = RequestMethod.GET) + @GetMapping(path = "/description", produces = "application/json") + public ResponseEntity> description() { + return new ResponseEntity<>(frontendMapping.getDescriptions(), HttpStatus.OK); + } + /** * Trigger reindexing of a landscape source. */ @PostMapping(path = "/reindex/{landscape}") - public ResponseEntity reindex(@PathVariable String landscape) throws URISyntaxException { + public ResponseEntity reindex(@PathVariable String landscape) { Landscape existing = landscapeRepository.findDistinctByIdentifier(landscape).orElse(null); if (existing == null) { return ResponseEntity.notFound().build(); @@ -199,8 +226,9 @@ public ResponseEntity reindex(@PathVariable String landscape) throws URI .orElseGet(() -> ResponseEntity.unprocessableEntity().build()); } + private Optional getURIForDTO(LandscapeDescription env) { - Optional link = Optional.ofNullable(linkFactory.generateComponentLink(env.getFullyQualifiedIdentifier())); + Optional link = linkFactory.generateComponentLink(env.getFullyQualifiedIdentifier()); if (link.isEmpty()) { return Optional.empty(); } diff --git a/src/main/java/de/bonndan/nivio/api/LinkFactory.java b/src/main/java/de/bonndan/nivio/api/LinkFactory.java index 6a47d5697..26f6fa293 100644 --- a/src/main/java/de/bonndan/nivio/api/LinkFactory.java +++ b/src/main/java/de/bonndan/nivio/api/LinkFactory.java @@ -5,15 +5,15 @@ import de.bonndan.nivio.model.*; import de.bonndan.nivio.output.LocalServer; import de.bonndan.nivio.output.docs.DocsController; +import de.bonndan.nivio.output.dto.GroupApiModel; +import de.bonndan.nivio.output.dto.ItemApiModel; +import de.bonndan.nivio.output.dto.LandscapeApiModel; import de.bonndan.nivio.output.map.MapController; import org.springframework.http.MediaType; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.StreamSupport; import static de.bonndan.nivio.model.Link.LinkBuilder.linkTo; @@ -35,9 +35,10 @@ public LinkFactory(LocalServer localServer, NivioConfigProperties configProperti this.configProperties = configProperties; } - public Map getLandscapeLinks(Landscape landscape) { + public Map getLandscapeLinks(LandscapeApiModel landscape) { Map links = new HashMap<>(); - links.put(REL_SELF, generateComponentLink(landscape.getFullyQualifiedIdentifier())); + generateComponentLink(landscape.getFullyQualifiedIdentifier()) + .ifPresent(link -> links.put(REL_SELF, link)); localServer.getUrl(ApiController.PATH, "reindex", landscape.getIdentifier()).ifPresent(url -> { links.put("reindex", linkTo(url) @@ -81,7 +82,6 @@ public Map getLandscapeLinks(Landscape landscape) { ); }); - localServer.getUrl(AssessmentController.PATH, landscape.getFullyQualifiedIdentifier().toString()).ifPresent(url -> { links.put("assessment", linkTo(url) .withMedia(MediaType.APPLICATION_JSON_VALUE) @@ -90,7 +90,6 @@ public Map getLandscapeLinks(Landscape landscape) { ); }); - return links; } @@ -100,14 +99,14 @@ public Map getLandscapeLinks(Landscape landscape) { * @param fullyQualifiedIdentifier the component's fqi * @return link based on the {@link FullyQualifiedIdentifier} */ - @Nullable - public Link generateComponentLink(@NonNull FullyQualifiedIdentifier fullyQualifiedIdentifier) { + @NonNull + public Optional generateComponentLink(@NonNull FullyQualifiedIdentifier fullyQualifiedIdentifier) { return localServer.getUrl(ApiController.PATH, Objects.requireNonNull(fullyQualifiedIdentifier).jsonValue()) .map(url -> linkTo(url) .withMedia(MediaType.APPLICATION_JSON_VALUE) .withTitle("JSON representation") .build() - ).orElse(null); + ); } /** @@ -139,26 +138,20 @@ Index getIndex(Iterable landscapes) { * * @param landscape landscape */ - void setLandscapeLinksRecursive(Landscape landscape) { + void setLandscapeLinksRecursive(LandscapeApiModel landscape) { Map landscapeLinks = getLandscapeLinks(landscape); - landscape.setLinks(landscapeLinks); - setGroupSelfLinksRecursive(landscape.getGroups()); - } - - void setGroupSelfLinksRecursive(Map groups) { - groups.forEach((s, groupItem) -> setGroupLinksRecursive(groupItem)); + landscape.setHateoasLinks(landscapeLinks); + landscape.getGroups().forEach(this::setGroupLinksRecursive); } - void setGroupLinksRecursive(Group groupItem) { - if (!groupItem.getLinks().containsKey(REL_SELF)) { - groupItem.getLinks().put(REL_SELF, generateComponentLink(groupItem.getFullyQualifiedIdentifier())); - } + void setGroupLinksRecursive(GroupApiModel groupItem) { + generateComponentLink(groupItem.getFullyQualifiedIdentifier()) + .ifPresent(link -> groupItem.setHateoasLinks(Map.of(REL_SELF, link))); groupItem.getItems().forEach(this::setItemSelfLink); } - void setItemSelfLink(Item item) { - if (!item.getLinks().containsKey(REL_SELF)) { - item.getLinks().put(REL_SELF, generateComponentLink(item.getFullyQualifiedIdentifier())); - } + void setItemSelfLink(ItemApiModel item) { + generateComponentLink(item.getFullyQualifiedIdentifier()) + .ifPresent(link -> item.setHateoasLinks(Map.of(REL_SELF, link))); } } diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessable.java b/src/main/java/de/bonndan/nivio/assessment/Assessable.java index a06594da0..9ef251e01 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessable.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessable.java @@ -1,20 +1,18 @@ package de.bonndan.nivio.assessment; import com.fasterxml.jackson.annotation.JsonIgnore; -import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.kpi.KPI; -import de.bonndan.nivio.model.Component; +import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.model.FullyQualifiedIdentifier; import org.springframework.lang.NonNull; import java.util.*; - -import static de.bonndan.nivio.assessment.StatusValue.SUMMARY_LABEL; +import java.util.stream.Collectors; /** * Interface for components that can be assessed and can have assigned {@link StatusValue}s. */ -public interface Assessable extends Component { +public interface Assessable { /** * Returns pre-set status values not computed by {@link KPI}s. @@ -24,15 +22,24 @@ public interface Assessable extends Component { * @return a distinct (by field) set */ @JsonIgnore + @NonNull Set getAdditionalStatusValues(); + /** + * Returns the string to be used as key/identifier for a component assessment. + * + * @return map key / identifier + */ + @JsonIgnore + @NonNull + String getAssessmentIdentifier(); + /** * Returns the components to be assessed before this (e.g. group items). */ @JsonIgnore - default List getChildren() { - return new ArrayList<>(); - } + @NonNull + List getChildren(); /** * Recursively applies the {@link KPI}s to children and self. @@ -40,8 +47,8 @@ default List getChildren() { * @param kpis kpis used for assessment * @return a map with statusValues indexed by {@link FullyQualifiedIdentifier} */ - default Map> applyKPIs(final Map kpis) { - final Map> map = new HashMap<>(); + default Map> applyKPIs(final Map kpis) { + final Map> map = new HashMap<>(); List childrenValues = new ArrayList<>(); //apply to children @@ -51,7 +58,7 @@ default Map> applyKPIs(final Map()); //add preset status values @@ -71,9 +78,10 @@ default Map> applyKPIs(final Map worst = getWorst(childrenValues); + replace(map.get(fqi), StatusValue.summary(getAssessmentIdentifier(), worst)); - //sort in descending order, worst first + //sort in descending order, the worst first map.get(fqi).sort(Collections.reverseOrder(new StatusValue.Comparator())); return map; } @@ -83,15 +91,22 @@ private void replaceAll(List present, Collection added } private void replace(List present, StatusValue added) { - present.remove(added); + List removables = present.stream() + .filter(statusValue -> statusValue.equals(added)) + .collect(Collectors.toUnmodifiableList()); + present.removeAll(removables); present.add(added); } @NonNull - static StatusValue getWorst(List values) { - return values.stream() - .filter(Objects::nonNull) - .max(new StatusValue.Comparator()) - .orElse(new StatusValue(SUMMARY_LABEL, Status.UNKNOWN)); + static List getWorst(List values) { + if (values == null || values.isEmpty()) { + return new ArrayList<>(); + } + + values.sort(new StatusValue.Comparator()); + Status worstStatus = values.get(values.size()-1).getStatus(); + + return values.stream().filter(statusValue -> statusValue.getStatus().equals(worstStatus)).collect(Collectors.toUnmodifiableList()); } } diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessableGroup.java b/src/main/java/de/bonndan/nivio/assessment/AssessableGroup.java new file mode 100644 index 000000000..059a3eb49 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/AssessableGroup.java @@ -0,0 +1,60 @@ +package de.bonndan.nivio.assessment; + +import de.bonndan.nivio.model.Group; +import de.bonndan.nivio.model.Item; +import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.model.Labeled; +import org.springframework.lang.NonNull; + +import java.util.*; + +/** + * This is a decorator for {@link Group} when creating {@link de.bonndan.nivio.assessment.Assessment}s. + */ +public class AssessableGroup implements Assessable, Labeled { + + @NonNull + private final Group group; + + @NonNull + private final List items; + + public AssessableGroup(@NonNull final Group group, @NonNull final Set items) { + this.group = Objects.requireNonNull(group); + this.items = new ArrayList<>(Objects.requireNonNull(items)); + } + + @Override + @NonNull + public Set getAdditionalStatusValues() { + return StatusValue.fromMapping(getAssessmentIdentifier(), group.indexedByPrefix(Label.status)); + } + + @Override + @NonNull + public String getAssessmentIdentifier() { + return group.getFullyQualifiedIdentifier().toString(); + } + + @Override + @NonNull + public List getChildren() { + return items; + } + + @Override + public String getLabel(String key) { + return group.getLabel(key); + } + + @Override + @NonNull + public Map getLabels() { + return group.getLabels(); + } + + @Override + public void setLabel(String key, String value) { + // the decorator is not meant to be modified + } +} diff --git a/src/main/java/de/bonndan/nivio/assessment/Assessment.java b/src/main/java/de/bonndan/nivio/assessment/Assessment.java index 54d239926..568828cea 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Assessment.java +++ b/src/main/java/de/bonndan/nivio/assessment/Assessment.java @@ -1,32 +1,38 @@ package de.bonndan.nivio.assessment; import de.bonndan.nivio.assessment.kpi.AbstractKPI; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.List; import java.util.Map; /** * Result of a landscape (or group, or item) assessment using {@link AbstractKPI}s. - * - * */ public class Assessment { - private final Map> results; - private final LocalDateTime date; + private final Map> results; + private final ZonedDateTime date; - public Assessment(Map> results) { - date = LocalDateTime.now(); + public Assessment(Map> results) { + date = ZonedDateTime.now(); this.results = results; } - public Map> getResults() { + /** + * Null-object + * + * @return an empty instance + */ + public static Assessment empty() { + return new Assessment(Map.of()); + } + + public Map> getResults() { return results; } - public LocalDateTime getDate() { + public ZonedDateTime getDate() { return date; } } diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentChangedEvent.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentChangedEvent.java new file mode 100644 index 000000000..425abf03f --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentChangedEvent.java @@ -0,0 +1,42 @@ +package de.bonndan.nivio.assessment; + +import de.bonndan.nivio.input.ProcessingEvent; +import de.bonndan.nivio.model.Landscape; +import org.springframework.lang.NonNull; + +import java.util.Objects; + +public class AssessmentChangedEvent extends ProcessingEvent { + + private final Landscape landscape; + private final Assessment assessment; + + public AssessmentChangedEvent(@NonNull final Landscape landscape, @NonNull final Assessment assessment) { + super(Objects.requireNonNull(landscape).getFullyQualifiedIdentifier()); + this.landscape = landscape; + this.assessment = Objects.requireNonNull(assessment); + } + + @Override + public String getLevel() { + return ProcessingEvent.LOG_LEVEL_INFO; + } + + @Override + public String getType() { + return getClass().getSimpleName(); + } + + @Override + public String getMessage() { + return null; + } + + public Landscape getLandscape() { + return landscape; + } + + public Assessment getAssessment() { + return assessment; + } +} diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java index b8898cb0f..a2c24f4b7 100644 --- a/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentController.java @@ -32,7 +32,7 @@ public ResponseEntity landscape(@PathVariable String identifier) { var optionalAssessment = assessmentRepository.getAssessment(fqi); if (optionalAssessment.isEmpty()) { - return new ResponseEntity<>(assessmentRepository.createAssessment(landscape), HttpStatus.OK); + return new ResponseEntity<>(assessmentRepository.getAssessment(landscape.getFullyQualifiedIdentifier()).orElse(Assessment.empty()), HttpStatus.OK); } else { return new ResponseEntity<>(optionalAssessment.get(), HttpStatus.OK); } diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java index e25752ee7..296ad7f3b 100644 --- a/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentFactory.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.assessment; import de.bonndan.nivio.assessment.kpi.KPI; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; import de.bonndan.nivio.model.Landscape; import org.springframework.lang.NonNull; @@ -11,7 +10,8 @@ import java.util.Objects; public class AssessmentFactory { - public static final String ASSESSMENTERRORNULL = "Assessments can't be created from a null value"; + + static final String ASSESSMENT_ERROR_NULL = "Assessments can't be created from a null value"; private AssessmentFactory() { } @@ -24,23 +24,24 @@ private AssessmentFactory() { * @throws NullPointerException On null input. */ public static Assessment createAssessment(@NonNull Landscape landscape) { - var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENTERRORNULL); + var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENT_ERROR_NULL); return new Assessment(testedLandscape.applyKPIs(testedLandscape.getKpis())); } /** - * This method which generates a new from a landscape and a kpi. + * This method which generates a new assessment from a landscape and a kpi. * * @param landscape used to generate the new Assessment. * @param kpis external kpi used to get status values. * @return Assessment * @throws NullPointerException On null input. */ - public static Assessment createAssessment(@NonNull Landscape landscape, @NonNull Map kpis) { - var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENTERRORNULL); - var testedKpis = Objects.requireNonNull(kpis, ASSESSMENTERRORNULL); - var map = new HashMap>(); - testedKpis.forEach((k, v) -> map.putIfAbsent(FullyQualifiedIdentifier.from(k), v.getStatusValues(testedLandscape))); + @NonNull + public static Assessment createAssessment(@NonNull final Landscape landscape, @NonNull Map kpis) { + var testedLandscape = Objects.requireNonNull(landscape, ASSESSMENT_ERROR_NULL); + var testedKpis = Objects.requireNonNull(kpis, ASSESSMENT_ERROR_NULL); + var map = new HashMap>(); + testedKpis.forEach((k, v) -> map.putIfAbsent(k, v.getStatusValues(testedLandscape))); return new Assessment(map); } @@ -51,9 +52,9 @@ public static Assessment createAssessment(@NonNull Landscape landscape, @NonNull * @return Assessment * @throws NullPointerException On null input. */ - public static Assessment createAssessment(@NonNull Map> results) { - var testedResult = Objects.requireNonNull(results, ASSESSMENTERRORNULL); - return new Assessment(testedResult); + @NonNull + public static Assessment createAssessment(@NonNull Map> results) { + return new Assessment(Objects.requireNonNull(results, ASSESSMENT_ERROR_NULL)); } diff --git a/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java b/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java index d500c1e32..cd2aaff6c 100644 --- a/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java +++ b/src/main/java/de/bonndan/nivio/assessment/AssessmentRepository.java @@ -1,14 +1,13 @@ package de.bonndan.nivio.assessment; import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import de.bonndan.nivio.model.Landscape; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Component; -import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; /** * Stores and loads and creates Assessments with FullyQualifiedIdentifier as key @@ -16,30 +15,34 @@ @Component public class AssessmentRepository { - private final HashMap repository; + private final Map repository; public AssessmentRepository() { - repository = new HashMap<>(); + repository = new ConcurrentHashMap<>(); } public void clean() { repository.clear(); } + /** + * Returns the current assessment for the landscape. + * + * @param fullyQualifiedIdentifier landscape identifier + * @return an assessment if present + */ @NonNull - public Assessment createAssessment(@NonNull Landscape landscape) { - var testedLandscape = Objects.requireNonNull(landscape, "Assessments can't be created from a null value"); - var newAssessment = AssessmentFactory.createAssessment(testedLandscape); - storeAssessment(testedLandscape.getFullyQualifiedIdentifier(), newAssessment); - return newAssessment; + public Optional getAssessment(@NonNull final FullyQualifiedIdentifier fullyQualifiedIdentifier) { + return Optional.ofNullable(repository.get(Objects.requireNonNull(fullyQualifiedIdentifier, "Null instead of FQI given"))); } - public Optional getAssessment(@Nullable FullyQualifiedIdentifier fullyQualifiedIdentifier) { - return Optional.ofNullable(repository.get(fullyQualifiedIdentifier)); + /** + * Saves the given assessment + * + * @param fqi landscape identifier + * @param assessment assessment + */ + public void save(@NonNull final FullyQualifiedIdentifier fqi, @NonNull final Assessment assessment) { + repository.put(fqi, assessment); } - - private void storeAssessment(@NonNull FullyQualifiedIdentifier fullyQualifiedIdentifier, @NonNull Assessment assessment) { - repository.put(fullyQualifiedIdentifier, assessment); - } - } diff --git a/src/main/java/de/bonndan/nivio/assessment/ProcessingEventListener.java b/src/main/java/de/bonndan/nivio/assessment/ProcessingEventListener.java new file mode 100644 index 000000000..c5622f63d --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/ProcessingEventListener.java @@ -0,0 +1,33 @@ +package de.bonndan.nivio.assessment; + +import de.bonndan.nivio.input.ProcessingFinishedEvent; +import de.bonndan.nivio.model.Landscape; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +/** + * Creates a new assessment after a {@link ProcessingFinishedEvent} + * + * + */ +@Component +public class ProcessingEventListener { + + private final AssessmentRepository repository; + private final ApplicationEventPublisher publisher; + + public ProcessingEventListener(final AssessmentRepository repository, final ApplicationEventPublisher publisher) { + this.repository = repository; + this.publisher = publisher; + } + + @EventListener(ProcessingFinishedEvent.class) + public void onProcessingFinishedEvent(final ProcessingFinishedEvent processingEvent) { + Landscape landscape = processingEvent.getLandscape(); + Assessment assessment = AssessmentFactory.createAssessment(landscape); + repository.save(landscape.getFullyQualifiedIdentifier(), assessment); + publisher.publishEvent(new AssessmentChangedEvent(landscape, assessment)); + } + +} diff --git a/src/main/java/de/bonndan/nivio/assessment/Status.java b/src/main/java/de/bonndan/nivio/assessment/Status.java index ddefb5f6e..34cb46c1c 100644 --- a/src/main/java/de/bonndan/nivio/assessment/Status.java +++ b/src/main/java/de/bonndan/nivio/assessment/Status.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonValue; import org.springframework.util.StringUtils; +import java.util.Objects; + public enum Status { UNKNOWN("grey", 0), @@ -13,11 +15,11 @@ public enum Status { RED("red", 4), BROWN("brown", 5); - private final String status; + private final String statusName; private final int order; Status(String status, int order) { - this.status = status; + this.statusName = status; this.order = order; } @@ -49,11 +51,14 @@ public String getName() { @Override public String toString() { - return status; + return statusName; } - public boolean isHigherThan(Status current) { - return order > current.order; + public static class Comparator implements java.util.Comparator { + public int compare(Status s1, Status s2) { + if (Objects.requireNonNull(s1).order > Objects.requireNonNull(s2).order) return 1; + if (s1.equals(s2)) return 0; + return -1; + } } - } diff --git a/src/main/java/de/bonndan/nivio/assessment/StatusValue.java b/src/main/java/de/bonndan/nivio/assessment/StatusValue.java index df7d1d303..f224791c5 100644 --- a/src/main/java/de/bonndan/nivio/assessment/StatusValue.java +++ b/src/main/java/de/bonndan/nivio/assessment/StatusValue.java @@ -6,18 +6,22 @@ import org.springframework.util.StringUtils; import java.util.*; +import java.util.stream.Collectors; /** * One specific property/kpi/key ... carrying a status. - *

+ * * Status (see {@link Status}) is an ordered set of status represented as colors */ @JsonInclude(JsonInclude.Include.NON_NULL) public class StatusValue { - public static final String SUMMARY_LABEL = "summary"; public static final String LABEL_SUFFIX_STATUS = "status"; public static final String LABEL_SUFFIX_MESSAGE = "message"; + public static final String SUMMARY_FIELD_VALUE = "summary"; + + @NonNull + private final String identifier; @NonNull private final String field; @@ -28,10 +32,8 @@ public class StatusValue { @Nullable private final String message; - private final boolean summary; + private boolean summary; - @Nullable - private final String maxField; /** * Turns a map of strings indexed by (KPI-)field into StatusValue objects. @@ -46,11 +48,12 @@ public class StatusValue { * @return derived StatusValues */ @NonNull - public static Set fromMapping(Map> valuesByKey) { + public static Set fromMapping(@NonNull final String identifier, @NonNull final Map> valuesByKey) { Set statusValues = new HashSet<>(); valuesByKey.forEach((key, stringStringMap) -> { StatusValue value = new StatusValue( + identifier, key, Status.from(stringStringMap.get(LABEL_SUFFIX_STATUS)), stringStringMap.get(LABEL_SUFFIX_MESSAGE) @@ -63,60 +66,54 @@ public static Set fromMapping(Map> valu /** * Creates a summary status value. * - * @param fieldName composed field name - * @param maxValue max/highest status value + * @param identifier assessment identifier (e.g. item fqi) + * @param maxValues max/highest status values * @return summary */ @NonNull - public static StatusValue summary(@NonNull String fieldName, @NonNull StatusValue maxValue) { - if (StringUtils.isEmpty(fieldName)) { - throw new IllegalArgumentException("Status value has no field name."); - } - if (StringUtils.isEmpty(maxValue)) { - throw new IllegalArgumentException("Status value has no max status value."); - } - return new StatusValue(fieldName, maxValue.getStatus(), maxValue.getMessage(), maxValue.getField()); + public static StatusValue summary(@NonNull final String identifier, @NonNull final List maxValues) { + Status status = maxValues.stream().findFirst().map(StatusValue::getStatus).orElse(Status.UNKNOWN); + + //skipping the child summaries + String message = maxValues.stream() + .filter(statusValue -> !statusValue.summary) + .map(statusValue -> String.format("%s %s: %s", statusValue.getIdentifier(), statusValue.getField(), statusValue.getMessage())) + .collect(Collectors.joining("; ")); + StatusValue statusValue = new StatusValue(identifier, SUMMARY_FIELD_VALUE, status, message); + statusValue.summary = true; + return statusValue; } /** * New StatusValue with message. * - * @param field field / label name - * @param status current status - * @param message additional message + * @param identifier assessment identifier (e.g. item fqi) + * @param field field / label name + * @param status current status + * @param message additional message */ - public StatusValue(@NonNull String field, @Nullable Status status, @Nullable String message) { - if (StringUtils.isEmpty(field)) { - throw new IllegalArgumentException("Status value has no field"); + public StatusValue(@NonNull final String identifier, + @NonNull final String field, + @Nullable final Status status, + @Nullable final String message + ) { + if (!StringUtils.hasLength(identifier)) { + throw new IllegalArgumentException("Assessment identifier is empty"); } - this.field = field; - - if (status == null) { - status = Status.UNKNOWN; - } - this.status = status; - this.message = message; - this.summary = false; - this.maxField = null; - } - - private StatusValue(String field, Status status, String message, String maxField) { - if (StringUtils.isEmpty(field)) { + if (!StringUtils.hasLength(field)) { throw new IllegalArgumentException("Status value has no field"); } - this.field = field; - if (status == null) { - status = Status.UNKNOWN; - } - this.status = status; + this.identifier = identifier; + this.field = field; + this.status = status == null ? Status.UNKNOWN : status; this.message = message; - this.summary = true; - this.maxField = status != Status.UNKNOWN ? maxField : null; + this.summary = false; } - public StatusValue(@NonNull String field, @Nullable Status status) { - this(field, status, null); + @NonNull + public String getIdentifier() { + return identifier; } @NonNull @@ -141,20 +138,15 @@ public boolean isSummary() { @Override public boolean equals(Object obj) { if (obj instanceof StatusValue) { - return field.equals(((StatusValue) obj).field); + StatusValue other = (StatusValue) obj; + return identifier.equalsIgnoreCase(other.identifier) && field.equalsIgnoreCase(other.field); } return false; } - public String getMaxField() { - return maxField; - } - public static class Comparator implements java.util.Comparator { public int compare(StatusValue s1, StatusValue s2) { - if (Objects.requireNonNull(s1.status).isHigherThan(Objects.requireNonNull(s2.status))) return 1; - if (s1.status.equals(s2.status)) return 0; - return -1; + return Objects.requireNonNull(s1.status).compareTo(Objects.requireNonNull(s2.status)); } } @@ -166,11 +158,11 @@ public int hashCode() { @Override public String toString() { return "StatusValue{" + - "field='" + field + '\'' + + "identifier='" + identifier + '\'' + + ", field='" + field + '\'' + ", status=" + status + ", message='" + message + '\'' + ", summary=" + summary + - ", maxField='" + maxField + '\'' + '}'; } } \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java index 34e0efb4c..2f878c1a6 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/AbstractKPI.java @@ -1,7 +1,7 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.StatusValue; -import de.bonndan.nivio.model.Component; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -15,23 +15,23 @@ public abstract class AbstractKPI implements KPI { protected String messageTemplate = "%s"; - private String description; + protected String description; private boolean enabled = true; - protected Function valueFunction; + protected Function valueFunction; @NonNull - protected Function msgFunction = component -> String.format(messageTemplate, valueFunction.apply(component)); + protected Function msgFunction = component -> String.format(messageTemplate, valueFunction.apply(component)); - public AbstractKPI() { + protected AbstractKPI() { } /** * @param valueFunction a function returning the value to assess * @param msgFunction a function returning the status message */ - public AbstractKPI(@NonNull Function valueFunction, - @Nullable Function msgFunction + public AbstractKPI(@NonNull Function valueFunction, + @Nullable Function msgFunction ) { this.valueFunction = Objects.requireNonNull(valueFunction); if (msgFunction != null) { @@ -46,24 +46,25 @@ public AbstractKPI(@NonNull Function valueFunction, * @return current status value, unknown if not present */ @NonNull - public List getStatusValues(Component component) { + public List getStatusValues(Assessable component) { if (valueFunction == null) { - throw new RuntimeException("Value function not initialized "); + throw new IllegalStateException("Value function not initialized."); } String value = valueFunction.apply(component); String message = msgFunction.apply(component); - return getStatusValues(value, message); + return getStatusValues(component, value, message); } /** * Returns the status values * + * @param assessable to assess * @param value the value to assess. Can be null if no value is present or the KPI is not applicable. * @param message the optional message * @return a status value if assessed */ - protected abstract List getStatusValues(@Nullable String value, @Nullable String message); + protected abstract List getStatusValues(@NonNull final Assessable assessable, @Nullable final String value, @Nullable final String message); @Override public String getDescription() { diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java index bf8904776..af8a47f8c 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ConditionKPI.java @@ -1,47 +1,55 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; -import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.output.dto.RangeApiModel; +import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Evaluates the "condition.*" labels, see {@link InputFormatHandlerKubernetes} * - * this is similiar to the {@link HealthKPI}, it only works on a different field. + * this is similar to the {@link HealthKPI}, it only works on a different field. */ public class ConditionKPI implements KPI { public static final String IDENTIFIER = "condition"; + private static final Map> matches = new LinkedHashMap<>(); + + static { + matches.put(Status.RED, List.of("one condition is not met")); + matches.put(Status.GREEN, List.of("all conditions are met")); + } + private boolean enabled = true; @Override - public List getStatusValues(Component component) { - if (!(component instanceof Labeled)) + @NonNull + public List getStatusValues(Assessable component) { + if (!(component instanceof Labeled)) { return new ArrayList<>(); + } var status = Status.UNKNOWN; var message = ""; - for (Map.Entry entry : ((Labeled) component).getLabels(Label.condition).entrySet()) { + for (Map.Entry entry : ((Labeled) component).getLabels(Label._condition).entrySet()) { String key = entry.getKey(); String flag = entry.getValue(); - if (StringUtils.isEmpty(flag)) + if (!StringUtils.hasLength(flag)) continue; - if (flag.toLowerCase().equals("false")) { + if (flag.equalsIgnoreCase("false")) { status = Status.RED; message = key; } - if (flag.toLowerCase().equals("true") && !status.equals(Status.RED)) { + if (flag.equalsIgnoreCase("true") && !status.equals(Status.RED)) { status = Status.GREEN; message = key; } @@ -50,7 +58,7 @@ public List getStatusValues(Component component) { if (Status.UNKNOWN.equals(status)) { return new ArrayList<>(); } - return Collections.singletonList(new StatusValue(IDENTIFIER, status, message)); + return Collections.singletonList(new StatusValue(component.getAssessmentIdentifier(), IDENTIFIER, status, message)); } @Override @@ -63,6 +71,16 @@ public boolean isEnabled() { return enabled; } + @Override + public Map getRanges() { + return null; + } + + @Override + public Map> getMatches() { + return sorted(matches); + } + public void setEnabled(boolean enabled) { this.enabled = enabled; } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java index 6cabba353..f97d2043b 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/CustomKPI.java @@ -1,12 +1,17 @@ package de.bonndan.nivio.assessment.kpi; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.output.dto.RangeApiModel; import org.apache.commons.lang3.Range; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import java.util.*; @@ -20,6 +25,8 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class CustomKPI extends AbstractKPI { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomKPI.class); + public static final String SEPARATOR = ";"; /** @@ -30,14 +37,17 @@ public class CustomKPI extends AbstractKPI { /** * For each {@link Status} a set of regular expressions can be defined which indicate the status. */ - private final Map>> matches = new HashMap<>(); + private final Map>> matchSpecs = new HashMap<>(); protected String label; + protected Map> matchers; + /** * */ public CustomKPI() { + //required for deserialization } @Override @@ -47,10 +57,14 @@ public void init(KPIConfig kpiConfig) { if (kpiConfig.label != null) { label = kpiConfig.label; } + if (kpiConfig.description != null) { + description = kpiConfig.description; + } this.setEnabled(kpiConfig.enabled); if (!StringUtils.isEmpty(kpiConfig.messageTemplate)) { messageTemplate = kpiConfig.messageTemplate; } + ranges = asRanges(kpiConfig.label, kpiConfig.ranges); addSpecsFromConfig(kpiConfig.matches); } @@ -59,31 +73,31 @@ public void init(KPIConfig kpiConfig) { if (component instanceof Labeled) { return ((Labeled) component).getLabel(label); } - throw new RuntimeException("Custom KPIs can only evaluate labels (custom fields)."); + LOGGER.error("Custom KPIs can only evaluate labels (custom fields)."); + return null; }; - } @Override - protected List getStatusValues(@Nullable String value, @Nullable String message) { + protected List getStatusValues(@NonNull final Assessable assessable, @Nullable String value, @Nullable String message) { List values = new ArrayList<>(); for (Status status : Status.values()) { Optional statusByRange = getStatusByRange(value); if (statusByRange.isPresent()) { - values.add(new StatusValue(label, statusByRange.get(), message)); + values.add(new StatusValue(assessable.getAssessmentIdentifier(), label, statusByRange.get(), message)); break; } - if (!matches.containsKey(status)) { + if (!matchSpecs.containsKey(status)) { continue; } - boolean anyMatch = false; + var anyMatch = false; if (value != null) { - anyMatch = matches.get(status).stream().anyMatch(stringBooleanFunction -> stringBooleanFunction.apply(value)); + anyMatch = matchSpecs.get(status).stream().anyMatch(stringBooleanFunction -> stringBooleanFunction.apply(value)); } if (anyMatch) { - values.add(new StatusValue(label, status, message)); + values.add(new StatusValue(assessable.getAssessmentIdentifier(), label, status, message)); break; } } @@ -91,6 +105,19 @@ protected List getStatusValues(@Nullable String value, @Nullable St return values; } + @Override + public Map getRanges() { + if (ranges == null) return null; + return sorted( + ranges.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> new RangeApiModel(entry.getValue()))) + ); + } + + @Override + public Map> getMatches() { + return sorted(matchers); + } + protected Map> asRanges(String label, Map ranges) { Map> rangeMap = new HashMap<>(); if (ranges == null) { @@ -136,8 +163,8 @@ protected void addSpecsFromConfig(@Nullable Map input) { Map statusPatterns = new HashMap<>(); if (input != null) { input.forEach((s, s2) -> statusPatterns.put(Status.from(s), s2)); - addSpecs(statusPatterns); } + addSpecs(statusPatterns); } protected void addSpecs(@Nullable Map statusPatterns) { @@ -145,17 +172,24 @@ protected void addSpecs(@Nullable Map statusPatterns) { return; } - statusPatterns.forEach((status, strings) -> { - List> specs = Arrays.stream(strings.split(SEPARATOR)).map(s -> { + Map> matchersPerStatus = statusPatterns.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + e -> Arrays.asList(e.getValue().split(SEPARATOR)) + )); + + matchersPerStatus.forEach((status, strings) -> { + List> specs = strings.stream().map(s -> { try { - Pattern p = Pattern.compile(s, Pattern.CASE_INSENSITIVE); + var p = Pattern.compile(s, Pattern.CASE_INSENSITIVE); return (Function) s1 -> p.matcher(s1).matches(); } catch (Exception e) { throw new ProcessingException(String.format("Failed to initialize KPI %s matcher pattern ", this.label), e); } }).collect(Collectors.toList()); - matches.put(status, specs); + matchSpecs.put(status, specs); }); + + this.matchers = matchersPerStatus; } } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java index b013f0e81..bd10ef4b4 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/HealthKPI.java @@ -20,6 +20,11 @@ public class HealthKPI extends CustomKPI { Status.RED, UNHEALTHY ); + @Override + public String getDescription() { + return "Evaluates the 'health' label values healthy and unhealthy."; + } + public HealthKPI() { super(); label = Label.health.name(); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java index 9fee4a023..cf1b3f335 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPI.java @@ -1,36 +1,44 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; +import com.fasterxml.jackson.annotation.JsonInclude; +import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Component; +import de.bonndan.nivio.output.dto.RangeApiModel; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import java.util.List; +import java.util.Map; +import java.util.TreeMap; /** * Key Performance Indicator * * Used to evaluate {@link Component}s. */ +@JsonInclude(JsonInclude.Include.NON_NULL) public interface KPI { /** * Controlled initialisation. * - * @throws ProcessingException if initialisation fails (eg regex compiling) * @param kpiConfig optional config + * @throws ProcessingException if initialisation fails (eg regex compiling) */ - default void init(@Nullable KPIConfig kpiConfig) {} + default void init(@Nullable KPIConfig kpiConfig) { + } /** * Returns the status evaluation of the component on the configured field. * - * @param component to assess + * @param assessable to assess * @return current status value, unknown if not present */ @NonNull - List getStatusValues(Component component); + List getStatusValues(Assessable assessable); /** * Describes the meaning of the KPI. @@ -43,4 +51,28 @@ default void init(@Nullable KPIConfig kpiConfig) {} * @return true if active */ boolean isEnabled(); + + /** + * Returns the calculated range for the statuses for the API. + * + * @return ranges if present, sorted from best to worst, otherwise null + */ + @Nullable + Map getRanges(); + + /** + * Returns the calculated matches for the statuses for the API. + * + * @return ranges if present, sorted from best to worst, otherwise null + */ + @Nullable + Map> getMatches(); + + @Nullable + default Map sorted(@Nullable final Map inner) { + if (inner == null) return null; + var sorted = new TreeMap(new Status.Comparator()); + inner.forEach(sorted::put); + return sorted; + } } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java index cb95ac529..8dbaafc12 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIConfig.java @@ -34,7 +34,7 @@ public class KPIConfig { example = "RED: BAD;err.*") public Map matches = new HashMap<>(); - @Schema(description = "A flag indicating that the KPI is active. Can be used to disable default kpis.") + @Schema(description = "A flag indicating that the KPI is active. Can be used to disable default KPIs.") public boolean enabled = true; } diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java index 5383def88..cc293922e 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KPIFactory.java @@ -24,6 +24,7 @@ public KPIFactory() { defaultKPIs.put(ScalingKPI.IDENTIFIER, ScalingKPI::new); defaultKPIs.put(ConditionKPI.IDENTIFIER, ConditionKPI::new); defaultKPIs.put(LifecycleKPI.IDENTIFIER, LifecycleKPI::new); + defaultKPIs.put(KubernetesKPI.IDENTIFIER, KubernetesKPI::new); } /** @@ -35,7 +36,7 @@ public KPIFactory() { */ public Map getConfiguredKPIs(@NonNull Map kpiConfigMap) { - Objects.requireNonNull(kpiConfigMap, "kpi config is null"); + Objects.requireNonNull(kpiConfigMap, "KPI config is null"); Map kpis = new HashMap<>(defaultKPIs.size() + kpiConfigMap.size()); defaultKPIs.forEach((s, kpiSupplier) -> kpis.put(s, kpiSupplier.get())); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java new file mode 100644 index 000000000..ca93f9358 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/KubernetesKPI.java @@ -0,0 +1,111 @@ +package de.bonndan.nivio.assessment.kpi; + +import de.bonndan.nivio.assessment.Assessable; +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.assessment.StatusValue; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.output.dto.RangeApiModel; +import org.apache.commons.collections.map.SingletonMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; +import org.springframework.util.ObjectUtils; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class KubernetesKPI implements KPI { + private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesKPI.class); + public static final String IDENTIFIER = "k8s"; + private boolean enabled = true; + + @Override + @NonNull + public List getStatusValues(Assessable assessable) { + if (!(assessable instanceof Labeled)) { + return new ArrayList<>(); + } + var statusList = new ArrayList(); + var counter = new AtomicInteger(0); + ((Labeled) assessable).getLabels(InputFormatHandlerKubernetes.LABEL_PREFIX).forEach((key, value) -> { + if (ObjectUtils.isEmpty(value)) { + return; + } + StatusValue statusValue; + var message = key.replaceFirst(InputFormatHandlerKubernetes.LABEL_PREFIX + ".", ""); + if (message.startsWith("boolcondition.")) { + message = message.replaceFirst("boolcondition.", ""); + statusValue = new StatusValue(assessable.getAssessmentIdentifier(), IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(boolCondition(value)), message); + } else if (message.startsWith("replicacondition.")) { + var splitValue = value.split(";"); + var replicaCount = getIntegerValue(splitValue, 0); + var replicaCountDesired = getIntegerValue(splitValue, 1); + var replicaCondition = replicaCondition(replicaCount, replicaCountDesired); + statusValue = new StatusValue(assessable.getAssessmentIdentifier(), IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(String.valueOf(replicaCondition.getValue())), String.valueOf(replicaCondition.getKey())); + } else { + statusValue = new StatusValue(assessable.getAssessmentIdentifier(), IDENTIFIER + ":" + counter.getAndIncrement(), Status.from(value), message); + } + statusList.add(statusValue); + }); + return statusList; + } + + private Integer getIntegerValue(String[] splitValue, int position) { + try { + return Integer.parseInt(splitValue[position]); + } catch (NumberFormatException e) { + LOGGER.warn(e.getMessage()); + } + return null; + } + + private String boolCondition(String flag) { + if (flag.toLowerCase(Locale.ROOT).equals("true")) { + return de.bonndan.nivio.assessment.Status.GREEN.toString(); + } else { + return de.bonndan.nivio.assessment.Status.RED.toString(); + } + } + + private SingletonMap replicaCondition(Integer replicaCount, Integer replicaCountDesired) { + var message = String.format("%s of %s Pods are ready", replicaCount, replicaCountDesired); + if (replicaCount == null) { + return new SingletonMap("ReadyReplicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); + } + if (replicaCountDesired == null) { + return new SingletonMap("Replicas count was null", de.bonndan.nivio.assessment.Status.ORANGE.toString()); + } + if (Objects.equals(replicaCount, replicaCountDesired)) { + return new SingletonMap("all pods are ready", de.bonndan.nivio.assessment.Status.GREEN.toString()); + } + if (replicaCount == 0) { + return new SingletonMap(message, de.bonndan.nivio.assessment.Status.RED.toString()); + } + return new SingletonMap(message, de.bonndan.nivio.assessment.Status.YELLOW.toString()); + } + + @Override + public String getDescription() { + return "Evaluates Kubernetes conditions."; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public Map getRanges() { + return Map.of(); + } + + @Override + public Map> getMatches() { + return Map.of(); + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java index a61b3a2e5..bc0182e5f 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/LifecycleKPI.java @@ -1,9 +1,11 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Lifecycle; +import org.springframework.lang.NonNull; import java.util.*; @@ -18,20 +20,25 @@ public LifecycleKPI() { super(); label = Label.lifecycle.name(); msgFunction = component -> Optional.ofNullable(Lifecycle.from(valueFunction.apply(component))) - .map(lifecycle -> "Phase: " + lifecycle.name().toLowerCase(Locale.ROOT).replace("_", " ")) + .map(lifecycle -> "phase: " + lifecycle.name().toLowerCase(Locale.ROOT).replace("_", " ")) .orElse("unknown"); - setDescription("This KPI evaluates the lifecycle label for known values (PLANNED, PRODUCTION)."); + matchers = Map.of( + Status.GREEN, List.of(Lifecycle.PRODUCTION.name()), + Status.ORANGE, List.of(Lifecycle.END_OF_LIFE.name()) + ); + + setDescription("Evaluates the lifecycle label for known values (e.g. PLANNED, PRODUCTION, etc.)."); } @Override - protected List getStatusValues(String value, String message) { - Lifecycle lifecycle = Lifecycle.from(value); + protected List getStatusValues(@NonNull final Assessable assessable, String value, String message) { + var lifecycle = Lifecycle.from(value); if (Lifecycle.PRODUCTION.equals(lifecycle)) { - return Collections.singletonList(new StatusValue(Label.lifecycle.name(), Status.GREEN, message)); + return Collections.singletonList(new StatusValue(assessable.getAssessmentIdentifier(), Label.lifecycle.name(), Status.GREEN, message)); } if (Lifecycle.END_OF_LIFE.equals(lifecycle)) { - return Collections.singletonList(new StatusValue(Label.lifecycle.name(), Status.ORANGE, message)); + return Collections.singletonList(new StatusValue(assessable.getAssessmentIdentifier(), Label.lifecycle.name(), Status.ORANGE, message)); } return new ArrayList<>(); diff --git a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java index 4356b2a8e..8129092bc 100644 --- a/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java +++ b/src/main/java/de/bonndan/nivio/assessment/kpi/ScalingKPI.java @@ -1,17 +1,21 @@ package de.bonndan.nivio.assessment.kpi; +import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; -import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.RelationType; +import de.bonndan.nivio.output.dto.RangeApiModel; +import org.apache.commons.lang3.Range; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import java.util.Collections; import java.util.List; +import java.util.Map; /** * This KPI evaluates the scale label and tries to find bottlenecks where providers for many items are down or not scaled. @@ -30,9 +34,21 @@ public class ScalingKPI extends AbstractKPI { private static final Logger LOGGER = LoggerFactory.getLogger(ScalingKPI.class); public static final String SCALED_TO_ZERO = "scaled to zero"; + private final Map ranges = Map.of( + Status.GREEN, new RangeApiModel(Range.between(1D, Double.POSITIVE_INFINITY)), + Status.YELLOW, new RangeApiModel(Range.between(0D, 0D), SCALED_TO_ZERO), + Status.ORANGE, new RangeApiModel(Range.between(0D, 0D), "data sink scaled to zero"), + Status.RED, new RangeApiModel(Range.between(0D, 0D), "provider scaled to zero") + ); + + @Override + public String getDescription() { + return "Turns yellow if the 'scale' label is zero, orange if it is a data sink, and red if it is a provider."; + } + @NonNull @Override - public List getStatusValues(Component component) { + public List getStatusValues(Assessable component) { if (!(component instanceof Item)) { return Collections.emptyList(); @@ -53,6 +69,7 @@ private List getItemStatusValues(Item component) { String scaleLabel = component.getLabel(Label.scale); int scaleValue = -1; + String assessmentIdentifier = component.getAssessmentIdentifier(); if (scaleLabel != null) { try { scaleValue = Integer.parseInt(scaleLabel); @@ -60,13 +77,13 @@ private List getItemStatusValues(Item component) { Status status = Status.YELLOW; String message = SCALED_TO_ZERO; if (usedAsProvider > 0) { - status = Status.RED; + status = Status.RED; message += " and provider for " + usedAsProvider + " items"; } else if (usedAsDataTarget > 0) { status = Status.ORANGE; message += " and data sink for " + usedAsDataTarget + " items"; } - return List.of(new StatusValue(Label.scale.name(), status, message)); + return List.of(new StatusValue(assessmentIdentifier, Label.scale.name(), status, message)); } } catch (NumberFormatException ignored) { LOGGER.warn("Scaling KPI cannot handle label scale value '{}' of component '{}'", scaleLabel, component); @@ -74,20 +91,31 @@ private List getItemStatusValues(Item component) { } if (scaleValue == 1 && (usedAsProvider > 1)) { - return List.of(new StatusValue(Label.scale.name(), Status.YELLOW, String.format("Unscaled, but %d items depend on it.", usedAsProvider))); + return List.of(new StatusValue(assessmentIdentifier, Label.scale.name(), Status.YELLOW, String.format("unscaled, but %d items depend on it", usedAsProvider))); } if (scaleValue > 0) { - return List.of(new StatusValue(Label.scale.name(), Status.GREEN)); + return List.of(new StatusValue(assessmentIdentifier, Label.scale.name(), Status.GREEN, "")); } return Collections.emptyList(); } @Override - protected List getStatusValues(String value, String message) { + protected List getStatusValues(@NonNull final Assessable assessable, String value, String message) { //unused return Collections.emptyList(); } + @Override + @Nullable + public Map getRanges() { + return sorted(ranges); + } + + @Override + @Nullable + public Map> getMatches() { + return null; + } } diff --git a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java index b9853362e..2e1958697 100644 --- a/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java +++ b/src/main/java/de/bonndan/nivio/config/ApplicationConfig.java @@ -1,24 +1,39 @@ package de.bonndan.nivio.config; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer; import de.bonndan.nivio.input.Seed; import de.bonndan.nivio.output.icons.LocalIcons; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.lang.NonNull; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.time.ZonedDateTime; + import static de.bonndan.nivio.output.icons.LocalIcons.DEFAULT_ICONS_FOLDER; @Configuration +@EnableConfigurationProperties(SeedProperties.class) public class ApplicationConfig { + private final SeedProperties seedProperties; + + public ApplicationConfig(SeedProperties seedProperties) { + this.seedProperties = seedProperties; + } + @Bean public WebMvcConfigurer configurer() { return new WebMvcConfigurer() { @Override - public void addCorsMappings(CorsRegistry registry) { + public void addCorsMappings(@NonNull CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("*"); } }; @@ -31,7 +46,7 @@ public RestTemplate restTemplate() { @Bean public Seed seed() { - return new Seed(ConfigurableEnvVars.SEED.value()); + return new Seed(seedProperties.getSeed(), seedProperties.getDemo()); } @Bean @@ -39,4 +54,13 @@ public LocalIcons getLocalIcons(@Value("${nivio.iconFolder:" + DEFAULT_ICONS_FOL return new LocalIcons(iconsFolder); } + @Bean + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + JavaTimeModule module = new JavaTimeModule(); + module.addSerializer(ZonedDateTime.class, ZonedDateTimeSerializer.INSTANCE); + return new Jackson2ObjectMapperBuilder() + .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .modulesToInstall(module); + } + } diff --git a/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java b/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java index a7ad634cb..4006683f3 100644 --- a/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java +++ b/src/main/java/de/bonndan/nivio/config/NivioConfigProperties.java @@ -40,7 +40,7 @@ public class NivioConfigProperties { private String brandingMessage; //iconFolder: /a/local/path - + public String getBaseUrl() { return baseUrl; } @@ -105,6 +105,8 @@ public void setBrandingMessage(String brandingMessage) { this.brandingMessage = brandingMessage; } + + public ApiModel getApiModel() { java.net.URL brandingLogoUrl = null; try { @@ -124,6 +126,7 @@ public static class ApiModel { public final java.net.URL brandingLogoUrl; public final String brandingMessage; + public ApiModel(String baseUrl, String version, String brandingForeground, @@ -131,6 +134,7 @@ public ApiModel(String baseUrl, String brandingSecondary, java.net.URL brandingLogoUrl, String brandingMessage + ) { this.baseUrl = baseUrl; this.version = version; @@ -139,6 +143,7 @@ public ApiModel(String baseUrl, this.brandingSecondary = brandingSecondary; this.brandingLogoUrl = brandingLogoUrl; this.brandingMessage = brandingMessage; + } } } diff --git a/src/main/java/de/bonndan/nivio/config/SeedProperties.java b/src/main/java/de/bonndan/nivio/config/SeedProperties.java new file mode 100644 index 000000000..afea38513 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/config/SeedProperties.java @@ -0,0 +1,25 @@ +package de.bonndan.nivio.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConstructorBinding; + +@ConfigurationProperties(prefix = "nivio") +@ConstructorBinding +public class SeedProperties { + + private final String seed; + private final String demo; // add this attribute for the environment variable DEMO + + public String getSeed() { + return seed; + } + + public String getDemo(){return demo;} + + public SeedProperties(String seed, String demo) + { + this.seed = seed; + this.demo = demo; + } + +} diff --git a/src/main/java/de/bonndan/nivio/input/AppearanceProcessor.java b/src/main/java/de/bonndan/nivio/input/AppearanceProcessor.java deleted file mode 100644 index fd6b0d2ec..000000000 --- a/src/main/java/de/bonndan/nivio/input/AppearanceProcessor.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.bonndan.nivio.input; - -import de.bonndan.nivio.input.dto.LandscapeDescription; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Label; -import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.output.icons.IconService; -import de.bonndan.nivio.util.URLHelper; -import org.springframework.lang.NonNull; -import org.springframework.util.StringUtils; - -import java.util.List; -import java.util.Optional; - -/** - * Resolves color and icons for {@link de.bonndan.nivio.model.Component} - * - * Appearance must be determined after indexing, because values might be needed in api, too. - */ -public class AppearanceProcessor extends Processor { - - /** - * see https://github.com/dedica-team/nivio/issues/543 - */ - public static final List affectedLabels = List.of(Label.icon.name(), Label.fill.name(), Label.color.name()); - - private final IconService iconService; - - public AppearanceProcessor(ProcessLog processLog, IconService iconService) { - super(processLog); - this.iconService = iconService; - } - - @Override - public ProcessingChangelog process(@NonNull final LandscapeDescription input, @NonNull final Landscape landscape) { - - Optional logo = Optional.ofNullable(landscape.getConfig().getBranding().getMapLogo()); - logo.ifPresent(s -> setLandscapeLogo(landscape, s)); - - landscape.getGroupItems().forEach(group -> group.getItems().forEach(item -> setItemAppearance(group, item))); - - return new ProcessingChangelog(); - } - - private void setItemAppearance(Group group, Item item) { - - item.setLabel(Label.icon, iconService.getIconUrl(item)); - String fill = item.getLabel(Label.fill); - if (!StringUtils.isEmpty(fill)) { - URLHelper.getURL(fill) - .flatMap(iconService::getExternalUrl) - .ifPresent(s -> item.setLabel(Label.fill, s)); - } - - if (StringUtils.isEmpty(item.getColor())) { - item.setLabel(Label.color, group.getColor()); - } - } - - private void setLandscapeLogo(Landscape landscape, String logo) { - if (StringUtils.isEmpty(logo)) { - return; - } - URLHelper.getURL(logo) - .flatMap(iconService::getExternalUrl) - .ifPresent(s -> landscape.setLabel("logo", s)); - } - -} diff --git a/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java b/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java index 0f31b6333..ba1f040ef 100644 --- a/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java +++ b/src/main/java/de/bonndan/nivio/input/ComponentDescriptionValues.java @@ -52,7 +52,7 @@ public static void assignSafeNotNull(ComponentDescription component, ComponentDe assignSafeIfAbsent(increment.getOwner(), component.getOwner(), component::setOwner); assignSafeIfAbsent(increment.getContact(), component.getContact(), component::setContact); - Labeled.merge(increment, component); + Labeled.add(increment, component); increment.getLinks().entrySet().stream() .filter(entry -> !component.getLinks().containsKey(entry.getKey())) diff --git a/src/main/java/de/bonndan/nivio/input/GroupProcessor.java b/src/main/java/de/bonndan/nivio/input/GroupProcessor.java index 43763f079..e792669ea 100644 --- a/src/main/java/de/bonndan/nivio/input/GroupProcessor.java +++ b/src/main/java/de/bonndan/nivio/input/GroupProcessor.java @@ -80,7 +80,7 @@ public ProcessingChangelog process(@NonNull final LandscapeDescription input, @N landscape.getItems().all().forEach(item -> { Optional group = landscape.getGroup(item.getGroup()); if (group.isPresent()) { - group.get().addItem(item); + group.get().addOrReplaceItem(item); return; } if (isBlacklisted(item.getGroup(), specs)) { diff --git a/src/main/java/de/bonndan/nivio/input/Hint.java b/src/main/java/de/bonndan/nivio/input/Hint.java index 7e4d7f564..b08016d6e 100644 --- a/src/main/java/de/bonndan/nivio/input/Hint.java +++ b/src/main/java/de/bonndan/nivio/input/Hint.java @@ -70,7 +70,7 @@ public void use(ItemDescription item, ItemDescription target, Optional { RelationDescription relation = createRelation(item, target); - item.addRelation(relation); + item.addOrReplaceRelation(relation); return relation; }); diff --git a/src/main/java/de/bonndan/nivio/input/Indexer.java b/src/main/java/de/bonndan/nivio/input/Indexer.java index ce8d2cba8..03eaec8a2 100644 --- a/src/main/java/de/bonndan/nivio/input/Indexer.java +++ b/src/main/java/de/bonndan/nivio/input/Indexer.java @@ -6,7 +6,6 @@ import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.model.LandscapeFactory; import de.bonndan.nivio.model.LandscapeRepository; -import de.bonndan.nivio.output.icons.IconService; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; @@ -20,19 +19,16 @@ public class Indexer { private final InputFormatHandlerFactory formatFactory; private final LinkHandlerFactory linkHandlerFactory; private final ApplicationEventPublisher eventPublisher; - private final IconService iconService; public Indexer(LandscapeRepository landscapeRepository, InputFormatHandlerFactory formatFactory, LinkHandlerFactory linkHandlerFactory, - ApplicationEventPublisher eventPublisher, - IconService iconService + ApplicationEventPublisher eventPublisher ) { this.landscapeRepo = landscapeRepository; this.formatFactory = formatFactory; this.linkHandlerFactory = linkHandlerFactory; this.eventPublisher = eventPublisher; - this.iconService = iconService; } /** @@ -111,9 +107,6 @@ private ProcessingChangelog runResolvers(LandscapeDescription input, Landscape l // create relations between items changelog.merge(new ItemRelationProcessor(logger).process(input, landscape)); - // ensures that items have a resolved icon in the api - new AppearanceProcessor(logger, iconService).process(input, landscape); - return changelog; } diff --git a/src/main/java/de/bonndan/nivio/input/IndexingDispatcher.java b/src/main/java/de/bonndan/nivio/input/IndexingDispatcher.java index d45897f94..fa3f043e2 100644 --- a/src/main/java/de/bonndan/nivio/input/IndexingDispatcher.java +++ b/src/main/java/de/bonndan/nivio/input/IndexingDispatcher.java @@ -2,7 +2,6 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.util.URLHelper; import org.springframework.context.ApplicationEventPublisher; import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; @@ -55,7 +54,6 @@ public LandscapeDescription fromIncoming(@NonNull final Landscape existing) { LandscapeDescription dto = existing.getSource().getURL() .map(landscapeDescriptionFactory::from) .orElseGet(() -> landscapeDescriptionFactory.fromString(existing.getSource().getStaticSource(), existing.getIdentifier() + " source")); - IndexEvent event = new IndexEvent(dto, "index landscape"); publisher.publishEvent(event); return dto; diff --git a/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java b/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java index a3f32174d..8873df0b8 100644 --- a/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java +++ b/src/main/java/de/bonndan/nivio/input/InputFormatHandler.java @@ -2,7 +2,9 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.observation.InputFormatObserver; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -28,16 +30,22 @@ public interface InputFormatHandler { * @param baseUrl parent config url * @param landscapeDescription the input dto to modify */ - void applyData(SourceReference reference, @Nullable URL baseUrl, LandscapeDescription landscapeDescription); + void applyData(@NonNull final SourceReference reference, @Nullable URL baseUrl, LandscapeDescription landscapeDescription); /** * Returns an observer for the source reference. * - * @param inner an observer for files or urls + * @param eventPublisher the event publisher to notify + * @param landscape the current landscape * @param sourceReference the {@link SourceReference} to observe * @return observer that can handle the format or null if no observer is available */ @Nullable - InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, @NonNull final SourceReference sourceReference); + default InputFormatObserver getObserver(@NonNull final ApplicationEventPublisher eventPublisher, + @NonNull final Landscape landscape, + @NonNull final SourceReference sourceReference + ) { + return null; + } } diff --git a/src/main/java/de/bonndan/nivio/input/InstantItemResolver.java b/src/main/java/de/bonndan/nivio/input/InstantItemResolver.java index 9b994d40d..39bb168d6 100644 --- a/src/main/java/de/bonndan/nivio/input/InstantItemResolver.java +++ b/src/main/java/de/bonndan/nivio/input/InstantItemResolver.java @@ -46,9 +46,13 @@ private List resolveTargets(ItemDescription description, ItemIn //other relations description.getRelations().forEach(rel -> { //inverse links, e.g. from docker compose + if (rel.getTarget() == null) { + processLog.warn("Found relation " + rel + " without target"); + return; + } String target = rel.getTarget().equalsIgnoreCase(description.getIdentifier()) ? rel.getSource() : rel.getTarget(); - if (!StringUtils.isEmpty(target) && !hasTarget(target.toLowerCase(), allItems)) { + if (StringUtils.hasLength(target) && !hasTarget(target.toLowerCase(), allItems)) { processLog.info(description + ": creating a new target item '" + target.toLowerCase() + "' instantly."); newItems.add(createItem(rel.getTarget())); } diff --git a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java index 70bd70b2d..02b1fc1c7 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java +++ b/src/main/java/de/bonndan/nivio/input/ItemDescriptionValues.java @@ -1,8 +1,12 @@ package de.bonndan.nivio.input; import de.bonndan.nivio.input.dto.ItemDescription; +import de.bonndan.nivio.input.dto.RelationDescription; +import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; +import java.util.Objects; + import static de.bonndan.nivio.util.SafeAssign.assignSafe; import static de.bonndan.nivio.util.SafeAssign.assignSafeIfAbsent; @@ -27,7 +31,7 @@ public static void assignNotNull(ItemDescription existing, ItemDescription incre if (increment.getAddress() != null) existing.setAddress(increment.getAddress()); - assignSafe(increment.getRelations(), (rel) -> rel.forEach(existing::addRelation)); + increment.getRelations().forEach(existing::addOrReplaceRelation); assignSafe(increment.getInterfaces(), (set) -> set.forEach(intf -> existing.getInterfaces().add(intf))); } @@ -35,10 +39,14 @@ public static void assignNotNull(ItemDescription existing, ItemDescription incre /** * Writes the values of the template (second object) to the first where first is null. * - * @param target target + * @param target target * @param source source */ - public static void assignSafeNotNull(ItemDescription target, ItemDescription source) { + public static void assignSafeNotNull(@NonNull final ItemDescription target, @NonNull final ItemDescription source) { + + if (Objects.requireNonNull(source) == Objects.requireNonNull(target)) { + return; + } ComponentDescriptionValues.assignSafeNotNull(target, source); @@ -53,7 +61,7 @@ public static void assignSafeNotNull(ItemDescription target, ItemDescription sou .forEach(s -> target.getProvidedBy().add(s)); } - source.getRelations().forEach(target::addRelation); + source.getRelations().forEach(target::addOrReplaceRelation); target.getInterfaces().addAll(source.getInterfaces()); } diff --git a/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java b/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java index 16fedba19..dcc45554e 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java +++ b/src/main/java/de/bonndan/nivio/input/ItemRelationProcessor.java @@ -3,7 +3,10 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.model.*; +import de.bonndan.nivio.search.ItemIndex; import org.apache.commons.collections.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import java.util.*; @@ -13,6 +16,8 @@ */ public class ItemRelationProcessor extends Processor { + private static final Logger LOGGER = LoggerFactory.getLogger(ItemRelationProcessor.class); + protected ItemRelationProcessor(ProcessLog processLog) { super(processLog); } @@ -35,17 +40,17 @@ public ProcessingChangelog process(@NonNull final LandscapeDescription input, @N Relation current = getCurrentRelation(relationDescription, landscape, origin) .map(relation -> { - Relation update = RelationBuilder.update(relation, relationDescription, landscape); + Relation update = RelationFactory.update(relation, relationDescription, landscape); List changes = relation.getChanges(update); if (!changes.isEmpty()) { - processLog.info(String.format(origin + ": Updating relation between %s and %s", update.getSource(), update.getTarget())); + processLog.info(String.format("%s: Updating relation between %s and %s", origin, update.getSource(), update.getTarget())); changelog.addEntry(update, ProcessingChangelog.ChangeType.UPDATED, String.join(";", changes)); } return update; }) .orElseGet(() -> { - Relation created = RelationBuilder.create(origin, relationDescription, landscape); - processLog.info(String.format(origin + ": Adding relation between %s and %s", created.getSource(), created.getTarget())); + Relation created = RelationFactory.create(origin, relationDescription, landscape); + processLog.info(String.format("%s: Adding relation between %s and %s", origin, created.getSource(), created.getTarget())); changelog.addEntry(created, ProcessingChangelog.ChangeType.CREATED, null); return created; }); @@ -66,22 +71,9 @@ public ProcessingChangelog process(@NonNull final LandscapeDescription input, @N .filter(relation -> !processed.contains(relation)) .filter(relation -> origin.equals(relation.getSource())) .forEach(relation -> { - processLog.info(String.format(origin + ": Removing relation between %s and %s", relation.getSource(), relation.getTarget())); - Item currentSource = landscape.getItems().pick( - relation.getSource().getFullyQualifiedIdentifier().getItem(), - relation.getSource().getFullyQualifiedIdentifier().getGroup() - ); - if (!currentSource.removeRelation(relation)) { - processLog.warn(String.format("Could not remove relation %s from source %s", relation, relation.getSource())); - } - - Item currentTarget = landscape.getItems().pick( - relation.getTarget().getFullyQualifiedIdentifier().getItem(), - relation.getTarget().getFullyQualifiedIdentifier().getGroup() - ); - if (!currentTarget.removeRelation(relation)) { - processLog.warn(String.format("Could not remove relation %s from target %s", relation, relation.getSource())); - } + processLog.info(String.format("%s: Removing relation between %s and %s", origin, relation.getSource(), relation.getTarget())); + removeRelationFromItem(landscape.getItems(), relation, relation.getSource()); + removeRelationFromItem(landscape.getItems(), relation, relation.getTarget()); changelog.addEntry(relation, ProcessingChangelog.ChangeType.DELETED, null); }); }); @@ -89,6 +81,28 @@ public ProcessingChangelog process(@NonNull final LandscapeDescription input, @N return changelog; } + /** + * Gracefully finds the relation end item in the landscape and tries to remove the relation. + * + * @param itemIndex all landscape items (containing a sibling of the relation source or target) + * @param relation the relation to remove + * @param relationEnd the relation source or target + */ + private void removeRelationFromItem(ItemIndex itemIndex, Relation relation, Item relationEnd) { + var fqi = relationEnd.getFullyQualifiedIdentifier(); + try { + Item sibling = itemIndex.pick(fqi.getItem(), fqi.getGroup()); + boolean isRelationRemoved = sibling.removeRelation(relation); + if (!isRelationRemoved) { + processLog.warn(String.format("Could not remove relation %s from item %s", relation, relationEnd)); + } + } catch (NoSuchElementException e) { + String msg = String.format("Could not find relation end %s from relation %s: %s", relationEnd, relation, e.getMessage()); + processLog.error(msg); + LOGGER.error(msg, e); + } + } + private boolean isValid(RelationDescription relationDescription, Landscape landscape) { List source = landscape.findBy(relationDescription.getSource()); @@ -123,11 +137,11 @@ private Optional getCurrentRelation(RelationDescription relationDescri Item target = landscape.findOneBy(relationDescription.getTarget(), origin.getGroup()); Iterator iterator = origin.getRelations().iterator(); - Relation created = new Relation(source, target); + Relation virtual = RelationFactory.createForTesting(source, target); Relation existing; while (iterator.hasNext()) { existing = iterator.next(); - if (existing.equals(created)) { + if (existing.equals(virtual)) { return Optional.of(existing); } } diff --git a/src/main/java/de/bonndan/nivio/input/ItemType.java b/src/main/java/de/bonndan/nivio/input/ItemType.java index 4868ed3ab..c00c48a3a 100644 --- a/src/main/java/de/bonndan/nivio/input/ItemType.java +++ b/src/main/java/de/bonndan/nivio/input/ItemType.java @@ -12,4 +12,7 @@ public class ItemType { public static final String POD = "pod"; public static final String DATABASE = "database"; public static final String KEYVALUESTORE = "keyvaluestore"; + public static final String DEPLOYMENT = "deployment"; + public static final String REPLICASET = "replicaset"; + public static final String STATEFULSET = "statefulset"; } diff --git a/src/main/java/de/bonndan/nivio/input/LandscapeDescriptionFactory.java b/src/main/java/de/bonndan/nivio/input/LandscapeDescriptionFactory.java index 8195da130..176429c11 100644 --- a/src/main/java/de/bonndan/nivio/input/LandscapeDescriptionFactory.java +++ b/src/main/java/de/bonndan/nivio/input/LandscapeDescriptionFactory.java @@ -76,7 +76,7 @@ public LandscapeDescription fromYaml(File file) { @NonNull public LandscapeDescription fromString(String yaml, String origin) { - if (StringUtils.isEmpty(yaml)) { + if (!StringUtils.hasLength(yaml)) { throw new ReadingException("Failed to create an environment from empty yaml input string.", new IllegalArgumentException("Got an empty string.")); } diff --git a/src/main/java/de/bonndan/nivio/input/ProcessLog.java b/src/main/java/de/bonndan/nivio/input/ProcessLog.java index 24203ca4d..e8aebb30d 100644 --- a/src/main/java/de/bonndan/nivio/input/ProcessLog.java +++ b/src/main/java/de/bonndan/nivio/input/ProcessLog.java @@ -4,11 +4,10 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import de.bonndan.nivio.model.Landscape; import org.slf4j.Logger; import org.springframework.lang.NonNull; -import java.time.LocalDateTime; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -71,9 +70,9 @@ public List getMessages() { } @JsonIgnore - public LocalDateTime getLastUpdate() { + public ZonedDateTime getLastUpdate() { - if (messages.size() > 0) { + if (!messages.isEmpty()) { return messages.get(messages.size() - 1).date; } return null; @@ -86,18 +85,18 @@ public static class Entry { public final String message; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") - public final LocalDateTime date; + public final ZonedDateTime date; public Entry(String level, String message) { this.level = level; this.message = message; - this.date = LocalDateTime.now(); + this.date = ZonedDateTime.now(); } public Entry(String level, ProcessingException e) { this.level = level; this.message = e.getMessage(); - this.date = LocalDateTime.now(); + this.date = ZonedDateTime.now(); } } } diff --git a/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java b/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java index 7b649ebff..44f666816 100644 --- a/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java +++ b/src/main/java/de/bonndan/nivio/input/ProcessingEvent.java @@ -4,8 +4,8 @@ import org.springframework.context.ApplicationEvent; import java.time.Instant; -import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; /** * Event that is emitted during processing of landscapes. @@ -15,7 +15,7 @@ public abstract class ProcessingEvent extends ApplicationEvent { public static final String LOG_LEVEL_INFO = "info"; public static final String LOG_LEVEL_ERROR = "error"; - public ProcessingEvent(FullyQualifiedIdentifier source) { + protected ProcessingEvent(FullyQualifiedIdentifier source) { super(source); } @@ -34,9 +34,9 @@ public ProcessingEvent(FullyQualifiedIdentifier source) { */ public abstract String getMessage(); - public LocalDateTime getDate() { + public ZonedDateTime getDate() { Instant instant = Instant.ofEpochMilli(getTimestamp()); - return instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); } @Override diff --git a/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java b/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java index c37008e2d..eb28a5f7f 100644 --- a/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java +++ b/src/main/java/de/bonndan/nivio/input/RelationEndpointResolver.java @@ -4,7 +4,7 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.search.ItemIndex; -import de.bonndan.nivio.model.RelationBuilder; +import de.bonndan.nivio.model.RelationFactory; import org.springframework.util.StringUtils; import java.util.Collection; @@ -37,8 +37,8 @@ private void resolveRelations(final ItemDescription description, ItemIndex { allItems.query(term).stream().findFirst().ifPresentOrElse(o -> { - RelationDescription rel = RelationBuilder.createProviderDescription(o, description.getIdentifier()); - description.addRelation(rel); + RelationDescription rel = RelationFactory.createProviderDescription(o, description.getIdentifier()); + description.addOrReplaceRelation(rel); }, () -> processLog.warn(description.getIdentifier() + ": no provider target found for term " + term)); }); @@ -57,7 +57,7 @@ private void resolveRelations(final ItemDescription description, ItemIndex resolveOne(ItemDescription description, String term, ItemIndex allItems) { - if (StringUtils.isEmpty(term)) { + if (!StringUtils.hasLength(term)) { return Optional.of(description); } diff --git a/src/main/java/de/bonndan/nivio/input/Seed.java b/src/main/java/de/bonndan/nivio/input/Seed.java index cadc889b2..fa746f550 100644 --- a/src/main/java/de/bonndan/nivio/input/Seed.java +++ b/src/main/java/de/bonndan/nivio/input/Seed.java @@ -1,9 +1,10 @@ package de.bonndan.nivio.input; -import de.bonndan.nivio.config.ConfigurableEnvVars; import de.bonndan.nivio.util.URLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; import java.io.File; @@ -11,10 +12,7 @@ import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; /** @@ -24,21 +22,25 @@ public class Seed { private static final Logger logger = LoggerFactory.getLogger(Seed.class); - private final List seed; + private final List seedUrls; + private final String demo; + /** - * @param seed comma separated urls - * @throw RuntimeException to fail early on wrong config + * @throws RuntimeException to fail early on wrong config */ - public Seed(Optional seed) { - if (seed.isEmpty()) { - this.seed = new ArrayList<>(); + public Seed(@NonNull final String seed, @Nullable final String demo) { + + this.demo = demo == null ? "" : demo; + if (Objects.requireNonNull(seed).isEmpty()) { + this.seedUrls = new ArrayList<>(); return; } - String[] strings = StringUtils.commaDelimitedListToStringArray(seed.get()); - this.seed = Arrays.stream(strings) - .map(s -> asURL(s)) + String[] strings = StringUtils.commaDelimitedListToStringArray(seed); + this.seedUrls = Arrays.stream(strings) + .map(this::asURL) .collect(Collectors.toList()); + } private URL asURL(String s) { @@ -62,16 +64,15 @@ private URL asURL(String s) { */ public List getDemoFiles() { List demoFiles = new ArrayList<>(); - if (ConfigurableEnvVars.DEMO.value().isEmpty()) { + if (!StringUtils.hasLength(demo)) { return demoFiles; } - String value = ConfigurableEnvVars.DEMO.value().get(); Path currentRelativePath = Paths.get(""); String absPath = currentRelativePath.toAbsolutePath().toString(); try { demoFiles.add(new File(absPath + "/src/test/resources/example/pet_clinic.yml").toURI().toURL()); - if (value.equalsIgnoreCase("all")) { + if (demo.equalsIgnoreCase("all")) { demoFiles.add(new File(absPath + "/src/test/resources/example/inout.yml").toURI().toURL()); demoFiles.add(new File(absPath + "/src/test/resources/example/internals.yml").toURI().toURL()); demoFiles.add(new File(absPath + "/src/test/resources/example/dedica_dot.yml").toURI().toURL()); @@ -89,7 +90,7 @@ public List getDemoFiles() { * @return list of configs */ public List getLocations() { - logger.info("Using seeds: {}", seed); - return seed; + logger.info("Using seeds: {}", seedUrls); + return seedUrls; } } diff --git a/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java b/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java index 4b6d9f430..8ea784f0e 100644 --- a/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java +++ b/src/main/java/de/bonndan/nivio/input/SourceReferencesResolver.java @@ -3,6 +3,8 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.LandscapeSource; import de.bonndan.nivio.util.URLHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; import org.springframework.lang.NonNull; @@ -15,6 +17,8 @@ */ public class SourceReferencesResolver { + private static final Logger LOGGER = LoggerFactory.getLogger(SourceReferencesResolver.class); + private final InputFormatHandlerFactory formatFactory; private final ProcessLog log; private final ApplicationEventPublisher eventPublisher; @@ -30,7 +34,7 @@ public SourceReferencesResolver(@NonNull final InputFormatHandlerFactory formatF public void resolve(final LandscapeDescription landscapeDescription) { - final URL baseUrl = getBaseUrl(landscapeDescription.getSource()); + final var baseUrl = getBaseUrl(landscapeDescription.getSource()); landscapeDescription.getSourceReferences().forEach(ref -> { InputFormatHandler formatHandler; @@ -59,14 +63,15 @@ public void resolve(final LandscapeDescription landscapeDescription) { eventPublisher.publishEvent(new ProcessingErrorEvent(landscapeDescription.getFullyQualifiedIdentifier(), ex)); landscapeDescription.setIsPartial(true); } catch (RuntimeException ex) { - log.warn(ex.getMessage()); + LOGGER.warn("Could not resolve source reference {}: {}", ref, ex.getMessage(), ex); + log.warn(String.format("Failed to resolve source reference %s properly.", ref.getUrl())); landscapeDescription.setIsPartial(true); } }); } private URL getBaseUrl(LandscapeSource source) { - if(source != null) { + if (source != null) { return source.getURL().flatMap(URLHelper::getParentPath).orElse(null); } return null; @@ -76,7 +81,7 @@ private URL getBaseUrl(LandscapeSource source) { private String getCauseMessage(Throwable cause) { String s = cause.getMessage().split("\\[")[0]; if (s.endsWith("at ")) { - s = s.substring(0, s.length()-3); + s = s.substring(0, s.length() - 3); } return s.trim(); diff --git a/src/main/java/de/bonndan/nivio/input/StartupListener.java b/src/main/java/de/bonndan/nivio/input/StartupListener.java index ca266a543..2f5f57887 100644 --- a/src/main/java/de/bonndan/nivio/input/StartupListener.java +++ b/src/main/java/de/bonndan/nivio/input/StartupListener.java @@ -1,6 +1,7 @@ package de.bonndan.nivio.input; import de.bonndan.nivio.config.ConfigurableEnvVars; +import de.bonndan.nivio.config.SeedProperties; import de.bonndan.nivio.util.URLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +15,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Optional; /** @@ -27,19 +29,23 @@ public class StartupListener implements ApplicationListener description.addRelation(RelationBuilder.createProviderDescription(s, description.getFullyQualifiedIdentifier().toString()))); + links.forEach(s -> description.addOrReplaceRelation(RelationFactory.createProviderDescription(s, description.getFullyQualifiedIdentifier().toString()))); } return description; diff --git a/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java b/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java index 4e3477765..76f64602f 100644 --- a/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java +++ b/src/main/java/de/bonndan/nivio/input/compose2/InputFormatHandlerCompose2.java @@ -10,9 +10,9 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.input.http.HttpService; -import de.bonndan.nivio.observation.InputFormatObserver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import java.io.IOException; @@ -24,7 +24,7 @@ @Service public class InputFormatHandlerCompose2 implements InputFormatHandler { - private static final Logger logger = LoggerFactory.getLogger(InputFormatHandler.class); + private static final Logger logger = LoggerFactory.getLogger(InputFormatHandlerCompose2.class); private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); static { @@ -49,7 +49,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { List itemDescriptions = new ArrayList<>(); String yml = fileFetcher.get(reference, baseUrl); @@ -60,7 +60,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti logger.error("Failed to read yml", e); } if (source == null) { - logger.warn("Got null out of yml string " + yml); + logger.warn("Got null out of yml string {}", yml); return; } @@ -71,10 +71,4 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti landscapeDescription.mergeItems(itemDescriptions); } - - @Override - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { - return inner; - } - } diff --git a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java index a9ea21d81..83c349cb0 100644 --- a/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java +++ b/src/main/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSV.java @@ -10,22 +10,18 @@ import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.observation.InputFormatObserver; -import org.springframework.lang.Nullable; +import de.bonndan.nivio.model.Relation; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import java.io.StringReader; import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; /** * Reads csv files to {@link ItemDescription}s. - * - * */ @Service public class InputFormatHandlerCSV implements InputFormatHandler { @@ -44,7 +40,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { List itemDescriptions = new ArrayList<>(); String content = fileFetcher.get(reference, baseUrl); CSVReader reader = getReader(reference, content); @@ -54,45 +50,54 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti throw new ProcessingException(reference.getLandscapeDescription(), "'mapping' must be present in configuration."); } if (!mapping.containsKey(IDENTIFIER_KEY)) { - throw new ProcessingException(reference.getLandscapeDescription(), "'" + IDENTIFIER_KEY + "' must be present in configured mapping."); + throw new ProcessingException(reference.getLandscapeDescription(), String.format("'%s' must be present in configured mapping.", IDENTIFIER_KEY)); } reader.iterator().forEachRemaining(strings -> { ItemDescription itemDescription = new ItemDescription(); - mapping.forEach((key, value) -> { - Integer colNum = 0; + RelationDescription relationDescription = null; + Map labels = new HashMap<>(); + for (Map.Entry entry : mapping.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + int colNum = 0; if (value instanceof String) { - colNum = Integer.valueOf((String)value); + colNum = Integer.parseInt((String) value); } if (value instanceof Integer) { colNum = (Integer) value; } - + String columnValue = strings[colNum]; if (IDENTIFIER_KEY.equals(key)) { - itemDescription.setIdentifier(strings[colNum]); - return; - } - - if (colNum >= strings.length) { - return; + if (columnValue.contains(Relation.DELIMITER)) { + String[] split = columnValue.split(Relation.DELIMITER); + itemDescription.setIdentifier(split[0]); + relationDescription = new RelationDescription(split[0], split[1]); + } else { + + itemDescription.setIdentifier(columnValue); + } + continue; } //relies on LabelToFieldProcessor running later - itemDescription.getLabels().put(LabelToFieldResolver.NIVIO_LABEL_PREFIX + key, strings[colNum]); - }); + labels.put(LabelToFieldResolver.NIVIO_LABEL_PREFIX + key, columnValue); + } + + if (relationDescription != null) { + relationDescription.setLabels(labels); + itemDescription.addOrReplaceRelation(relationDescription); + } else { + itemDescription.getLabels().putAll(labels); + } + itemDescriptions.add(itemDescription); }); landscapeDescription.mergeItems(itemDescriptions); } - @Override - @Nullable - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { - return inner; - } - private CSVReader getReader(SourceReference reference, String content) { String separator = (String) Optional.ofNullable(reference.getProperty("separator")).orElse(";"); int skipLines = (int) Optional.ofNullable(reference.getProperty("skipLines")).orElse(0); diff --git a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java index a8f1e71f0..4e8c34307 100644 --- a/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java +++ b/src/main/java/de/bonndan/nivio/input/demo/ChangeTrigger.java @@ -1,9 +1,9 @@ package de.bonndan.nivio.input.demo; -import de.bonndan.nivio.config.ConfigurableEnvVars; import de.bonndan.nivio.input.IndexEvent; import de.bonndan.nivio.input.LandscapeDescriptionFactory; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.model.LandscapeRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationEventPublisher; @@ -13,6 +13,7 @@ import java.io.File; import java.nio.file.Paths; import java.util.Optional; +import java.util.stream.StreamSupport; @Component public class ChangeTrigger { @@ -20,19 +21,22 @@ public class ChangeTrigger { private static final Logger LOGGER = LoggerFactory.getLogger(ChangeTrigger.class); private final LandscapeDescriptionFactory landscapeDescriptionFactory; + private final LandscapeRepository landscapeRepository; private final ApplicationEventPublisher eventPublisher; - public ChangeTrigger(LandscapeDescriptionFactory landscapeDescriptionFactory, - ApplicationEventPublisher eventPublisher + public ChangeTrigger( + LandscapeRepository landscapeRepository, + LandscapeDescriptionFactory landscapeDescriptionFactory, + ApplicationEventPublisher eventPublisher ) { this.landscapeDescriptionFactory = landscapeDescriptionFactory; + this.landscapeRepository = landscapeRepository; this.eventPublisher = eventPublisher; } @Scheduled(initialDelay = 20000, fixedDelay = 30000) public void trigger() { - - if (ConfigurableEnvVars.DEMO.value().isEmpty()) { + if (StreamSupport.stream(landscapeRepository.findAll().spliterator(), false).noneMatch(landscape -> landscape.getIdentifier().equals("petclinic"))) { LOGGER.debug("DEMO not set, not simulating any pet clinic events."); return; } @@ -45,7 +49,7 @@ private Optional getDemoLandscapeDescription() { String demoFile = absPath + "/src/test/resources/example/pet_clinic.yml"; File file = new File(demoFile); if (!file.exists()) { - LOGGER.error(String.format("Failed to read pet clinic demo data from %s", demoFile)); + LOGGER.error("Failed to read pet clinic demo data from {}", demoFile); return Optional.empty(); } diff --git a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java index 760c4f904..9bdbf5198 100644 --- a/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java +++ b/src/main/java/de/bonndan/nivio/input/dot/InputFormatHandlerDot.java @@ -6,14 +6,12 @@ import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.model.RelationType; -import de.bonndan.nivio.observation.InputFormatObserver; import guru.nidi.graphviz.model.MutableGraph; import guru.nidi.graphviz.parse.Parser; import guru.nidi.graphviz.parse.ParserException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import java.io.IOException; @@ -43,7 +41,7 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { List itemDescriptions = new ArrayList<>(); String content = fileFetcher.get(reference, baseUrl); List items = new ArrayList<>(); @@ -81,7 +79,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti break; } }); - itemDescription.addRelation(rel); + itemDescription.addOrReplaceRelation(rel); }); items.add(itemDescription); @@ -97,11 +95,4 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti } landscapeDescription.mergeItems(itemDescriptions); } - - @Override - @Nullable - public InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, @NonNull final SourceReference sourceReference) { - return inner; - } - } diff --git a/src/main/java/de/bonndan/nivio/input/dto/ComponentDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ComponentDescription.java index 8b6bf270f..e80f3f164 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ComponentDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ComponentDescription.java @@ -1,8 +1,16 @@ package de.bonndan.nivio.input.dto; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.Labeled; import de.bonndan.nivio.model.Linked; +import org.springframework.lang.NonNull; +import org.springframework.util.StringUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; /** * Base interface for input DTOs, which are mutable objects. @@ -18,4 +26,54 @@ public interface ComponentDescription extends Component, Labeled, Linked { void setOwner(String owner); void setContact(String contact); + + void setIcon(String icon); + + default void setLabel(String key, String value){ + setLabel(key, (Object) value); + } + + /** + * Any-setter default implementation for deserialization. + * + * @param key label key + * @param value label value (string|string[]|number|list|map) + */ + @JsonAnySetter + default void setLabel(@NonNull final String key, final Object value) { + if (!StringUtils.hasLength(key)) { + throw new IllegalArgumentException("Label key is empty."); + } + + if (value instanceof String) { + getLabels().put(key.toLowerCase(), (String) value); + return; + } + + if (value instanceof Number) { + getLabels().put(key.toLowerCase(), String.valueOf(value)); + return; + } + + if (value instanceof String[]) { + Arrays.stream(((String[]) value)).forEach(s -> setPrefixed(key, s)); + return; + } + + if (value instanceof List) { + try { + //noinspection unchecked,rawtypes + ((List) value).forEach(s -> setPrefixed(key, (String) s)); + return; + } catch (ClassCastException e) { + throw new ProcessingException(String.format("Cannot set '%s' to list '%s'. Is this a list-like structure", key, value), e); + } + } + + if (value instanceof Map) { + throw new IllegalArgumentException(String.format("Cannot use the value of '%s' as map ('%s'). Please check the spelling of", key, value)); + } + + getLabels().put(key, String.valueOf(value)); + } } diff --git a/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java b/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java index 9d8aad1c2..b8f748e36 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/GroupDescription.java @@ -1,10 +1,10 @@ package de.bonndan.nivio.input.dto; import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import de.bonndan.nivio.model.FullyQualifiedIdentifier; +import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Link; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; @@ -75,13 +75,11 @@ public String getOwner() { @JsonIgnore @Override public String getIcon() { - return null; + return getLabel(Label.icon); } - @JsonIgnore - @Override - public String getAddress() { - return null; + public void setIcon(String icon) { + setLabel(Label.icon, icon); } public void setOwner(String owner) { @@ -135,26 +133,17 @@ public void setContains(List contains) { this.contains = contains; } + @NonNull + @JsonAnyGetter public Map getLabels() { return labels; } @Override - @JsonAnyGetter public String getLabel(String key) { return labels.get(key); } - public void setLabel(String key, String value) { - labels.put(key, value); - } - - @JsonAnySetter - @Override - public void setLabel(@NonNull String key, Object value) { - ComponentDescription.super.setLabel(key, value); - } - public void setEnvironment(String environment) { this.environment = environment; } diff --git a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java index 0683ee5ea..dc35375f9 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/ItemDescription.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.input.dto; import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -70,6 +69,9 @@ public class ItemDescription implements ComponentDescription, Labeled, Linked, T @Schema(description = "The technical address of the item (should be an URI). Taken into account when matching relation endpoints.") private String address; + @Schema(description = "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", example = "service|database|volume") + private String type; + public ItemDescription() { } @@ -105,14 +107,12 @@ public void setEnvironment(String environment) { this.environment = environment; } - @Schema(description = "The type of the item. A string describing its nature. If no icon is set, the type determines the displayed icon.", - example = "service|database|volume") public String getType() { - return getLabel(Label.type); + return type; } public void setType(String type) { - this.setLabel(Label.type, type); + this.type = type; } public String getName() { @@ -181,7 +181,7 @@ public void setGroup(String group) { public void setLifecycle(String lifecycle) { //try to standardize using enum values - if (!StringUtils.isEmpty(lifecycle)) { + if (StringUtils.hasLength(lifecycle)) { Lifecycle from = Lifecycle.from(lifecycle); if (from != null) { lifecycle = from.name(); @@ -193,7 +193,9 @@ public void setLifecycle(String lifecycle) { } } + @NonNull @Override + @JsonAnyGetter public Map getLabels() { return labels; } @@ -231,14 +233,26 @@ public Set getRelations() { @JsonIgnore public void setRelations(List relations) { relations.stream() - .filter(s -> !StringUtils.isEmpty(s)) - .map(s -> RelationBuilder.createDataflowDescription(this, s)) - .forEach(this::addRelation); + .filter(StringUtils::hasLength) + .map(s -> RelationFactory.createDataflowDescription(this, s)) + .forEach(this::addOrReplaceRelation); } - public void addRelation(RelationDescription relationItem) { - Objects.requireNonNull(relationItem); - this.relations.add(relationItem); + /** + * Add or update a relation description. + * + * If an equal relation description exist, it is updated with values from the newer one. + * + * @param description relation dto to be added + */ + public void addOrReplaceRelation(@NonNull final RelationDescription description) { + RelationDescription relationDescription = Objects.requireNonNull(description).findMatching(this.relations) + .map(existingRelation -> { + existingRelation.update(description); + return existingRelation; + }) + .orElse(description); + this.relations.add(relationDescription); } public String getAddress() { @@ -270,7 +284,7 @@ public int hashCode() { */ @Override public String toString() { - if (StringUtils.isEmpty(environment)) { + if (!StringUtils.hasLength(environment)) { return identifier; } @@ -306,22 +320,10 @@ public void setStatus(List> status) { } @Override - @JsonAnyGetter public String getLabel(String key) { return labels.get(key); } - @Override - public void setLabel(String key, String value) { - labels.put(key, value); - } - - @JsonAnySetter - @Override - public void setLabel(@NonNull String key, Object value) { - ComponentDescription.super.setLabel(key, value); - } - /** * Setter for framework map. * diff --git a/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java b/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java index 83c103baf..ad05b01d0 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/LandscapeDescription.java @@ -1,9 +1,6 @@ package de.bonndan.nivio.input.dto; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreType; -import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import de.bonndan.nivio.input.ComponentDescriptionValues; import de.bonndan.nivio.model.LandscapeConfig; @@ -21,7 +18,7 @@ /** * Input DTO for a landscape. - * + *

* Think of a group of servers and apps, like a "project", "workspace" or stage. */ @JsonIgnoreType @@ -146,7 +143,11 @@ public String getOwner() { } public String getIcon() { - return null; + return getLabel(Label.icon); + } + + public void setIcon(String icon) { + setLabel(Label.icon, icon); } public String getColor() { @@ -174,12 +175,6 @@ public void setSource(LandscapeSource source) { this.source = source; } - @JsonIgnore - @Override - public String getAddress() { - return null; - } - public ItemIndex getItemDescriptions() { return itemDescriptions; } @@ -195,8 +190,9 @@ public void setTemplates(Map templates) { /** * Merges the incoming items with existing ones. - * + *

* Already existing ones are updated. + * * @param incoming new data */ public void mergeItems(@Nullable Collection incoming) { @@ -218,8 +214,9 @@ public void mergeItems(@Nullable Collection incoming) { /** * Merges the incoming groups with existing ones. - * + *

* Already existing ones are updated. + * * @param incoming new data */ public void mergeGroups(@Nullable Map incoming) { @@ -227,7 +224,7 @@ public void mergeGroups(@Nullable Map incoming) { return; } - incoming.forEach( (identifier, groupDescription) -> { + incoming.forEach((identifier, groupDescription) -> { groupDescription.setEnvironment(this.identifier); GroupDescription existing = groups.get(identifier); @@ -269,7 +266,7 @@ public Map getGroups() { public void setGroups(Map groups) { groups.forEach((s, groupItem) -> { - if (!s.equals(groupItem.getIdentifier()) && !StringUtils.isEmpty(groupItem.getIdentifier())) { + if (!s.equals(groupItem.getIdentifier()) && StringUtils.hasLength(groupItem.getIdentifier())) { LOGGER.warn("Group map key {} and identifier {} are both set and differ. Overriding with map key.", s, groupItem.getIdentifier()); } groupItem.setIdentifier(s); @@ -287,23 +284,14 @@ public Map getLinks() { return links; } + @NonNull + @JsonAnyGetter public Map getLabels() { return labels; } - public void setLabels(Map labels) { - this.labels = labels; - } - @Override public String getLabel(String key) { return getLabels().get(key); } - - @Override - public void setLabel(String key, String value) { - getLabels().put(key, value); - } - - -} +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java index 47198a9bb..e204285c2 100644 --- a/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java +++ b/src/main/java/de/bonndan/nivio/input/dto/RelationDescription.java @@ -1,10 +1,17 @@ package de.bonndan.nivio.input.dto; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import de.bonndan.nivio.model.Labeled; import de.bonndan.nivio.model.RelationType; +import de.bonndan.nivio.search.ItemMatcher; import io.swagger.v3.oas.annotations.media.Schema; +import org.springframework.lang.NonNull; + +import java.util.*; + @Schema(description = "A directed relation between two landscape items. Also known as edge in a directed graph.") -public class RelationDescription { +public class RelationDescription implements Labeled { @Schema(description = "The type of the relation, i.e. whether it is a hard or a soft dependency.") private RelationType type; @@ -21,7 +28,11 @@ public class RelationDescription { @Schema(description = "The item identifier of the target. Prepend a group identifier if the simple item identifier is ambiguous.", example = "dataSink|groupB/dataSink") private String target; - public RelationDescription(){} + @Schema(description = "Key-value pair labels for a relation.") + private final Map labels = new HashMap<>(); + + public RelationDescription() { + } public RelationDescription(String source, String target) { this.source = source; @@ -78,4 +89,54 @@ public String toString() { ", target='" + target + '\'' + '}'; } + + @Override + public String getLabel(String key) { + return getLabels().get(key); + } + + @Override + @NonNull + public Map getLabels() { + return labels; + } + + @Override + @JsonAnySetter + public void setLabel(String key, String value) { + getLabels().put(key, value); + } + + /** + * Finds the first relation description with same source and target. + * + * @param relations a collection of existing relations + * @return the sibling + */ + Optional findMatching(@NonNull final Collection relations) { + return Objects.requireNonNull(relations).stream() + .filter(rel -> matches(source, rel.getSource())) + .filter(rel -> matches(target, rel.getTarget())) + .findFirst(); + } + + private boolean matches(String end1, String end2) { + Optional m1 = ItemMatcher.forTarget(end1); + Optional m2 = ItemMatcher.forTarget(end2); + return m1.isPresent() && m2.isPresent() && m1.map(m -> m.equals(m2.get())).orElse(false); + } + + /** + * Updates the current object with values from the param. + * + * @param newer update + */ + public void update(@NonNull final RelationDescription newer) { + Objects.requireNonNull(newer); + + setDescription(newer.description); + setFormat(newer.format); + + Labeled.merge(newer, this); + } } diff --git a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java index 8e20049fe..dbc0aa48e 100644 --- a/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java +++ b/src/main/java/de/bonndan/nivio/input/external/LinkHandlerFactory.java @@ -2,16 +2,14 @@ import de.bonndan.nivio.input.external.github.GitHubRepoHandler; +import de.bonndan.nivio.input.external.gitlab.GitLabRepoHandler; import de.bonndan.nivio.input.external.openapi.OpenAPILinkHandler; import de.bonndan.nivio.input.external.sonar.SonarLinkHandler; import de.bonndan.nivio.input.external.springboot.SpringBootHealthHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; - import java.util.Map; import java.util.Optional; @@ -21,11 +19,10 @@ @Component public class LinkHandlerFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(LinkHandlerFactory.class); - public static final String GITHUB = "github"; private static final String SONAR = "sonar"; private static final String SPRING_HEALTH = "spring.health"; + private static final String GITLAB = "gitlab"; // add semantics, e.g. handle identifier "sonarqube" to grab metrics // see https://github.com/dedica-team/nivio/issues/97 @@ -33,7 +30,9 @@ public class LinkHandlerFactory { GITHUB, GitHubRepoHandler.class, SONAR, SonarLinkHandler.class, SPRING_HEALTH, SpringBootHealthHandler.class, - OpenAPILinkHandler.NAMESPACE, OpenAPILinkHandler.class + OpenAPILinkHandler.NAMESPACE, OpenAPILinkHandler.class, + GITLAB, GitLabRepoHandler.class + ); private final AutowireCapableBeanFactory beanFactory; @@ -52,7 +51,7 @@ private Optional createHandler(String key, Class hostUrl = GITLAB_HOST_URL.value(); + Optional hostUrl = Optional.ofNullable(gitLabProperties.getHostUrl()); if (hostUrl.isEmpty()) { return null; } - Optional personalAccessToken = GITLAB_PERSONAL_ACCESS_TOKEN.value(); - Optional username = GITLAB_USERNAME.value(); - Optional password = GITLAB_PASSWORD.value(); + Optional personalAccessToken = Optional.ofNullable(gitLabProperties.getPersonalAccessToken()); + Optional username = Optional.ofNullable(gitLabProperties.getUsername()); + Optional password = Optional.ofNullable(gitLabProperties.getPassword()); return getGitLabAPI(hostUrl.get(), personalAccessToken, username, password); } GitLabApi getGitLabAPI(@NonNull String hostUrl, - Optional personalAccessToken, - Optional username, - Optional password + Optional personalAccessToken, + Optional username, + Optional password ) { if (personalAccessToken.isPresent()) { diff --git a/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java new file mode 100644 index 000000000..f0ab72008 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/external/gitlab/GitLabProperties.java @@ -0,0 +1,55 @@ +package de.bonndan.nivio.input.external.gitlab; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "gitlab") +public class GitLabProperties { + + private String hostUrl; + private String personalAccessToken; + private String username; + private String password; + + public GitLabProperties() { + } + + public GitLabProperties(String hostUrl, String personalAccessToken, String username, String password) { + this.hostUrl = hostUrl; + this.personalAccessToken = personalAccessToken; + this.username = username; + this.password = password; + } + + public String getHostUrl() { + return hostUrl; + } + + public void setHostUrl(String hostUrl) { + this.hostUrl = hostUrl; + } + + public String getPersonalAccessToken() { + return personalAccessToken; + } + + public void setPersonalAccessToken(String personalAccessToken) { + this.personalAccessToken = personalAccessToken; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + +} diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java index ecb2e3cb5..4d1bd645f 100644 --- a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarConfig.java @@ -1,29 +1,38 @@ package de.bonndan.nivio.input.external.sonar; import org.sonar.wsclient.SonarClient; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Optional; -import static de.bonndan.nivio.config.ConfigurableEnvVars.*; - @Configuration +@EnableConfigurationProperties(SonarProperties.class) public class SonarConfig { + private final SonarProperties sonarProperties; + + public SonarConfig(SonarProperties sonarProperties) { + this.sonarProperties = sonarProperties; + } + @Bean public SonarClient.Builder getSonarClientBuilder() { - Optional serverUrl = SONAR_SERVER_URL.value(); + Optional serverUrl = Optional.ofNullable(sonarProperties.getServerUrl()); + if (serverUrl.isEmpty()) { return null; } SonarClient.Builder builder = SonarClient.builder().url(serverUrl.get()); - SONAR_LOGIN.value().ifPresent(builder::login); - SONAR_PASSWORD.value().ifPresent(builder::password); - SONAR_PROXY_HOST.value().ifPresent( - host -> SONAR_PROXY_PORT.value() + + Optional.ofNullable(sonarProperties.getLogin()) .ifPresent(builder::login); + + Optional.ofNullable(sonarProperties.getPassword()).ifPresent(builder::password); + Optional.ofNullable(sonarProperties.getProxyHost()).ifPresent( + host -> Optional.ofNullable(sonarProperties.getProxyPort()) .ifPresent(port -> builder.proxy(host, Integer.parseInt(port))) ); diff --git a/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java new file mode 100644 index 000000000..b988f2b68 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/external/sonar/SonarProperties.java @@ -0,0 +1,63 @@ +package de.bonndan.nivio.input.external.sonar; + +import org.springframework.boot.context.properties.ConfigurationProperties; + + +@ConfigurationProperties(prefix = "sonar") +public class SonarProperties { + + private String serverUrl; + private String login; + private String password; + private String proxyHost; + private String proxyPort; + + public SonarProperties(String serverUrl,String login,String password,String proxyHost,String proxyPort){ + this.serverUrl = serverUrl; + this.login = login; + this.password = password; + this.proxyHost = proxyHost; + this.proxyPort = proxyPort; + } + + public String getServerUrl() { + return serverUrl; + } + + public void setServerUrl(String serverUrl) { + this.serverUrl = serverUrl; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getProxyHost() { + return proxyHost; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + public String getProxyPort() { + return proxyPort; + } + + public void setProxyPort(String proxyPort) { + this.proxyPort = proxyPort; + } + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/CreateItems.java b/src/main/java/de/bonndan/nivio/input/kubernetes/CreateItems.java new file mode 100644 index 000000000..8c2b0c19a --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/CreateItems.java @@ -0,0 +1,64 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.details.*; +import de.bonndan.nivio.input.kubernetes.itemadapters.*; +import de.bonndan.nivio.input.kubernetes.status.BoolStatus; +import de.bonndan.nivio.input.kubernetes.status.ReplicaStatus; +import io.fabric8.kubernetes.client.KubernetesClient; +import org.springframework.lang.NonNull; + +import java.util.List; +import java.util.stream.Collectors; + +public class CreateItems { + private CreateItems() { + } + + public static List getDeploymentItems(@NonNull KubernetesClient client) { + var deploymentList = client.apps().deployments().list().getItems(); + return deploymentList.stream().map(deployment -> { + var deploymentItem = new K8sItemBuilder(ItemType.DEPLOYMENT, new DeploymentItemAdapter(deployment)).addStatus(new BoolStatus()).addDetails(new DeploymentDetails(new DefaultDetails())).build(); + deployment.getStatus().getConditions().forEach(condition -> deploymentItem.addStatus(condition.getType(), condition.getStatus())); + return deploymentItem; + }).collect(Collectors.toList()); + } + + public static List getPersistentVolumeClaimItems(KubernetesClient client) { + var getPersistentVolumeClaimsList = client.persistentVolumeClaims().list().getItems(); + return getPersistentVolumeClaimsList.stream().map(persistentVolumeClaims -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeClaimItemAdapter(persistentVolumeClaims)).addDetails(new PersistentVolumeClaimDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } + + public static List getPersistentVolumeItems(KubernetesClient client) { + var getPersistentVolumeList = client.persistentVolumes().list().getItems(); + return getPersistentVolumeList.stream().map(persistentVolume -> new K8sItemBuilder(ItemType.VOLUME, new PersistentVolumeItemAdapter(persistentVolume)).addDetails(new PersistentVolumeDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } + + public static List getPodItems(KubernetesClient client) { + var pods = client.pods().list().getItems(); + return pods.stream().map(pod -> { + var podItem = new K8sItemBuilder(ItemType.POD, new PodItemAdapter(pod)).addStatus(new BoolStatus()).build(); + pod.getStatus().getConditions().forEach(condition -> podItem.addStatus(condition.getType(), condition.getStatus())); + return podItem; + }).collect(Collectors.toList()); + } + + public static List getReplicaSetItems(KubernetesClient client) { + var replicaSetList = client.apps().replicaSets().list().getItems(); + return replicaSetList.stream().map(replicaSet -> { + var replicaSetItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(replicaSet)).addStatus(new ReplicaStatus()).build(); + replicaSet.getStatus().getConditions().forEach(condition -> replicaSetItem.addStatus(condition.getType(), condition.getStatus())); + return replicaSetItem; + }).collect(Collectors.toList()); + } + + public static List getServiceItems(KubernetesClient client) { + var serviceList = client.services().list().getItems(); + return serviceList.stream().map(service -> new K8sItemBuilder(ItemType.SERVICE, new ServiceItemAdapter(service)).addDetails(new ServiceDetails(new DefaultDetails())).build()).collect(Collectors.toList()); + } + + public static List getStatefulSetItems(KubernetesClient client) { + var statefulSetList = client.apps().statefulSets().list().getItems(); + return statefulSetList.stream().map(statefulSet -> new K8sItemBuilder(ItemType.STATEFULSET, new StatefulSetItemAdapter(statefulSet)).addStatus(new ReplicaStatus()).build()).collect(Collectors.toList()); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java index e20ea45b8..7bf185d5b 100644 --- a/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetes.java @@ -1,30 +1,33 @@ package de.bonndan.nivio.input.kubernetes; -import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.input.InputFormatHandler; -import de.bonndan.nivio.input.ItemType; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter; import de.bonndan.nivio.model.Label; -import de.bonndan.nivio.model.RelationType; +import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.observation.InputFormatObserver; -import de.bonndan.nivio.util.URLHelper; -import io.fabric8.kubernetes.api.model.*; +import de.bonndan.nivio.observation.KubernetesObserver; +import io.fabric8.kubernetes.api.model.OwnerReference; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientException; +import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.lang.NonNull; -import org.springframework.util.StringUtils; -import java.net.MalformedURLException; import java.net.URL; import java.util.*; import java.util.stream.Collectors; +import static de.bonndan.nivio.input.kubernetes.CreateItems.*; + /** * Scans the k8s api for services, pods, volumes etc. */ @@ -34,16 +37,9 @@ public class InputFormatHandlerKubernetes implements InputFormatHandler { private static final Logger LOGGER = LoggerFactory.getLogger(InputFormatHandlerKubernetes.class); public static final String NAMESPACE = "namespace"; - public static final String GROUP_LABEL_PARAM = "groupLabel"; - /** - * label name to determine the group name (fallback from GROUP_LABEL) - */ - public static final String APP_KUBERNETES_IO_INSTANCE_LABEL = "app.kubernetes.io/instance"; - public static final String APP_SELECTOR = "app"; + public static final String LABEL_PREFIX = Label.INTERNAL_LABEL_PREFIX + "k8s"; - private String namespace = null; - private String groupLabel = null; private KubernetesClient client; @SuppressWarnings("OptionalUsedAsFieldOrParameterType") @@ -60,213 +56,124 @@ public List getFormats() { * Created Items: service -> pod -> containers */ @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + this.client = getClient(reference.getUrl()); try { - if (!StringUtils.isEmpty(reference.getUrl())) { - URL url = new URL(reference.getUrl()); - Map params = URLHelper.splitQuery(url); - if (params.containsKey(NAMESPACE)) { - namespace = params.get(NAMESPACE); - } - if (params.containsKey(GROUP_LABEL_PARAM)) { - this.groupLabel = params.get(GROUP_LABEL_PARAM); - } - } - } catch (MalformedURLException ignored) { - + client.apps().deployments(); + landscapeDescription.mergeItems(getItemDescription(client)); + } catch (KubernetesClientException n) { + LOGGER.error(n.getMessage()); + LOGGER.error("Kubernetes might not be available"); } - - KubernetesClient client = getClient(reference.getUrl()); - - List descriptions = new ArrayList<>(); - final List pods = new ArrayList<>(); - getPods().forEach(pod -> { - ItemDescription podItem = createPodItemDescription(pod); - descriptions.add(podItem); - pods.add(podItem); - List descriptionsFromPod = createDescriptionsFromPod(pod, podItem); - descriptions.addAll(descriptionsFromPod); - }); - - List services = client.services().list().getItems(); - LOGGER.info("Found services: {}", services.stream().map(service -> service.getMetadata().getName()).collect(Collectors.toList())); - services.stream() - .filter(service -> namespace == null || namespace.equals(service.getMetadata().getNamespace())) - .forEach(service -> descriptions.add(createDescriptionFromService(service, pods))); - - landscapeDescription.mergeItems(descriptions); - } - - @Override - public InputFormatObserver getObserver(@NonNull final InputFormatObserver inner, @NonNull final SourceReference sourceReference) { - return null; } /** - * Creates a pod item + * This method collects all Kubernetes objects encapsulated in K8sItems and creates ItemDescription from them * - * @param pod k8s pod object - * @return pod (yet ungrouped) - */ - private ItemDescription createPodItemDescription(Pod pod) { - ItemDescription itemDescription = new ItemDescription(); - itemDescription.setName(pod.getMetadata().getName()); - itemDescription.setIdentifier(pod.getMetadata().getName()); - itemDescription.setType(ItemType.POD); - itemDescription.setGroup(getGroup(pod)); - pod.getMetadata().getLabels().forEach(itemDescription::setLabel); - return itemDescription; - } - - /** - * @return all pods in the namespace + * @param client the KubernetesClient is used to get the K8s Objects + * @return a list of ItemDescriptions */ - private List getPods() { - try { - List pods = client.pods().list().getItems(); - LOGGER.info("Found pods: {}", pods.stream().map(pod -> pod.getMetadata().getName()).collect(Collectors.toList())); - return pods.stream() - .filter(pod -> namespace == null || namespace.equals(pod.getMetadata().getNamespace())) - .collect(Collectors.toList()); - } catch (Exception ex) { - throw new ProcessingException("Failed to load pods ", ex); - } - } - - private ItemDescription createDescriptionFromService(Service kubernetesService, List pods) { - ItemDescription service = new ItemDescription(); - service.setIdentifier(kubernetesService.getMetadata().getName()); - service.setType(kubernetesService.getSpec().getType()); - - String group = getGroup(kubernetesService); - service.setGroup(group); - - String targetId = ""; - Map selector = kubernetesService.getSpec().getSelector(); - if (selector != null) { - targetId = selector.getOrDefault(APP_SELECTOR, null); - } - - //TODO, check if this is reliable - if (!StringUtils.isEmpty(targetId)) { - service.addRelation(new RelationDescription(service.getIdentifier(), targetId)); + private List getItemDescription(KubernetesClient client) { + var persistentVolumeClaims = getPersistentVolumeClaimItems(client); + var persistentVolumes = getPersistentVolumeItems(client); + crossReferenceClaimer(persistentVolumeClaims, persistentVolumes); + + var serviceItems = getServiceItems(client); + var deploymentItems = getDeploymentItems(client); + var statefulSetItems = getStatefulSetItems(client); + + crossReferenceService(serviceItems, deploymentItems); + crossReferenceService(serviceItems, statefulSetItems); + + var podItems = getPodItems(client); + crossReferenceVolumes(persistentVolumeClaims, podItems); + + var itemList = new ArrayList(); + itemList.addAll(getReplicaSetItems(client)); + itemList.addAll(podItems); + itemList.addAll(serviceItems); + itemList.addAll(deploymentItems); + itemList.addAll(statefulSetItems); + crossReferenceOwner(itemList); + + itemList.addAll(persistentVolumeClaims); + itemList.addAll(persistentVolumes); + if (K8sJsonParser.getExperimentalActive()) { + crossReferenceLabel(itemList); } - - //link pods as providers - pods.stream() - .filter(pod -> pod.getName().startsWith(service.getIdentifier())) - .forEach(pod -> { - RelationDescription rel = new RelationDescription(pod.getIdentifier(), service.getIdentifier()); - rel.setType(RelationType.PROVIDER); - service.addRelation(rel); - pod.setGroup(service.getGroup()); - }); - - return service; + return createItemDescription(itemList); } - public Config getConfiguration() { - return getClient("").getConfiguration(); + private List createItemDescription(List itemList) { + return itemList.stream().map(item -> { + var itemDescription = new ItemDescription(); + itemDescription.setIdentifier(item.getUid()); + itemDescription.setName(item.getName()); + itemDescription.setType(item.getType()); + if (!item.getOwner().isEmpty()) { + itemDescription.setOwner(item.getOwner().get(0).getName()); + } + itemDescription.setGroup(item.getGroup()); + item.getOwner().forEach(owner -> itemDescription.addOrReplaceRelation(new RelationDescription(owner.getUid(), item.getUid()))); + if (!item.getDetails().isEmpty()) { + item.getDetails().forEach(itemDescription::setLabel); + } + return itemDescription; + }).collect(Collectors.toList()); } - private List createDescriptionsFromPod(Pod pod, ItemDescription podItem) { - - List descriptions = new ArrayList<>(); - - ItemDescription node = new ItemDescription(); - node.setName(pod.getSpec().getNodeName()); - node.setIdentifier(pod.getSpec().getNodeName()); - node.setType(ItemType.SERVER); - descriptions.add(node); - podItem.addRelation(new RelationDescription(node.getIdentifier(), podItem.getIdentifier())); - - String group = getGroup(pod); - pod.getSpec().getContainers().forEach(container -> { - ItemDescription containerDesc = new ItemDescription(); - containerDesc.setGroup(group); - containerDesc.setName(container.getName()); - containerDesc.setIdentifier(podItem.getName() + "-" + container.getName()); - containerDesc.setLabel(Label.software, container.getImage()); - containerDesc.setType(ItemType.CONTAINER); - pod.getMetadata().getLabels().forEach(containerDesc::setLabel); - - //container provides the pod - RelationDescription relationDescription = new RelationDescription(containerDesc.getIdentifier(), podItem.getIdentifier()); - relationDescription.setType(RelationType.PROVIDER); - containerDesc.addRelation(relationDescription); - - // TODO - //description.setScale(...); - // statuses: pod.getStatus() - setConditionsAndHealth(pod.getStatus(), podItem); - podItem.setLabel("hostIP", pod.getStatus().getHostIP()); - podItem.setLabel("podIP", pod.getStatus().getPodIP()); - podItem.setLabel("phase", pod.getStatus().getPhase()); - podItem.setLabel("startTime", pod.getStatus().getStartTime()); - //description.setNetworks(); + /** + * The crossReferenceLevel Method tries to match K8sItems via their Label. It is restricted via the level of a K8sItem and a minimal of matching labels. + * + * @param itemList all K8sItems + */ - descriptions.add(containerDesc); + private void crossReferenceLabel(ArrayList itemList) { + itemList.forEach(ownedItem -> { + var ownerList = itemList.stream().filter( + ownerItem -> CollectionUtils.intersection(Objects.requireNonNullElse(ownedItem.getItemAdapter().getLabels(), new HashMap()).values(), + Objects.requireNonNullElse(ownerItem.getItemAdapter().getLabels(), new HashMap()).values()) + .size() >= K8sJsonParser.getMinMatchingLevel() && ownerItem.getLevelDecorator().getLevel() != -1 && ownedItem.getLevelDecorator().getLevel() != -1 && + (ownerItem.getLevelDecorator().getLevel() - ownedItem.getLevelDecorator().getLevel()) == 1).collect(Collectors.toList()); + ownerList.forEach(ownedItem::addOwner); }); + } - pod.getSpec().getVolumes().forEach(volume -> { - - //storing configmap volumes in labels - if (volume.getConfigMap() != null) { - podItem.setLabel(Label.withPrefix("configMap", volume.getConfigMap().getName()), volume.getConfigMap().getName()); - return; - } - - ItemDescription volumeDesc = createVolumeDescription(group, volume, pod, podItem); - descriptions.add(volumeDesc); + private void crossReferenceVolumes(List persistentVolumeClaimList, List podList) { + persistentVolumeClaimList.forEach(persistentVolume -> { + var owners = new ArrayList(); + owners = (ArrayList) podList.stream().filter(pod -> ((PodItemAdapter) pod.getItemAdapter()).getVolumes().stream().anyMatch(volume -> volume.getPersistentVolumeClaim() != null && volume.getPersistentVolumeClaim().getClaimName().equals(persistentVolume.getName()))).collect(Collectors.toList()); + owners.forEach(persistentVolume::addOwner); }); - - return descriptions; } - private ItemDescription createVolumeDescription(String group, Volume volume, Pod pod, ItemDescription podItem) { - ItemDescription volumeDesc = new ItemDescription(); - volumeDesc.setGroup(group); - volumeDesc.setName(volume.getName()); - volumeDesc.setIdentifier(podItem.getName() + "-" + volume.getName()); - volumeDesc.setType(ItemType.VOLUME); - if (volume.getSecret() != null && volume.getSecret().getSecretName().equals(volume.getName())) { - volumeDesc.setLabel("secret", 1); - volumeDesc.setType(ItemType.SECRET); - } - pod.getMetadata().getLabels().forEach(volumeDesc::setLabel); - - //volume provides the pod - RelationDescription relationDescription = new RelationDescription(volumeDesc.getIdentifier(), podItem.getIdentifier()); - relationDescription.setType(RelationType.PROVIDER); - volumeDesc.addRelation(relationDescription); - - return volumeDesc; + private void crossReferenceOwner(ArrayList itemList) { + itemList.forEach(ownedItem -> { + var owners = new ArrayList(); + owners = (ArrayList) itemList.stream().filter(ownerItem -> ownedItem.getItemAdapter().getOwnerReferences().stream().map(OwnerReference::getUid).collect(Collectors.toList()).contains(ownerItem.getUid())).collect(Collectors.toList()); + owners.forEach(ownedItem::addOwner); + }); } - private void setConditionsAndHealth(PodStatus status, ItemDescription podItem) { - if (status != null && status.getConditions() != null) { - status.getConditions().forEach(podCondition -> { - podItem.setLabel(Label.condition.withPrefix(podCondition.getType()), podCondition.getStatus()); - }); - } + private void crossReferenceClaimer(List persistentVolumeClaims, List persistentVolumes) { + persistentVolumes.forEach(ownedItem -> { + var claimer = persistentVolumeClaims.stream().filter(claimItem -> ((PersistentVolumeItemAdapter) ownedItem.getItemAdapter()).getClaimRef().getUid().equals(claimItem.getUid())).collect(Collectors.toList()); + claimer.forEach(ownedItem::addOwner); + }); } - private String getGroup(HasMetadata hasMetadata) { - if (groupLabel != null) { - String labelValue = hasMetadata.getMetadata().getLabels().getOrDefault(groupLabel, ""); - if (!StringUtils.isEmpty(labelValue)) { - return labelValue; - } - } - - String labelValue = hasMetadata.getMetadata().getLabels().getOrDefault(APP_KUBERNETES_IO_INSTANCE_LABEL, ""); - if (!StringUtils.isEmpty(labelValue)) { - return labelValue; - } + private void crossReferenceService(List service, List owners) { + service.forEach(ownedItem -> { + var claimer = owners.stream().filter(claimItem -> (ownedItem.getName().equals(claimItem.getName()))).collect(Collectors.toList()); + claimer.forEach(ownedItem::addOwner); + }); + } - return ""; + @Override + public InputFormatObserver getObserver(@NonNull final ApplicationEventPublisher eventPublisher, @NonNull final Landscape landscape, @NonNull final SourceReference sourceReference) { + return new KubernetesObserver(landscape, eventPublisher, this.client); } private KubernetesClient getClient(String context) { @@ -274,7 +181,7 @@ private KubernetesClient getClient(String context) { return this.client; // see https://github.com/fabric8io/kubernetes-client#configuring-the-client - Config config = Config.autoConfigure(context); + var config = Config.autoConfigure(context); this.client = new DefaultKubernetesClient(config); return this.client; diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sConfig.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sConfig.java new file mode 100644 index 000000000..4ff909175 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sConfig.java @@ -0,0 +1,42 @@ +package de.bonndan.nivio.input.kubernetes; + +import java.util.Map; + +public class K8sConfig { + private boolean active; + private int minMatchingLabel; + private Map level; + + public K8sConfig() { + } + + public K8sConfig(boolean active, int minMatchingLabel, Map level) { + this.active = active; + this.minMatchingLabel = minMatchingLabel; + this.level = level; + } + + public boolean isActive() { + return active; + } + + public int getMinMatchingLabel() { + return minMatchingLabel; + } + + public Map getLevel() { + return level; + } + + public void setMinMatchingLabel(int minMatchingLabel) { + this.minMatchingLabel = minMatchingLabel; + } + + public void setLevel(Map level) { + this.level = level; + } + + public void setActive(boolean active) { + this.active = active; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java new file mode 100644 index 000000000..618600175 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItem.java @@ -0,0 +1,100 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.dto.RelationDescription; +import de.bonndan.nivio.input.kubernetes.details.Details; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.status.Status; +import org.springframework.lang.NonNull; + +import java.util.*; + +/** + * The K8sItem Class is intended to unify the K8s Objects up to an certain point and to store relation data between those. + */ + +public class K8sItem { + private final List relationDescriptionList = new ArrayList<>(); + private final Map labelMap = new HashMap<>(); + private final List owners = new ArrayList<>(); + + private final LevelDecorator levelDecorator; + private final ItemAdapter itemAdapter; + private final Details details; + private final Status status; + private final String type; + + public K8sItem(String type, ItemAdapter itemAdapter, Status status, Details details) { + this.levelDecorator = new LevelDecorator(K8sJsonParser.getExperimentalLevel(itemAdapter.getClass())); + this.itemAdapter = itemAdapter; + this.details = details; + this.status = status; + this.type = type; + } + + public void addOwner(@NonNull K8sItem owner) { + this.owners.add(Objects.requireNonNull(owner)); + } + + public void addRelation(@NonNull RelationDescription relationDescription) { + relationDescriptionList.add(Objects.requireNonNull(relationDescription)); + } + + public void addStatus(@NonNull String key, @NonNull String value) { + labelMap.put(Objects.requireNonNull(key), Objects.requireNonNull(value)); + } + + @NonNull + public String getGroup() { + if (this.getOwner().isEmpty()) { + return itemAdapter.getName(); + } else { + return this.getOwner().get(0).getGroup(); + } + } + + public LevelDecorator getLevelDecorator() { + return levelDecorator; + } + + @NonNull + public String getName() { + return itemAdapter.getName(); + } + + @NonNull + public List getOwner() { + return owners; + } + + @NonNull + public List getRelationDescriptionList() { + return relationDescriptionList; + } + + @NonNull + public Map getDetails() { + var newLabelMap = new HashMap(); + if (status != null) { + newLabelMap.putAll(status.getExtendedStatus(labelMap, itemAdapter)); + } + var test = details.getExtendedDetails(labelMap, itemAdapter); + newLabelMap.putAll(test); + return newLabelMap; + } + + @NonNull + public String getType() { + return type; + } + + @NonNull + public String getUid() { + return itemAdapter.getUid(); + } + + @NonNull + public ItemAdapter getItemAdapter() { + return itemAdapter; + } + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java new file mode 100644 index 000000000..488bf44e3 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sItemBuilder.java @@ -0,0 +1,34 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.kubernetes.details.DefaultDetails; +import de.bonndan.nivio.input.kubernetes.details.Details; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.status.Status; + +public class K8sItemBuilder { + private final String type; + private final ItemAdapter itemAdapter; + private Details details; + private Status status; + + public K8sItemBuilder(String type, ItemAdapter itemAdapter) { + this.details = new DefaultDetails(); + this.itemAdapter = itemAdapter; + this.status = null; + this.type = type; + } + + public K8sItemBuilder addStatus(Status status) { + this.status = status; + return this; + } + + public K8sItemBuilder addDetails(Details details) { + this.details = details; + return this; + } + + public K8sItem build() { + return new K8sItem(type, itemAdapter, status, details); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java new file mode 100644 index 000000000..660cccd28 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/K8sJsonParser.java @@ -0,0 +1,59 @@ +package de.bonndan.nivio.input.kubernetes; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Map; + +/** + * Parses config values for the crossReferenceLabel feature + */ + +public class K8sJsonParser { + + private static final Logger LOGGER = LoggerFactory.getLogger(K8sJsonParser.class); + private static final String FILEPATH = "src/main/resources/k8sLabelConfig.json"; + private static K8sConfig k8sConfig; + + static { + k8sConfig = getK8sConfig(); + } + + private K8sJsonParser() { + } + + private static K8sConfig getK8sConfig() { + if (k8sConfig != null) { + return k8sConfig; + } else { + try { + var testMapper = new ObjectMapper(); + k8sConfig = testMapper.readValue(new File(FILEPATH), K8sConfig.class); + return k8sConfig; + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } + } + k8sConfig = new K8sConfig(false, 0, Map.of()); + return k8sConfig; + } + + public static boolean getExperimentalActive() { + return getK8sConfig().isActive(); + } + + public static int getMinMatchingLevel() { + return getK8sConfig().getMinMatchingLabel(); + } + + public static int getExperimentalLevel(Class classToParse) { + return getExperimentalLevelFromJSON(classToParse.getSimpleName()); + } + + private static int getExperimentalLevelFromJSON(String objectName) { + return getK8sConfig().getLevel().getOrDefault(objectName, -1); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/LevelDecorator.java b/src/main/java/de/bonndan/nivio/input/kubernetes/LevelDecorator.java new file mode 100644 index 000000000..32984f9e9 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/LevelDecorator.java @@ -0,0 +1,13 @@ +package de.bonndan.nivio.input.kubernetes; + +public class LevelDecorator { + int level; + + public LevelDecorator(int level) { + this.level = level; + } + + public int getLevel() { + return level; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java new file mode 100644 index 000000000..3505fe12b --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetails.java @@ -0,0 +1,23 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class DefaultDetails implements Details { + + @NonNull + @Override + public Map getExtendedDetails(@Nullable Map statusMap, @NonNull ItemAdapter itemAdapter) { + Objects.requireNonNull(itemAdapter); + var labels = new HashMap(); + labels.putIfAbsent("name", itemAdapter.getName()); + labels.putIfAbsent("namespace", itemAdapter.getNamespace()); + labels.putIfAbsent("creation", itemAdapter.getCreationTimestamp()); + return labels; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java new file mode 100644 index 000000000..753238efe --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetails.java @@ -0,0 +1,29 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public class DeploymentDetails extends DetailDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(DeploymentDetails.class); + + public DeploymentDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + try { + newDetailMap.put("strategy", ((DeploymentItemAdapter) itemAdapter).getStrategyType()); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); + } + return newDetailMap; + } + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/DetailDecorator.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DetailDecorator.java new file mode 100644 index 000000000..d3011ee2d --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/DetailDecorator.java @@ -0,0 +1,9 @@ +package de.bonndan.nivio.input.kubernetes.details; + +public abstract class DetailDecorator implements Details { + protected Details detail; + + protected DetailDecorator(Details detail) { + this.detail = detail; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java new file mode 100644 index 000000000..78d30ef52 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/Details.java @@ -0,0 +1,9 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; + +import java.util.Map; + +public interface Details { + Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter); +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java new file mode 100644 index 000000000..013f73f0a --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetails.java @@ -0,0 +1,31 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public class PersistentVolumeClaimDetails extends DetailDecorator { + + private static final Logger LOGGER = LoggerFactory.getLogger(PersistentVolumeClaimDetails.class); + + public PersistentVolumeClaimDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + try { + var persistentVolumeClaim = (PersistentVolumeClaimItemAdapter) itemAdapter; + mewDetailMap.put("phase status", persistentVolumeClaim.getPhase()); + mewDetailMap.put("storage class", persistentVolumeClaim.getStorageClassName()); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); + } + return mewDetailMap; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java new file mode 100644 index 000000000..5f6365e3c --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetails.java @@ -0,0 +1,38 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public class PersistentVolumeDetails extends DetailDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(PersistentVolumeDetails.class); + + public PersistentVolumeDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var newDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + try { + var persistentVolume = (PersistentVolumeItemAdapter) itemAdapter; + newDetailMap.put("phase status", persistentVolume.getPhase()); + newDetailMap.put("storage class", persistentVolume.getStorageClassName()); + newDetailMap.put("reclaim policy", persistentVolume.getPersistentVolumeReclaimPolicy()); + var accessMode = new StringBuilder(); + for (String entity : persistentVolume.getAccessModes()) { + accessMode.append(entity); + } + newDetailMap.put("storage mode", accessMode.toString()); + persistentVolume.getCapacity().forEach((key, value) -> newDetailMap.put(key, value.getAmount() + value.getFormat())); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); + } + + return newDetailMap; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java b/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java new file mode 100644 index 000000000..742ab84d8 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetails.java @@ -0,0 +1,33 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public class ServiceDetails extends DetailDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceDetails.class); + + + public ServiceDetails(Details detail) { + super(detail); + } + + @Override + public Map getExtendedDetails(Map statusMap, ItemAdapter itemAdapter) { + var mewDetailMap = new HashMap<>(detail.getExtendedDetails(statusMap, itemAdapter)); + + try { + var service = (ServiceItemAdapter) itemAdapter; + mewDetailMap.put("cluster ip", service.getClusterIP()); + mewDetailMap.put("service type", service.getType()); + mewDetailMap.put("session affinity", service.getSessionAffinity()); + } catch (ClassCastException e) { + LOGGER.warn(e.getMessage()); + } + return mewDetailMap; + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java new file mode 100644 index 000000000..69edbef85 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/DeploymentItemAdapter.java @@ -0,0 +1,52 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + + +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.apps.Deployment; + +import java.util.List; +import java.util.Map; + +public class DeploymentItemAdapter implements ItemAdapter { + private final Deployment deployment; + + public DeploymentItemAdapter(Deployment deployment) { + this.deployment = deployment; + } + + @Override + public Map getLabels() { + return deployment.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return deployment.getMetadata().getOwnerReferences(); + } + + @Override + public String getUid() { + return deployment.getMetadata().getUid(); + } + + @Override + public String getName() { + return deployment.getMetadata().getName(); + } + + @Override + public String getNamespace() { + return deployment.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return deployment.getMetadata().getCreationTimestamp(); + } + + public String getStrategyType() { + return deployment.getSpec().getStrategy().getType(); + } + + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java new file mode 100644 index 000000000..c81871b69 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ItemAdapter.java @@ -0,0 +1,21 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import io.fabric8.kubernetes.api.model.OwnerReference; + +import java.util.List; +import java.util.Map; + +public interface ItemAdapter { + + Map getLabels(); + + String getUid(); + + String getName(); + + String getNamespace(); + + String getCreationTimestamp(); + + List getOwnerReferences(); +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java new file mode 100644 index 000000000..5cc47ddc1 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeClaimItemAdapter.java @@ -0,0 +1,55 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.PersistentVolumeClaim; + +import java.util.List; +import java.util.Map; + +public class PersistentVolumeClaimItemAdapter implements ItemAdapter { + private final PersistentVolumeClaim persistentVolumeClaim; + + public PersistentVolumeClaimItemAdapter(PersistentVolumeClaim persistentVolumeClaim) { + this.persistentVolumeClaim = persistentVolumeClaim; + } + + @Override + public Map getLabels() { + return persistentVolumeClaim.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return persistentVolumeClaim.getMetadata().getOwnerReferences(); + } + + @Override + public String getName() { + return persistentVolumeClaim.getMetadata().getName(); + } + + @Override + public String getUid() { + return persistentVolumeClaim.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return persistentVolumeClaim.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return persistentVolumeClaim.getMetadata().getCreationTimestamp(); + } + + public String getPhase() { + return persistentVolumeClaim.getStatus().getPhase(); + } + + public String getStorageClassName() { + return persistentVolumeClaim.getSpec().getStorageClassName(); + } + + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java new file mode 100644 index 000000000..89dced07f --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PersistentVolumeItemAdapter.java @@ -0,0 +1,72 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import io.fabric8.kubernetes.api.model.ObjectReference; +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.PersistentVolume; +import io.fabric8.kubernetes.api.model.Quantity; + +import java.util.List; +import java.util.Map; + +public class PersistentVolumeItemAdapter implements ItemAdapter { + private final PersistentVolume persistentVolume; + + public PersistentVolumeItemAdapter(PersistentVolume persistentVolume) { + this.persistentVolume = persistentVolume; + } + + @Override + public Map getLabels() { + return persistentVolume.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return persistentVolume.getMetadata().getOwnerReferences(); + } + + @Override + public String getName() { + return persistentVolume.getMetadata().getName(); + } + + @Override + public String getUid() { + return persistentVolume.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return persistentVolume.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return persistentVolume.getMetadata().getCreationTimestamp(); + } + + public String getPhase() { + return persistentVolume.getStatus().getPhase(); + } + + public String getStorageClassName() { + return persistentVolume.getSpec().getStorageClassName(); + } + + public String getPersistentVolumeReclaimPolicy() { + return persistentVolume.getSpec().getPersistentVolumeReclaimPolicy(); + } + + public List getAccessModes() { + return persistentVolume.getSpec().getAccessModes(); + } + + public Map getCapacity() { + return persistentVolume.getSpec().getCapacity(); + } + + public ObjectReference getClaimRef() { + return persistentVolume.getSpec().getClaimRef(); + } + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java new file mode 100644 index 000000000..cafe509cd --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/PodItemAdapter.java @@ -0,0 +1,52 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.Volume; + +import java.util.List; +import java.util.Map; + +public class PodItemAdapter implements ItemAdapter { + private final Pod pod; + + public PodItemAdapter(Pod pod) { + this.pod = pod; + } + + @Override + public Map getLabels() { + return pod.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return pod.getMetadata().getOwnerReferences(); + } + + @Override + public String getName() { + return pod.getMetadata().getName(); + } + + @Override + public String getUid() { + return pod.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return pod.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return pod.getMetadata().getCreationTimestamp(); + } + + public List getVolumes() { + return pod.getSpec().getVolumes(); + } + + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java new file mode 100644 index 000000000..ebf8a7f92 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ReplicaSetItemAdapter.java @@ -0,0 +1,56 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + + +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.apps.ReplicaSet; + +import java.util.List; +import java.util.Map; + +public class ReplicaSetItemAdapter implements ItemAdapter { + private final ReplicaSet replicaSet; + + public ReplicaSetItemAdapter(ReplicaSet replicaSet) { + this.replicaSet = replicaSet; + } + + @Override + public Map getLabels() { + return replicaSet.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return replicaSet.getMetadata().getOwnerReferences(); + } + + @Override + public String getName() { + return replicaSet.getMetadata().getName(); + } + + @Override + public String getUid() { + return replicaSet.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return replicaSet.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return replicaSet.getMetadata().getCreationTimestamp(); + } + + public Integer getReadyReplicas() { + return replicaSet.getStatus().getReadyReplicas(); + } + + public Integer getReplicas() { + return replicaSet.getSpec().getReplicas(); + } + + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java new file mode 100644 index 000000000..7fa8e8298 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/ServiceItemAdapter.java @@ -0,0 +1,59 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.Service; + +import java.util.List; +import java.util.Map; + +public class ServiceItemAdapter implements ItemAdapter { + private final Service service; + + public ServiceItemAdapter(Service service) { + this.service = service; + } + + @Override + public Map getLabels() { + return service.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return service.getMetadata().getOwnerReferences(); + } + + @Override + public String getName() { + return service.getMetadata().getName(); + } + + @Override + public String getUid() { + return service.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return service.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return service.getMetadata().getCreationTimestamp(); + } + + public String getClusterIP() { + return service.getSpec().getClusterIP(); + } + + public String getType() { + return service.getSpec().getType(); + } + + public String getSessionAffinity() { + return service.getSpec().getSessionAffinity(); + } + + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java new file mode 100644 index 000000000..b0bb658b2 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/itemadapters/StatefulSetItemAdapter.java @@ -0,0 +1,55 @@ +package de.bonndan.nivio.input.kubernetes.itemadapters; + +import io.fabric8.kubernetes.api.model.OwnerReference; +import io.fabric8.kubernetes.api.model.apps.StatefulSet; + +import java.util.List; +import java.util.Map; + +public class StatefulSetItemAdapter implements ItemAdapter { + private final StatefulSet statefulSet; + + public StatefulSetItemAdapter(StatefulSet statefulSet) { + this.statefulSet = statefulSet; + } + + @Override + public Map getLabels() { + return statefulSet.getMetadata().getLabels(); + } + + @Override + public List getOwnerReferences() { + return statefulSet.getMetadata().getOwnerReferences(); + } + + @Override + public String getName() { + return statefulSet.getMetadata().getName(); + } + + @Override + public String getUid() { + return statefulSet.getMetadata().getUid(); + } + + @Override + public String getNamespace() { + return statefulSet.getMetadata().getNamespace(); + } + + @Override + public String getCreationTimestamp() { + return statefulSet.getMetadata().getCreationTimestamp(); + } + + public Integer getReadyReplicas() { + return statefulSet.getStatus().getReadyReplicas(); + } + + public Integer getReplicas() { + return statefulSet.getSpec().getReplicas(); + } + + +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java new file mode 100644 index 000000000..0c167c9dc --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/BoolStatus.java @@ -0,0 +1,21 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; + +public class BoolStatus implements Status { + + @Override + public Map getExtendedStatus(@NonNull Map statusMap, @Nullable ItemAdapter itemAdapter) { + return statusMap.entrySet().stream().collect(Collectors.toMap( + pair -> InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition." + pair.getKey().toLowerCase(), + pair -> pair.getValue().toLowerCase(Locale.ROOT) + )); + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java new file mode 100644 index 000000000..a7267f882 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatus.java @@ -0,0 +1,25 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter; +import org.springframework.lang.NonNull; + +import java.util.Map; + +public class ReplicaStatus implements Status { + + @Override + public Map getExtendedStatus(@NonNull Map statusMap, @NonNull ItemAdapter itemAdapter) { + if (itemAdapter instanceof ReplicaSetItemAdapter) { + var concreteItem = (ReplicaSetItemAdapter) itemAdapter; + return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); + } else if (itemAdapter instanceof StatefulSetItemAdapter) { + var concreteItem = (StatefulSetItemAdapter) itemAdapter; + return Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", concreteItem.getReadyReplicas() + ";" + concreteItem.getReplicas()); + } else { + return statusMap; + } + } +} diff --git a/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java b/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java new file mode 100644 index 000000000..8acf3ce6f --- /dev/null +++ b/src/main/java/de/bonndan/nivio/input/kubernetes/status/Status.java @@ -0,0 +1,9 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; + +import java.util.Map; + +public interface Status { + Map getExtendedStatus(Map statusMap, ItemAdapter itemAdapter); +} diff --git a/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java b/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java index 94cb8d027..de6220445 100644 --- a/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java +++ b/src/main/java/de/bonndan/nivio/input/nivio/InputFormatHandlerNivio.java @@ -3,20 +3,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; import de.bonndan.nivio.input.FileFetcher; import de.bonndan.nivio.input.InputFormatHandler; +import de.bonndan.nivio.input.Mappers; import de.bonndan.nivio.input.ReadingException; -import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.observation.InputFormatObserver; -import de.bonndan.nivio.input.Mappers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.lang.Nullable; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -41,9 +38,8 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription description) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription description) { - List descriptions = new ArrayList<>(); String yml = fileFetcher.get(reference, baseUrl); Source source; try { @@ -54,7 +50,7 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti } if (source == null) { - logger.warn("Got null out of yml string " + yml); + logger.warn("Got null out of yml string {}", yml); return; } @@ -66,10 +62,4 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti } } - - @Override - @Nullable - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { - return inner; - } } diff --git a/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java b/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java index 8e60ec2b2..73a53a9d4 100644 --- a/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java +++ b/src/main/java/de/bonndan/nivio/input/rancher1/APIWalker.java @@ -147,7 +147,7 @@ private List asDescriptions(List data, final Map getFormats() { - return Arrays.asList("rancher1-prometheus"); + return Collections.singletonList("rancher1-prometheus"); } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { String landscape = reference.getLandscapeDescription().getIdentifier(); @@ -42,8 +43,12 @@ public void applyData(SourceReference reference, URL baseUrl, LandscapeDescripti } @Override - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference sourceReference) { - //TODO add observer - return null; + public InputFormatObserver getObserver(@NonNull final ApplicationEventPublisher eventPublisher, + @NonNull final Landscape landscape, + @NonNull final SourceReference sourceReference) { + //TODO add observer, or maybe not, since it is deprecated + return () -> { + + }; } } diff --git a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java index b356f327e..0270af63b 100644 --- a/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java +++ b/src/main/java/de/bonndan/nivio/input/rancher1/InputFormatHandlerRancher1API.java @@ -1,13 +1,11 @@ package de.bonndan.nivio.input.rancher1; import de.bonndan.nivio.input.InputFormatHandler; -import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.ProcessingException; -import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.observation.InputFormatObserver; import io.rancher.Rancher; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -28,18 +26,11 @@ public List getFormats() { } @Override - public void applyData(SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { + public void applyData(@NonNull SourceReference reference, URL baseUrl, LandscapeDescription landscapeDescription) { APIWalker apiWalker = new APIWalker(reference, getConfig(reference)); landscapeDescription.mergeItems(apiWalker.getDescriptions()); } - @Override - public InputFormatObserver getObserver(InputFormatObserver inner, SourceReference reference) { - Rancher.Config config = getConfig(reference); - //TODO add observer - return null; - } - private Rancher.Config getConfig(SourceReference reference) { Rancher.Config config; String accessKey = (String) reference.getProperty(API_ACCESS_KEY); diff --git a/src/main/java/de/bonndan/nivio/model/Component.java b/src/main/java/de/bonndan/nivio/model/Component.java index 4b191fcf1..88cc9cc65 100644 --- a/src/main/java/de/bonndan/nivio/model/Component.java +++ b/src/main/java/de/bonndan/nivio/model/Component.java @@ -60,6 +60,4 @@ public interface Component { @Nullable String getColor(); - @Nullable - String getAddress(); } diff --git a/src/main/java/de/bonndan/nivio/model/Group.java b/src/main/java/de/bonndan/nivio/model/Group.java index 617a4049f..c974d5d07 100644 --- a/src/main/java/de/bonndan/nivio/model/Group.java +++ b/src/main/java/de/bonndan/nivio/model/Group.java @@ -1,9 +1,5 @@ package de.bonndan.nivio.model; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import de.bonndan.nivio.assessment.Assessable; -import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.output.Color; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; @@ -20,7 +16,7 @@ * * Each item can only be member of one group. */ -public class Group implements Labeled, Linked, Assessable { +public class Group implements Component, Labeled, Linked { /** * Default group identifier (items are assigned to this group if no group is given @@ -38,7 +34,7 @@ public class Group implements Labeled, Linked, Assessable { * Items belonging to this group. Order is important for layouting (until items are ordered there). */ @NonNull - private final Set items = new LinkedHashSet<>(); + private final Set items = new LinkedHashSet<>(); @NonNull private final String identifier; @@ -46,7 +42,6 @@ public class Group implements Labeled, Linked, Assessable { private final String owner; private final String description; private final String contact; - private final String icon; private final String color; /** @@ -55,7 +50,6 @@ public class Group implements Labeled, Linked, Assessable { * @param owner owner * @param description description * @param contact contact - * @param icon icon * @param color color, usually member items inherit it */ public Group(@NonNull final String identifier, @@ -63,27 +57,25 @@ public Group(@NonNull final String identifier, @Nullable final String owner, @Nullable final String description, @Nullable final String contact, - @Nullable final String icon, @Nullable final String color ) { - if (StringUtils.isEmpty(identifier)) { + if (!StringUtils.hasLength(identifier)) { throw new IllegalArgumentException("Group identifier must not be empty"); } this.identifier = identifier; - if (StringUtils.isEmpty(landscapeIdentifier)) { + if (!StringUtils.hasLength(landscapeIdentifier)) { throw new IllegalArgumentException("Landscape identifier must not be empty"); } this.landscapeIdentifier = landscapeIdentifier; this.owner = owner; this.description = description; this.contact = contact; - this.icon = icon; this.color = Color.safe(color); } public Group(@NonNull final String identifier, @NonNull final String landscapeIdentifier) { - this(identifier, landscapeIdentifier, null, null, null, null, Color.getGroupColor(identifier)); + this(identifier, landscapeIdentifier, null, null, null, Color.getGroupColor(identifier)); } @Override @@ -127,48 +119,26 @@ public String getColor() { return color; } - @JsonIgnore - @Override - public String getAddress() { - return null; - } - @Schema(name = "_links") public Map getLinks() { return links; } /** - * Returns an immutable copy of the items. + * Returns a copy of the items. * * @return immutable copy */ - public Set getItems() { - return Collections.unmodifiableSet(items); + public Set getItems() { + return new LinkedHashSet<>(items); } - @JsonIgnore @Override @NonNull public Map getLabels() { return labels; } - /** - * Returns the labels without the internal ones (having prefixes). - * - * @return filtered labels - */ - @JsonProperty("labels") - public Map getJSONLabels() { - - return Labeled.groupedByPrefixes( - Labeled.withoutKeys(labels, Label.condition.name(), Label.status.name(), Tagged.LABEL_PREFIX_TAG), - "," - ); - } - - @Override @Nullable public String getLabel(String key) { @@ -180,22 +150,9 @@ public void setLabel(String key, String value) { labels.put(key, value); } - @Override - @NonNull - public Set getAdditionalStatusValues() { - return StatusValue.fromMapping(indexedByPrefix(Label.status)); - } - - @JsonIgnore - @Override - @NonNull - public List getChildren() { - return new ArrayList<>(getItems()); - } - @Override public String getIcon() { - return icon; + return getLabel(Label._icondata); } @Override @@ -211,12 +168,15 @@ public String toString() { * @param item the item to add. * @throws IllegalArgumentException if the item group field mismatches */ - public void addItem(Item item) { - if (!item.getGroup().equals(identifier)) { + public void addOrReplaceItem(Item item) { + if (!identifier.equals(item.getGroup())) { throw new IllegalArgumentException(String.format("Item group '%s' cannot be added to group '%s'", item.getGroup(), identifier)); } - items.add(item); + //ensures that an existing item is removed from set + FullyQualifiedIdentifier fqi = item.getFullyQualifiedIdentifier(); + items.stream().filter(item1 -> item1.equals(fqi)).findFirst().ifPresent(items::remove); + items.add(fqi); } /** @@ -229,7 +189,7 @@ public boolean removeItem(@Nullable Item item) { if (item == null) { return false; } - return items.remove(item); + return items.remove(item.getFullyQualifiedIdentifier()); } public String getLandscapeIdentifier() { diff --git a/src/main/java/de/bonndan/nivio/model/GroupBuilder.java b/src/main/java/de/bonndan/nivio/model/GroupBuilder.java index 463edbba6..0688c16ba 100644 --- a/src/main/java/de/bonndan/nivio/model/GroupBuilder.java +++ b/src/main/java/de/bonndan/nivio/model/GroupBuilder.java @@ -3,14 +3,13 @@ import java.util.HashMap; import java.util.Map; -final class GroupBuilder { +public final class GroupBuilder { private Map links = new HashMap<>(); private String identifier; private String landscapeIdentifier; private String owner; private String description; private String contact; - private String icon; private String color; private Map labels = new HashMap<>(); @@ -51,11 +50,6 @@ public GroupBuilder withContact(String contact) { return this; } - public GroupBuilder withIcon(String icon) { - this.icon = icon; - return this; - } - public GroupBuilder withColor(String color) { this.color = color; return this; @@ -67,7 +61,7 @@ public GroupBuilder withLabels(Map labels) { } public Group build() { - Group group = new Group(identifier, landscapeIdentifier, owner, description, contact, icon, color); + Group group = new Group(identifier, landscapeIdentifier, owner, description, contact, color); group.setLinks(links); group.getLabels().putAll(labels); return group; diff --git a/src/main/java/de/bonndan/nivio/model/GroupFactory.java b/src/main/java/de/bonndan/nivio/model/GroupFactory.java index 94df0f2ba..4f64faa9e 100644 --- a/src/main/java/de/bonndan/nivio/model/GroupFactory.java +++ b/src/main/java/de/bonndan/nivio/model/GroupFactory.java @@ -19,13 +19,12 @@ public class GroupFactory { * @param added group that carries additional values * @return a new group, or the first one if the second one is null */ - public static Group merge(final Group group, Group added) { + public static Group merge(final Group group, final Group added) { GroupBuilder builder = getBuilder(group); if (added != null) { assignSafeIfAbsent(added.getColor(), group.getColor(), builder::withColor); - assignSafeIfAbsent(added.getIcon(), group.getIcon(), builder::withIcon); assignSafeIfAbsent(added.getContact(), group.getContact(), builder::withContact); assignSafeIfAbsent(added.getDescription(), group.getDescription(), builder::withDescription); assignSafeIfAbsent(added.getOwner(), group.getOwner(), builder::withOwner); @@ -57,7 +56,7 @@ public static Group createFromDescription(@NonNull final String groupIdentifier, } - if (StringUtils.isEmpty(builder.getColor())) { + if (!StringUtils.hasLength(builder.getColor())) { builder.withColor(Color.getGroupColor(builder.getIdentifier())); } @@ -72,7 +71,6 @@ private static GroupBuilder getBuilder(Group group) { .withOwner(group.getOwner()) .withContact(group.getContact()) .withColor(group.getColor()) - .withIcon(group.getIcon()) .withLandscapeIdentifier(group.getLandscapeIdentifier()) .withLinks(group.getLinks()) .withLabels(group.getLabels()); diff --git a/src/main/java/de/bonndan/nivio/model/Item.java b/src/main/java/de/bonndan/nivio/model/Item.java index 9f8583c87..a87f69491 100644 --- a/src/main/java/de/bonndan/nivio/model/Item.java +++ b/src/main/java/de/bonndan/nivio/model/Item.java @@ -1,11 +1,13 @@ package de.bonndan.nivio.model; -import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonManagedReference; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; import de.bonndan.nivio.assessment.Assessable; import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.input.ItemRelationProcessor; import de.bonndan.nivio.output.Color; -import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; @@ -19,7 +21,7 @@ import static de.bonndan.nivio.model.ComponentDiff.*; @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "fullyQualifiedIdentifier") -@JsonInclude(JsonInclude.Include.NON_NULL) +//needed when internal models are serialized for debugging public class Item implements Linked, Tagged, Labeled, Assessable, ItemComponent { public static final String LAYER_INFRASTRUCTURE = "infrastructure"; @@ -33,8 +35,7 @@ public class Item implements Linked, Tagged, Labeled, Assessable, ItemComponent private final String identifier; @NotNull - @JsonIgnore - @Schema(hidden = true) + @JsonIgnore //needed when internal models are serialized for debugging private final Landscape landscape; private final String name; @@ -47,6 +48,8 @@ public class Item implements Linked, Tagged, Labeled, Assessable, ItemComponent private final String group; + private final String type; + /** * technical address */ @@ -64,32 +67,33 @@ public class Item implements Linked, Tagged, Labeled, Assessable, ItemComponent @JsonManagedReference private Set interfaces = new HashSet<>(); - public Item(@NotNull final String identifier, - @NotNull final Landscape landscape, - @NotNull final String group, + public Item(final String identifier, + final Landscape landscape, + final String group, final String name, final String owner, final String contact, final String description, final String color, final String icon, + final String type, final URI address ) { - if (StringUtils.isEmpty(identifier)) { - throw new RuntimeException("Identifier must not be empty"); + if (!StringUtils.hasLength(identifier)) { + throw new IllegalArgumentException("Identifier must not be empty"); } this.identifier = identifier.toLowerCase(); this.landscape = Objects.requireNonNull(landscape, "Landscape must not be null"); - if (StringUtils.isEmpty(group)) { - throw new RuntimeException("Group identifier must not be empty"); + if (!StringUtils.hasLength(group)) { + throw new IllegalArgumentException("Group identifier must not be empty"); } this.group = group; - this.name = name; this.owner = owner; this.contact = contact; this.description = description; + this.type = type; this.address = address; //these are effectively mutable @@ -136,7 +140,6 @@ public String getContact() { return contact; } - @Schema(name = "_links") public Map getLinks() { return links; } @@ -150,35 +153,25 @@ public String getDescription() { return description; } - @JsonIgnore + @NonNull @Override public Map getLabels() { return labels; } - /** - * Returns the labels without the internal ones (having prefixes). - * - * @return filtered labels - */ - @JsonProperty("labels") - public Map getJSONLabels() { - return Labeled.withoutKeys(labels, Label.condition.name(), Label.status.name(), Tagged.LABEL_PREFIX_TAG, Label.type.name(), Label.icon.name()); - } - /** * Returns the relations. * * @return immutable set */ - @JsonIgnore + @JsonIgnore //needed for internal debugging public Set getRelations() { return Set.copyOf(relations); } /** * Adds a relation or replaces the similar one. - * + *

* This is necessary because {@link Set} does not replace AND we need to check relation end equality on object level * because referenced source or target items will be replaced by new copies. * @@ -186,7 +179,7 @@ public Set getRelations() { */ public void addOrReplace(@NonNull final Relation relation) { if (relation.getSource() != this && relation.getTarget() != this) { - throw new IllegalArgumentException("Relation contains no reference to item."); + throw new IllegalArgumentException(String.format("Relation contains no reference to item.%s %s", relation.getIdentifier(), this)); } getSimilar(relation).map(relations::remove); @@ -211,25 +204,13 @@ private Optional getSimilar(Relation relation) { .findFirst(); } - @JsonProperty("relations") - public Map getJSONRelations() { - Map map = new HashMap<>(); - - relations.forEach(relation -> { - Relation.ApiModel apiModel = new Relation.ApiModel(relation, this); - map.put(apiModel.id, apiModel); - }); - - return map; - } - void setRelations(Set outgoing) { this.relations.clear(); this.relations.addAll(outgoing); } public String getType() { - return getLabel(Label.type); + return type; } public String getAddress() { @@ -245,7 +226,6 @@ public Set getInterfaces() { } @Override - @JsonAnyGetter public String getLabel(String key) { return labels.get(key); } @@ -256,7 +236,6 @@ public Map getLabels(String prefix) { } @Override - @JsonAnySetter public void setLabel(String key, String value) { labels.put(key, value); } @@ -296,10 +275,22 @@ public String toString() { } @Override + @NonNull public Set getAdditionalStatusValues() { - return StatusValue.fromMapping(indexedByPrefix(Label.status)); + return StatusValue.fromMapping(getAssessmentIdentifier(), indexedByPrefix(Label.status)); } + @Override + @NonNull + public String getAssessmentIdentifier() { + return getFullyQualifiedIdentifier().toString(); + } + + @Override + @NonNull + public List getChildren() { + return getRelations().stream().filter(relation -> relation.getSource().equals(this)).collect(Collectors.toList()); + } /** * Compare on field level against a newer version. @@ -318,6 +309,7 @@ public List getChanges(final Item newer) { changes.addAll(compareStrings(this.description, newer.description, "Description")); changes.addAll(compareStrings(this.name, newer.name, "Name")); changes.addAll(compareStrings(this.owner, newer.owner, "Owner")); + changes.addAll(compareStrings(this.type, newer.type, "Type")); changes.addAll(compareOptionals(Optional.ofNullable(this.address), Optional.ofNullable(newer.address), "Address")); changes.addAll(compareCollections(this.links.keySet(), newer.links.keySet(), "Links")); changes.addAll(newer.diff(this)); @@ -330,4 +322,4 @@ public List getChanges(final Item newer) { } -} +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/model/ItemBuilder.java b/src/main/java/de/bonndan/nivio/model/ItemBuilder.java index 68423a700..62ae1d781 100644 --- a/src/main/java/de/bonndan/nivio/model/ItemBuilder.java +++ b/src/main/java/de/bonndan/nivio/model/ItemBuilder.java @@ -20,6 +20,7 @@ public final class ItemBuilder { private String group; private String color; private String icon; + private String type; private URI address; private Map labels = new HashMap<>(); @@ -90,6 +91,11 @@ public ItemBuilder withIcon(String icon) { return this; } + public ItemBuilder withType(String type) { + this.type = type; + return this; + } + public ItemBuilder withAddress(URI address) { this.address = address; return this; @@ -97,7 +103,7 @@ public ItemBuilder withAddress(URI address) { public Item build() { Item item = new Item(identifier, landscape, group, name, owner, contact, - description, color, icon, address); + description, color, icon, type, address); item.setLinks(links); item.getLabels().putAll(labels); item.setRelations(relations); @@ -113,4 +119,4 @@ public ItemBuilder withLabels(Map labels) { public String getGroup() { return group; } -} +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/model/ItemComponent.java b/src/main/java/de/bonndan/nivio/model/ItemComponent.java index b3194c795..9e7ae9356 100644 --- a/src/main/java/de/bonndan/nivio/model/ItemComponent.java +++ b/src/main/java/de/bonndan/nivio/model/ItemComponent.java @@ -11,4 +11,7 @@ public interface ItemComponent extends Component { @Nullable String getGroup(); + + @Nullable + String getAddress(); } diff --git a/src/main/java/de/bonndan/nivio/model/ItemFactory.java b/src/main/java/de/bonndan/nivio/model/ItemFactory.java index 9df2c1279..7700a20ed 100644 --- a/src/main/java/de/bonndan/nivio/model/ItemFactory.java +++ b/src/main/java/de/bonndan/nivio/model/ItemFactory.java @@ -14,20 +14,23 @@ public class ItemFactory { + private ItemFactory() { + } + private static final Logger logger = LoggerFactory.getLogger(ItemFactory.class); public static Item getTestItem(String group, String identifier) { - Landscape landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); + var landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); return getTestItem(group, identifier, landscape); } public static Item getTestItem(String group, String identifier, Landscape landscape) { return new Item(identifier, landscape, group, null,null,null, - null, null, null, null); + null, null, null, null, null); } public static ItemBuilder getTestItemBuilder(String group, String identifier) { - Landscape landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); + var landscape = LandscapeBuilder.aLandscape().withIdentifier("test").withName("test").build(); return ItemBuilder.anItem().withGroup(group).withIdentifier(identifier).withLandscape(landscape); } @@ -42,6 +45,7 @@ public static Item fromDescription(@NonNull ItemDescription description, Landsca .withOwner(description.getOwner()) .withGroup(description.getGroup()) .withIcon(description.getIcon()) + .withType(description.getType()) .withLandscape(landscape); if (description.getAddress() != null) { @@ -55,7 +59,7 @@ public static Item fromDescription(@NonNull ItemDescription description, Landsca builder.withLinks(description.getLinks()); builder.withLabels(description.getLabels()); - if (StringUtils.isEmpty(builder.getGroup())) { + if (!StringUtils.hasLength(builder.getGroup())) { builder.withGroup(Group.COMMON); } return builder.build(); @@ -70,7 +74,7 @@ public static Item fromDescription(@NonNull ItemDescription description, Landsca public static Item assignAll(@NonNull final Item item, @Nullable final ItemDescription description) { Objects.requireNonNull(item, "Item is null"); if (description == null) { - logger.warn(String.format("ItemDescription for item %s is null in assignAllValues", item.getIdentifier())); + logger.warn("ItemDescription for item {} is null in assignAllValues", item.getIdentifier()); return item; } @@ -82,6 +86,7 @@ public static Item assignAll(@NonNull final Item item, @Nullable final ItemDescr .withOwner(item.getOwner()) .withGroup(item.getGroup()) .withIcon(item.getIcon()) + .withType(item.getType()) .withLandscape(item.getLandscape()) .withRelations(item.getRelations()) .withInterfaces(item.getInterfaces()) @@ -100,9 +105,10 @@ public static Item assignAll(@NonNull final Item item, @Nullable final ItemDescr builder.withOwner(description.getOwner()); builder.withColor(description.getColor()); builder.withIcon(description.getIcon()); + builder.withType(description.getType()); builder.withContact(description.getContact()); builder.withLabels(description.getLabels()); return builder.build(); } -} +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/model/Label.java b/src/main/java/de/bonndan/nivio/model/Label.java index 189026bbe..0a17d34b1 100644 --- a/src/main/java/de/bonndan/nivio/model/Label.java +++ b/src/main/java/de/bonndan/nivio/model/Label.java @@ -15,19 +15,23 @@ public enum Label { capability("The capability the service provides for the business or, in case of infrastructure," + " the technical capability like enabling service discovery, configuration, secrets, or persistence."), - color("A hex color code to override the inherited group color"), + color("A hex color code (items inherit group colors as default)"), costs("Running costs of the item."), fill("Background image (for displaying purposes)."), + _filldata("Background image resolved to a data-url."), framework("A map of used frameworks (key is name, value is version).", true), frameworks("A comma-separated list of frameworks as key-value pairs (key is name, value is version)."), icon("Icon/image (for displaying purposes)."), + _icondata("Icon/image resolved to a data-url"), health("Description of the item's health status."), + label("A custom label (like a note, but very short)."), + layer("A technical layer."), lifecycle("A lifecycle phase (``PLANNED|plan``, ``INTEGRATION|int``, ``PRODUCTION|prod``, ``END_OF_LIFE|eol|end``)."), @@ -46,8 +50,6 @@ public enum Label { team("Name of the responsible team (e.g. technical owner)."), - type("The type (service, database, queue, load balancer, etc.)."), - version("The version (e.g. software version or protocol version)."), visibility("Visibility to other items."), @@ -56,13 +58,22 @@ public enum Label { status("Prefix for status labels. Can be used as prefix for all other labels to mark a status for the label.", true), - condition("Prefix for condition labels.", true); + _condition("Prefix for condition labels.", true), + + weight("Importance or relations. Used as factor for drawn width if numbers between 0 and 5 are given.") + + ; /** * Separator for label key parts. * Should not be used outside this package. Use key() methods instead. */ - static final String DELIMITER = "."; + public static final String DELIMITER = "."; + + /** + * Internal labels start with an underscore. They are not diffed and not part of the public api. + */ + public static final String INTERNAL_LABEL_PREFIX = "_"; public final String meaning; public final boolean isPrefix; @@ -113,6 +124,7 @@ public static Map export(boolean includePrefixes) { List

* Outgoing flows having a target which matches a service identifier will cause a relation to be created. */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class Relation implements Serializable { +public class Relation implements Labeled, Assessable, Serializable { public static final String DELIMITER = ";"; - @JsonIdentityReference(alwaysAsId = true) + @JsonIdentityReference(alwaysAsId = true) //needed for debugging internal models private final Item source; - @JsonIdentityReference(alwaysAsId = true) + @JsonIdentityReference(alwaysAsId = true) //needed for debugging internal models private final Item target; private final String description; @@ -37,11 +32,7 @@ public class Relation implements Serializable { private final RelationType type; - public Relation(@NonNull final Item source, - @NonNull final Item target - ) { - this(source, target, null, null, null); - } + private final Map labels = new HashMap<>(); public Relation(@NonNull final Item source, @NonNull final Item target, @@ -49,16 +40,12 @@ public Relation(@NonNull final Item source, final String format, final RelationType type ) { - if (source == null || target == null) { - throw new IllegalArgumentException("Null arguments passed."); - } - if (source.equals(target)) { - throw new IllegalArgumentException("Relation source and target are equal."); + throw new IllegalArgumentException(String.format("Relation source and target are equal.%s %s", source, target)); } - this.source = source; - this.target = target; + this.source = Objects.requireNonNull(source, "Source is null"); + this.target = Objects.requireNonNull(target, "Target is null"); this.description = description; this.format = format; this.type = type; @@ -107,46 +94,38 @@ public String toString() { return "Relation{" + getIdentifier() + '}'; } - @JsonInclude(JsonInclude.Include.NON_NULL) - static class ApiModel { - - public static final String INBOUND = "inbound"; - public static final String OUTBOUND = "outbound"; - - @JsonIdentityReference(alwaysAsId = true) - public final Item source; - - @JsonIdentityReference(alwaysAsId = true) - public final Item target; - - public final String description; - - public final String format; - - public final RelationType type; + @Override + public String getLabel(String key) { + return getLabels().get(key); + } - public final String name; + @NonNull + @Override + public Map getLabels() { + return labels; + } - public final String id; + @Override + public void setLabel(String key, String value) { + labels.put(key, value); + } - public final String direction; + @Override + @NonNull + public Set getAdditionalStatusValues() { + return StatusValue.fromMapping(getAssessmentIdentifier(), indexedByPrefix(Label.status)); + } - ApiModel(@NonNull final Relation relation, @NonNull final Item owner) { - source = relation.source; - target = relation.target; - description = relation.description; - format = relation.format; - type = relation.type; - id = relation.getIdentifier(); + @Override + @NonNull + public String getAssessmentIdentifier() { + return getIdentifier(); + } - if (relation.source.equals(owner)) { - name = StringUtils.isEmpty(target.getName()) ? target.getIdentifier() : target.getName(); - direction = OUTBOUND; - } else { - name = StringUtils.isEmpty(source.getName()) ? source.getIdentifier() : source.getName(); - direction = INBOUND; - } - } + @Override + @NonNull + public List getChildren() { + return new ArrayList<>(); } /** @@ -157,8 +136,8 @@ static class ApiModel { * @throws IllegalArgumentException if the arg is not comparable */ public List getChanges(Relation newer) { - if (!newer.equals(this)) { - throw new IllegalArgumentException("Cannot compare relation " + newer.toString() + " against " + this.toString()); + if (!this.equals(newer)) { + throw new IllegalArgumentException(String.format("Cannot compare relation %s against %s", newer, this)); } List changes = new ArrayList<>(); diff --git a/src/main/java/de/bonndan/nivio/model/RelationBuilder.java b/src/main/java/de/bonndan/nivio/model/RelationFactory.java similarity index 85% rename from src/main/java/de/bonndan/nivio/model/RelationBuilder.java rename to src/main/java/de/bonndan/nivio/model/RelationFactory.java index 660494cc7..494993c72 100644 --- a/src/main/java/de/bonndan/nivio/model/RelationBuilder.java +++ b/src/main/java/de/bonndan/nivio/model/RelationFactory.java @@ -6,12 +6,19 @@ import java.util.Objects; -public class RelationBuilder { +/** + * Factory to create {@link Relation} instances. + * + * + */ +public class RelationFactory { public static RelationDescription createProviderDescription(ItemDescription source, String target) { return createProviderDescription(source.getIdentifier(), target); } + private RelationFactory() {} + /** * Factory method to create a provider type relation. * @@ -68,13 +75,16 @@ public static Relation update(@NonNull final Relation existing, Objects.requireNonNull(description); Objects.requireNonNull(landscape); - return new Relation( + Relation relation = new Relation( landscape.findOneBy(description.getSource(), existing.getSource().getGroup()), landscape.findOneBy(description.getTarget(), existing.getTarget().getGroup()), description.getDescription(), description.getFormat(), - existing.getType() + description.getType() ); + + Labeled.merge(description, relation); + return relation; } /** @@ -93,13 +103,22 @@ public static Relation create(@NonNull final Item origin, Objects.requireNonNull(relationDescription); Objects.requireNonNull(landscape); - return new Relation( + Relation relation = new Relation( landscape.findOneBy(relationDescription.getSource(), origin.getGroup()), landscape.findOneBy(relationDescription.getTarget(), origin.getGroup()), relationDescription.getDescription(), relationDescription.getFormat(), relationDescription.getType() ); + + Labeled.merge(relationDescription, relation); + return relation; } + /** + * Creates a relation instance without any checks. + */ + public static Relation createForTesting(Item source, Item target) { + return new Relation(source, target, null, null, null); + } } diff --git a/src/main/java/de/bonndan/nivio/model/RelationType.java b/src/main/java/de/bonndan/nivio/model/RelationType.java index 666efbea2..51edf41a2 100644 --- a/src/main/java/de/bonndan/nivio/model/RelationType.java +++ b/src/main/java/de/bonndan/nivio/model/RelationType.java @@ -12,7 +12,7 @@ public enum RelationType { @JsonCreator public static RelationType from(String relationType) { - if (StringUtils.isEmpty(relationType)) { + if (!StringUtils.hasLength(relationType)) { return DATAFLOW; } diff --git a/src/main/java/de/bonndan/nivio/model/Tagged.java b/src/main/java/de/bonndan/nivio/model/Tagged.java index c2276bb53..aba9fc14a 100644 --- a/src/main/java/de/bonndan/nivio/model/Tagged.java +++ b/src/main/java/de/bonndan/nivio/model/Tagged.java @@ -7,7 +7,7 @@ */ public interface Tagged extends Labeled { - String LABEL_PREFIX_TAG = "tag."; + String LABEL_PREFIX_TAG = Label.INTERNAL_LABEL_PREFIX + "tag."; /** * Returns a copy of the components tags. @@ -26,7 +26,7 @@ default String[] getTags() { default void setTags(String[] tags) { for (String tag : tags) { - if (!StringUtils.isEmpty(tag)) { + if (StringUtils.hasLength(tag)) { tag = tag.toLowerCase(); setLabel(LABEL_PREFIX_TAG + tag, tag); } diff --git a/src/main/java/de/bonndan/nivio/notification/EventNotification.java b/src/main/java/de/bonndan/nivio/notification/EventNotification.java index 0650b5fee..df4537270 100644 --- a/src/main/java/de/bonndan/nivio/notification/EventNotification.java +++ b/src/main/java/de/bonndan/nivio/notification/EventNotification.java @@ -12,8 +12,8 @@ import org.springframework.lang.Nullable; import java.time.Instant; -import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Objects; /** @@ -32,7 +32,7 @@ public class EventNotification { /** * @param processingEvent application event * @return api model - * @throws NullPointerException + * @throws NullPointerException if a required processing event field is empty */ public static EventNotification from(ProcessingEvent processingEvent) { return new EventNotification( @@ -113,9 +113,9 @@ public String getLandscape() { } @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") - public LocalDateTime getDate() { + public ZonedDateTime getDate() { Instant instant = Instant.ofEpochMilli(timestamp); - return instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); + return ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); } @Schema(description = "In case of ProcessingFinishedEvent a changelog is contained.") diff --git a/src/main/java/de/bonndan/nivio/notification/MessagingService.java b/src/main/java/de/bonndan/nivio/notification/MessagingService.java index 42e01c254..79c687589 100644 --- a/src/main/java/de/bonndan/nivio/notification/MessagingService.java +++ b/src/main/java/de/bonndan/nivio/notification/MessagingService.java @@ -1,8 +1,11 @@ package de.bonndan.nivio.notification; +import de.bonndan.nivio.assessment.AssessmentChangedEvent; import de.bonndan.nivio.input.ProcessingErrorEvent; +import de.bonndan.nivio.input.ProcessingEvent; import de.bonndan.nivio.input.ProcessingFinishedEvent; import de.bonndan.nivio.observation.InputChangedEvent; +import de.bonndan.nivio.output.layout.LayoutChangedEvent; import org.apache.commons.collections4.queue.CircularFifoQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,8 +19,6 @@ /** * This services listens for events and broadcasts them to subscribed websocket clients. - * - * */ @Component public class MessagingService { @@ -33,18 +34,12 @@ public MessagingService(SimpMessagingTemplate template) { @EventListener(ProcessingFinishedEvent.class) public void onProcessingFinishedEvent(ProcessingFinishedEvent processingEvent) { - EventNotification eventNotification = EventNotification.from(processingEvent); - fifo.add(eventNotification); - LOGGER.debug("Broadcasting processing event: " + processingEvent.getType()); - this.template.convertAndSend(WebSocketConfig.TOPIC + EVENTS, eventNotification); + broadcast(processingEvent); } @EventListener(ProcessingErrorEvent.class) public void onProcessingErrorEvent(ProcessingErrorEvent processingEvent) { - EventNotification eventNotification = EventNotification.from(processingEvent); - fifo.add(eventNotification); - LOGGER.debug("Broadcasting processing event: " + processingEvent.getType()); - this.template.convertAndSend(WebSocketConfig.TOPIC + EVENTS, eventNotification); + broadcast(processingEvent); } @EventListener(InputChangedEvent.class) @@ -55,6 +50,23 @@ public void onInputChangedEvent(InputChangedEvent inputChangedEvent) { this.template.convertAndSend(WebSocketConfig.TOPIC + EVENTS, eventNotification); } + @EventListener(AssessmentChangedEvent.class) + public void onAssessmentChangedEvent(AssessmentChangedEvent event) { + broadcast(event); + } + + @EventListener(LayoutChangedEvent.class) + public void onLayoutChangedEvent(LayoutChangedEvent event) { + broadcast(event); + } + + public void broadcast(ProcessingEvent event) { + EventNotification eventNotification = EventNotification.from(event); + fifo.add(eventNotification); + LOGGER.debug(String.format("Broadcasting %s event.", event.getClass().getSimpleName())); + this.template.convertAndSend(WebSocketConfig.TOPIC + EVENTS, eventNotification); + } + /** * @return the last 1000 processing events */ diff --git a/src/main/java/de/bonndan/nivio/observation/BaseObserver.java b/src/main/java/de/bonndan/nivio/observation/BaseObserver.java index 07ee69dfd..8bbc8c2c6 100644 --- a/src/main/java/de/bonndan/nivio/observation/BaseObserver.java +++ b/src/main/java/de/bonndan/nivio/observation/BaseObserver.java @@ -14,7 +14,7 @@ public abstract class BaseObserver implements InputFormatObserver { protected final Landscape landscape; protected final ApplicationEventPublisher eventPublisher; - public BaseObserver(@NonNull final Landscape landscape, @NonNull final ApplicationEventPublisher eventPublisher) { + protected BaseObserver(@NonNull final Landscape landscape, @NonNull final ApplicationEventPublisher eventPublisher) { this.landscape = Objects.requireNonNull(landscape); this.eventPublisher = Objects.requireNonNull(eventPublisher); } diff --git a/src/main/java/de/bonndan/nivio/observation/InputFormatObserver.java b/src/main/java/de/bonndan/nivio/observation/InputFormatObserver.java index e73a081cc..44a3c3d12 100644 --- a/src/main/java/de/bonndan/nivio/observation/InputFormatObserver.java +++ b/src/main/java/de/bonndan/nivio/observation/InputFormatObserver.java @@ -8,5 +8,4 @@ * URL observer is implemented, but others like k8s observer to be done */ public interface InputFormatObserver extends Runnable { - } diff --git a/src/main/java/de/bonndan/nivio/observation/KubernetesObserver.java b/src/main/java/de/bonndan/nivio/observation/KubernetesObserver.java new file mode 100644 index 000000000..bc9522492 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/observation/KubernetesObserver.java @@ -0,0 +1,66 @@ +package de.bonndan.nivio.observation; + + +import de.bonndan.nivio.model.Landscape; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.lang.NonNull; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +/** + * The KubernetesObserver Class is intended to detect changes in the Kubernetes cluster. + * To achieve this the class compares two HashSets containing Kubernetes Items with each other. + * The run method is executed once every second + */ + +public class KubernetesObserver implements InputFormatObserver { + + private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesObserver.class); + + private final Landscape landscape; + private final ApplicationEventPublisher eventPublisher; + private final KubernetesClient kubernetesClient; + private final List eventUidList; + + public KubernetesObserver(@NonNull final Landscape landscape, + @NonNull final ApplicationEventPublisher eventPublisher, + @NonNull final KubernetesClient kubernetesClient) { + this.landscape = landscape; + this.kubernetesClient = kubernetesClient; + this.eventPublisher = eventPublisher; + this.eventUidList = getK8sComponents(); + } + + @Override + public void run() { + if (!new HashSet<>(eventUidList).equals(new HashSet<>(getK8sComponents()))) { + LOGGER.info("K8s change detected"); + eventPublisher.publishEvent(new InputChangedEvent(new ObservedChange(landscape, "k8s cluster changed"))); + } + } + + @NonNull + private List getK8sComponents() { + try { + List componentList = new ArrayList<>(); + componentList.addAll(kubernetesClient.apps().deployments().list().getItems()); + componentList.addAll(kubernetesClient.persistentVolumeClaims().list().getItems()); + componentList.addAll(kubernetesClient.persistentVolumes().list().getItems()); + componentList.addAll(kubernetesClient.pods().list().getItems()); + componentList.addAll(kubernetesClient.apps().replicaSets().list().getItems()); + componentList.addAll(kubernetesClient.services().list().getItems()); + componentList.addAll(kubernetesClient.apps().statefulSets().list().getItems()); + return componentList; + } catch (KubernetesClientException n) { + LOGGER.error("Kubernetes might not be available"); + } + return new ArrayList<>(); + } +} diff --git a/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java b/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java index ac6c43da9..ecc044da1 100644 --- a/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java +++ b/src/main/java/de/bonndan/nivio/observation/LandscapeObserverFactory.java @@ -65,30 +65,32 @@ public List getObserversFor(@NonNull final Landscape landsc if (baseUrl.isEmpty()) { LOGGER.info("Cannot create observer for landscape '{}' source '{}' ", description.getIdentifier(), url.get()); } else { - observers.add(getObserver(landscape, url.get())); + observers.add(getDefaultObserver(landscape, url.get())); } } for (SourceReference sourceReference : description.getSourceReferences()) { InputFormatHandler inputFormatHandler = inputFormatHandlerFactory.getInputFormatHandler(sourceReference); - InputFormatObserver observer; + URL combined; try { - observer = getObserver(landscape, new URL(URLHelper.combine(baseUrl.orElse(null), sourceReference.getUrl()))); + combined = new URL(URLHelper.combine(baseUrl.orElse(null), sourceReference.getUrl())); } catch (MalformedURLException e) { LOGGER.warn("Failed to create observer for base url {} and source reference {}", baseUrl.orElse(null), sourceReference.getUrl()); continue; } + InputFormatObserver observer = inputFormatHandler.getObserver(eventPublisher, landscape, sourceReference); - observer = inputFormatHandler.getObserver(observer, sourceReference); - if (observer != null) { - observers.add(observer); + if (observer == null) { + observer = getDefaultObserver(landscape, combined); } + + observers.add(observer); } return observers; } - private InputFormatObserver getObserver(Landscape landscape, URL url) { + private InputFormatObserver getDefaultObserver(Landscape landscape, URL url) { if (URLHelper.isLocal(url)) { try { return new LocalFileObserver(landscape, eventPublisher, new File(url.toURI())); diff --git a/src/main/java/de/bonndan/nivio/observation/LandscapeObserverPool.java b/src/main/java/de/bonndan/nivio/observation/LandscapeObserverPool.java index 6c6d4d32a..2a962c107 100644 --- a/src/main/java/de/bonndan/nivio/observation/LandscapeObserverPool.java +++ b/src/main/java/de/bonndan/nivio/observation/LandscapeObserverPool.java @@ -17,15 +17,16 @@ */ public class LandscapeObserverPool { + private static final Logger LOGGER = LoggerFactory.getLogger(LandscapeObserverPool.class); private final ThreadPoolTaskScheduler taskScheduler; private final Map> scheduledTasks = new IdentityHashMap<>(); - private final long delay; + private final ObserverConfigProperties observerConfigProperties; - public LandscapeObserverPool(@NonNull final ThreadPoolTaskScheduler taskScheduler, long delay) { + public LandscapeObserverPool(@NonNull final ThreadPoolTaskScheduler taskScheduler, @NonNull ObserverConfigProperties observerConfigProperties) { this.taskScheduler = Objects.requireNonNull(taskScheduler); - this.delay = delay; + this.observerConfigProperties = observerConfigProperties; } /** @@ -45,7 +46,8 @@ public void updateObservers(List observers) { observers.forEach(inputFormatObserver -> { try { - ScheduledFuture scheduledFuture = taskScheduler.scheduleWithFixedDelay(inputFormatObserver, delay); + ScheduledFuture scheduledFuture = taskScheduler.scheduleWithFixedDelay(inputFormatObserver, + observerConfigProperties.getScanDelay().getOrDefault(inputFormatObserver.getClass().getSimpleName(), 30) * 1000L); scheduledTasks.put(inputFormatObserver, scheduledFuture); } catch (TaskRejectedException e) { LOGGER.error("Failed to schedule observer: " + e.getMessage(), e); diff --git a/src/main/java/de/bonndan/nivio/observation/ObserverConfigProperties.java b/src/main/java/de/bonndan/nivio/observation/ObserverConfigProperties.java new file mode 100644 index 000000000..2932cce48 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/observation/ObserverConfigProperties.java @@ -0,0 +1,24 @@ +package de.bonndan.nivio.observation; + + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; + +import java.util.Map; + +@Configuration +@ConfigurationProperties(prefix = "observerconfig") +@Validated +public class ObserverConfigProperties { + + private Map scanDelay; + + public Map getScanDelay() { + return scanDelay; + } + + public void setScanDelay(Map scanDelay) { + this.scanDelay = scanDelay; + } +} diff --git a/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java b/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java index 14432af61..a3e9ba974 100644 --- a/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java +++ b/src/main/java/de/bonndan/nivio/observation/ObserverRegistry.java @@ -23,19 +23,23 @@ public class ObserverRegistry { private static final Logger LOGGER = LoggerFactory.getLogger(ObserverRegistry.class); + private final Map observerMap = new ConcurrentHashMap<>(); private final LandscapeObserverFactory landscapeObserverPoolFactory; private final ThreadPoolTaskScheduler taskScheduler; private final IndexingDispatcher indexingDispatcher; + private final ObserverConfigProperties observerConfigProperties; public ObserverRegistry(LandscapeObserverFactory landscapeObserverPoolFactory, ThreadPoolTaskScheduler taskScheduler, - IndexingDispatcher indexingDispatcher + IndexingDispatcher indexingDispatcher, + ObserverConfigProperties observerConfigProperties ) { this.landscapeObserverPoolFactory = landscapeObserverPoolFactory; this.taskScheduler = taskScheduler; this.indexingDispatcher = indexingDispatcher; + this.observerConfigProperties = observerConfigProperties; } /** @@ -48,16 +52,9 @@ public void onProcessingFinishedEvent(ProcessingFinishedEvent event) { LandscapeDescription landscapeDescription = event.getInput(); Landscape landscape = Objects.requireNonNull(event.getLandscape()); - if (landscapeDescription == null) { - String msg = String.format("No landscape description (input) available. Landscape %s could not be registered for observation", landscape.getIdentifier()); - landscape.getLog().warn(msg); - LOGGER.warn(msg); - return; - } - LandscapeObserverPool pool = observerMap.computeIfAbsent(landscape.getIdentifier(), s -> { LOGGER.info("Registered landscape {} for observation.", landscapeDescription); - return new LandscapeObserverPool(taskScheduler, 30 * 1000); + return new LandscapeObserverPool(taskScheduler, observerConfigProperties); }); pool.updateObservers(landscapeObserverPoolFactory.getObserversFor(landscape, landscapeDescription)); } diff --git a/src/main/java/de/bonndan/nivio/output/Renderer.java b/src/main/java/de/bonndan/nivio/output/Renderer.java index e928e05ee..5f9bb1ed7 100644 --- a/src/main/java/de/bonndan/nivio/output/Renderer.java +++ b/src/main/java/de/bonndan/nivio/output/Renderer.java @@ -34,4 +34,9 @@ public interface Renderer { * @throws IOException if file cannot be written */ void render(@NonNull final LayoutedComponent landscape, @NonNull final Assessment assessment, @NonNull final File file, boolean debug) throws IOException; + + /** + * @return the generated class of the impl + */ + String getRenderingType(); } diff --git a/src/main/java/de/bonndan/nivio/output/docs/DocsController.java b/src/main/java/de/bonndan/nivio/output/docs/DocsController.java index ef4e708c2..2a1c84774 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/DocsController.java +++ b/src/main/java/de/bonndan/nivio/output/docs/DocsController.java @@ -1,6 +1,7 @@ package de.bonndan.nivio.output.docs; import de.bonndan.nivio.api.NotFoundException; +import de.bonndan.nivio.assessment.Assessment; import de.bonndan.nivio.assessment.AssessmentRepository; import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.model.LandscapeRepository; @@ -39,7 +40,7 @@ private ResponseEntity getResponseEntity(HttpServletRequest request, Lan HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_TYPE, "text/html"); return new ResponseEntity<>( - generator.toDocument(landscape, assessmentRepository.getAssessment(landscape.getFullyQualifiedIdentifier()).orElse(assessmentRepository.createAssessment(landscape)), + generator.toDocument(landscape, assessmentRepository.getAssessment(landscape.getFullyQualifiedIdentifier()).orElse(Assessment.empty()), new SearchConfig(request.getParameterMap())), headers, HttpStatus.OK diff --git a/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java b/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java index 831a5f968..49e5dbdc3 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java +++ b/src/main/java/de/bonndan/nivio/output/docs/HtmlGenerator.java @@ -16,10 +16,7 @@ import org.springframework.util.StringUtils; import java.net.URL; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -27,13 +24,15 @@ import static de.bonndan.nivio.output.FormatUtils.ifPresent; import static de.bonndan.nivio.output.FormatUtils.nice; import static j2html.TagCreator.*; -import static org.springframework.util.StringUtils.isEmpty; - +import static org.springframework.util.StringUtils.hasLength; public abstract class HtmlGenerator { protected static final String GROUP_CIRCLE = "⦿"; + private static final String CONTENT = "content"; + private static final String CLASS = "class"; + @NonNull protected final LocalServer localServer; @@ -62,10 +61,10 @@ protected ContainerTag getHead(Landscape landscape) { title(landscape.getName()), link().condAttr(css != null, "rel", "stylesheet").attr("href", css), meta().attr("charset", "utf-8"), - meta().attr("name", "viewport").attr("content", "width=device-width, initial-scale=1, shrink-to-fit=no"), - meta().attr("name", "description").attr("content", landscape.getName()), - meta().attr("name", "author").attr("content", landscape.getContact()), - meta().attr("generator", "author").attr("content", "nivio"), + meta().attr("name", "viewport").attr(CONTENT, "width=device-width, initial-scale=1, shrink-to-fit=no"), + meta().attr("name", "description").attr(CONTENT, landscape.getName()), + meta().attr("name", "author").attr(CONTENT, landscape.getContact()), + meta().attr("generator", "author").attr(CONTENT, "nivio"), style("html {margin: 1rem} .group{margin-top: 1rem;} .card{margin-bottom: 1rem;}").attr("type", "text/css") ); } @@ -86,50 +85,54 @@ protected ContainerTag writeItem(Item item, Assessment assessment, Collection String.format("%s: %s", StringUtils.capitalize(Label.framework.unprefixed(mapEntry.getKey())), mapEntry.getValue())) .collect(Collectors.toList()); - List statusValues = assessment.getResults().get(item.getFullyQualifiedIdentifier()); + List statusValues = assessment.getResults().get(item.getAssessmentIdentifier()); + if (statusValues == null) { + statusValues = new ArrayList<>(); + } return div( div( - iff(!isEmpty(item.getLabel(Label.note)), div(item.getLabel(Label.note)).attr("class", "alert alert-warning float float-right")), + iff(hasLength(item.getLabel(Label.note)), div(item.getLabel(Label.note)).attr(CLASS, "alert alert-warning float float-right")), a().attr("id", item.getFullyQualifiedIdentifier().toString()), h3( - img().attr("src", iconService.getIconUrl(item)).attr("width", "30px").attr("class", "img-fluid"), + img().attr("src", item.getLabel(Label._icondata)).attr("width", "30px").attr(CLASS, "img-fluid"), rawHtml(" "), - rawHtml(isEmpty(item.getName()) ? item.getIdentifier() : item.getName()) + rawHtml(!hasLength(item.getName()) ? item.getIdentifier() : item.getName()) ), p(FormatUtils.nice(item.getDescription())), ul().with( - iff(!isEmpty(item.getName()), li("Name: " + FormatUtils.nice(item.getName()))) - , iff(!isEmpty(item.getFullyQualifiedIdentifier().toString()), li("Full identifier: " + item.getFullyQualifiedIdentifier())) - , iff(!isEmpty(item.getIdentifier()), li("Identifier: " + item.getIdentifier())) - , iff(!isEmpty(item.getGroup()), li(rawHtml("Group: " + "" + GROUP_CIRCLE + " " + FormatUtils.nice(item.getGroup())))) - , iff(!isEmpty(item.getContact()), li("Contact: " + FormatUtils.nice(item.getContact()))) - , iff(!isEmpty(item.getOwner()), li("Owner: " + FormatUtils.nice(item.getOwner()))) - , iff(!isEmpty(item.getType()), li("Type: " + item.getType())) + iff(hasLength(item.getName()), li("Name: " + FormatUtils.nice(item.getName()))) + , iff(hasLength(item.getFullyQualifiedIdentifier().toString()), li("Full identifier: " + item.getFullyQualifiedIdentifier())) + , iff(hasLength(item.getIdentifier()), li("Identifier: " + item.getIdentifier())) + , iff(hasLength(item.getGroup()), li(rawHtml("Group: " + "" + GROUP_CIRCLE + " " + FormatUtils.nice(item.getGroup())))) + , iff(hasLength(item.getContact()), li("Contact: " + FormatUtils.nice(item.getContact()))) + , iff(hasLength(item.getOwner()), li("Owner: " + FormatUtils.nice(item.getOwner()))) + , iff(item.getTags().length > 0, li("Tags: " + String.join(", ", item.getTags()))) + , iff(hasLength(item.getType()), li("Type: " + item.getType())) + , iff(hasLength(item.getAddress()), li("Address: " + item.getAddress())) , iff(links.size() > 1, li("Links: ").with(links)) - , iff(frameworks.size() > 0, li("Frameworks: " + String.join(String.format("%s ", DELIMITER), frameworks))) + , iff(!frameworks.isEmpty(), li("Frameworks: " + String.join(String.format("%s ", DELIMITER), frameworks))) ).with(labelList), //statuses - iff(!statusValues.isEmpty(), h4("Status information")), + iff(!statusValues.isEmpty(), h4("Status")), dl().with( statusValues.stream().map(statusItem -> join( dt(FormatUtils.nice( - statusItem.getField().endsWith("." + item.getIdentifier()) - ? statusItem.getField().replace("." + item.getIdentifier(), "") - : statusItem.getField() + statusItem.getField().endsWith("." + item.getIdentifier()) + ? statusItem.getField().replace("." + item.getIdentifier(), "") + : statusItem.getField() ) + " " ).with( span(" " + statusItem.getStatus() + " ") - .attr("class", "badge") + .attr(CLASS, "badge") .attr("style", "background-color: " + statusItem.getStatus() + " !important") ), - iff( - !isEmpty(statusItem.getMessage()) && !"summary".equals(statusItem.getMessage()), + iff(hasLength(statusItem.getMessage()) && !"summary".equals(statusItem.getMessage()), dd(span(" " + FormatUtils.nice(statusItem.getMessage()))) ) ) @@ -167,35 +170,29 @@ protected ContainerTag writeItem(Item item, Assessment assessment, Collection li( span(interfaceItem.getDescription()), - iff(!StringUtils.isEmpty(interfaceItem.getFormat()), span(", format: " + interfaceItem.getFormat())), - iff(interfaceItem.getUrl() != null && !StringUtils.isEmpty(interfaceItem.getUrl().toString()), + iff(StringUtils.hasLength(interfaceItem.getFormat()), span(", format: " + interfaceItem.getFormat())), + iff(interfaceItem.getUrl() != null && StringUtils.hasLength(interfaceItem.getUrl().toString()), span(", ").with(a(interfaceItem.getUrl().toString()).attr("href", interfaceItem.getUrl().toString())) ) )) )) - ).attr("class", "card-body") + ).attr(CLASS, "card-body") - ).attr("class", "card"); + ).attr(CLASS, "card"); } protected List getLabelList(Item item) { Function, Boolean> filter = s -> { - if (isEmpty(s.getValue())) { - return false; - } - if (Label.type.name().equals(s.getKey())) { + if (!hasLength(s.getValue())) { return false; } if (Label.framework.name().equals(s.getKey())) { return false; } - if (Label.icon.name().equals(s.getKey())) { - return false; - } - if (Label.color.name().equals(s.getKey())) { + if (s.getKey().startsWith(Label.INTERNAL_LABEL_PREFIX)) { return false; } - if (Label.fill.name().equals(s.getKey())) { + if (s.getValue().equals("null")) { return false; } //filter out statuses, they are part of the assessment @@ -214,4 +211,4 @@ protected List getLabelList(Item item) { }) .collect(Collectors.toList()); } -} +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java b/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java index b83673c6d..56b58b790 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java +++ b/src/main/java/de/bonndan/nivio/output/docs/OwnersReportGenerator.java @@ -14,6 +14,7 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -31,18 +32,18 @@ public OwnersReportGenerator(LocalServer localServer, IconService iconService) { public String toDocument(@NonNull final Landscape landscape, @NonNull final Assessment assessment, @Nullable final SearchConfig searchConfig) { String title = "Report"; - if (searchConfig != null && !StringUtils.isEmpty(searchConfig.getTitle())) { + if (searchConfig != null && StringUtils.hasLength(searchConfig.getTitle())) { title = searchConfig.getTitle(); } - final Optional searchTerm = searchConfig != null && !StringUtils.isEmpty(searchConfig.getSearchTerm()) ? Optional.ofNullable(searchConfig.getSearchTerm()) : Optional.empty(); + final Optional searchTerm = searchConfig != null && StringUtils.hasLength(searchConfig.getSearchTerm()) ? Optional.ofNullable(searchConfig.getSearchTerm()) : Optional.empty(); List items = new ArrayList<>(searchTerm.map(landscape::search).orElse(landscape.getItems().all())); return html( getHead(landscape), body( h1(title), h6("Landscape: " + landscape.getName()), - h6("Date: " + ZonedDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)), + h6("Date: " + ZonedDateTime.now().format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT))), iff(searchTerm.isPresent(), h6("Search term: " + (searchTerm.orElse(null)))), br(), rawHtml(writeOwnerGroups(GroupedBy.by(Component::getOwner, items), assessment)) diff --git a/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java b/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java index abc1e513a..777b0d3ec 100644 --- a/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java +++ b/src/main/java/de/bonndan/nivio/output/docs/ReportGenerator.java @@ -18,7 +18,7 @@ import static de.bonndan.nivio.output.FormatUtils.nice; import static de.bonndan.nivio.output.map.MapController.MAP_SVG_ENDPOINT; import static j2html.TagCreator.*; -import static org.springframework.util.StringUtils.isEmpty; +import static org.springframework.util.StringUtils.hasLength; /** * Generates a report containing all landscape groups and items. @@ -40,7 +40,7 @@ private String writeLandscape(final Landscape landscape, final Assessment assess getHead(landscape), body( h1(landscape.getName()), - iff(!isEmpty(landscape.getContact()), p("Contact: " + nice(landscape.getContact()))), + iff(hasLength(landscape.getContact()), p("Contact: " + nice(landscape.getContact()))), div(embed().attr("src", MapController.PATH + "/" + landscape.getIdentifier() + "/" + MAP_SVG_ENDPOINT).attr("class", "img-fluid img-thumbnail mx-auto d-block")), br(), br(), rawHtml(writeGroups(landscape, assessment)) @@ -60,7 +60,7 @@ private String writeGroups(Landscape landscape, Assessment assessment) { ); builder.append( div().attr("class", "group") - .with(groupItem.getItems().stream().map(item -> this.writeItem(item, assessment, all))) + .with(groupItem.getItems().stream().map(fqi -> this.writeItem(landscape.getItems().pick(fqi), assessment, all))) .render() ); }); diff --git a/src/main/java/de/bonndan/nivio/output/dto/ComponentApiModel.java b/src/main/java/de/bonndan/nivio/output/dto/ComponentApiModel.java new file mode 100644 index 000000000..a2a8d1371 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/dto/ComponentApiModel.java @@ -0,0 +1,37 @@ +package de.bonndan.nivio.output.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.model.Link; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.HashMap; +import java.util.Map; + +public abstract class ComponentApiModel { + + protected Map hateoasLinks = new HashMap<>(); + + @Schema(name = "_links") + @JsonProperty("_links") + public Map getLinks() { + return hateoasLinks; + } + + public abstract Map getLabels(); + + public void setHateoasLinks(Map hateoasLinks) { + this.hateoasLinks.putAll(hateoasLinks); + } + + /** + * Returns the labels without the internal ones (having prefixes). + * + * @return filtered labels + */ + protected Map getPublicLabels(Map labels) { + return Labeled.withoutKeys(labels, Label.INTERNAL_LABEL_PREFIX, Label.status.name()); + } + +} diff --git a/src/main/java/de/bonndan/nivio/output/dto/GroupApiModel.java b/src/main/java/de/bonndan/nivio/output/dto/GroupApiModel.java new file mode 100644 index 000000000..71a9847a5 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/dto/GroupApiModel.java @@ -0,0 +1,69 @@ +package de.bonndan.nivio.output.dto; + +import de.bonndan.nivio.model.FullyQualifiedIdentifier; +import de.bonndan.nivio.model.Group; +import de.bonndan.nivio.model.Item; +import de.bonndan.nivio.model.Label; +import org.springframework.lang.NonNull; + +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class GroupApiModel extends ComponentApiModel { + + private final Group group; + private final Set items; + + public GroupApiModel(@NonNull final Group group, final Set items) { + this.group = Objects.requireNonNull(group); + this.hateoasLinks.putAll(group.getLinks()); + this.items = items.stream().map(item -> new ItemApiModel(item, group)).collect(Collectors.toSet()); + } + + public FullyQualifiedIdentifier getFullyQualifiedIdentifier() { + return group.getFullyQualifiedIdentifier(); + } + + public String getName() { + return group.getName(); + } + + public String getIdentifier() { + return group.getIdentifier(); + } + + public String getOwner() { + return group.getOwner(); + } + + public String getDescription() { + return group.getDescription(); + } + + public String getContact() { + return group.getContact(); + } + + public String getColor() { + return group.getColor(); + } + + public Set getItems() { + return items; + } + + @Override + public Map getLabels() { + return getPublicLabels(group.getLabels()); + } + + public String getIcon() { + return group.getLabel(Label._icondata); + } + + public String getLandscapeIdentifier() { + return group.getLandscapeIdentifier(); + } +} diff --git a/src/main/java/de/bonndan/nivio/output/dto/ItemApiModel.java b/src/main/java/de/bonndan/nivio/output/dto/ItemApiModel.java new file mode 100644 index 000000000..f429e9216 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/dto/ItemApiModel.java @@ -0,0 +1,113 @@ +package de.bonndan.nivio.output.dto; + +import com.fasterxml.jackson.annotation.*; +import de.bonndan.nivio.model.*; +import org.springframework.util.StringUtils; + +import javax.validation.constraints.NotNull; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "fullyQualifiedIdentifier") +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ItemApiModel extends ComponentApiModel { + + @NotNull + @JsonIgnore + private final Item item; + private final String color; + + public ItemApiModel(@NotNull final Item item, @NotNull final Group group) { + this.item = Objects.requireNonNull(item); + + //ensures that the api model inherits the group colors as fallback + this.color = !StringUtils.hasLength(item.getColor()) ? group.getColor() : item.getColor(); + hateoasLinks.putAll(item.getLinks()); + } + + public String getIdentifier() { + return item.getIdentifier(); + } + + public FullyQualifiedIdentifier getFullyQualifiedIdentifier() { + return item.getFullyQualifiedIdentifier(); + } + + public String getName() { + return item.getName(); + } + + public String getOwner() { + return item.getOwner(); + } + + public String getIcon() { + return item.getLabel(Label._icondata); + } + + public String getColor() { + return color; + } + + public String getContact() { + return item.getContact(); + } + + public String getGroup() { + return item.getGroup(); + } + + public String getDescription() { + return item.getDescription(); + } + + @Override + public Map getLabels() { + return getPublicLabels(item.getLabels()); + } + + @JsonProperty("relations") + @JsonManagedReference + public Map getJSONRelations() { + Map map = new HashMap<>(); + + item.getRelations().forEach(relation -> { + RelationApiModel apiModel = new RelationApiModel(relation, this.item); + map.put(apiModel.id, apiModel); + }); + + return map; + } + + public String getType() { + return item.getType(); + } + + public String getAddress() { + return item.getAddress(); + } + + @JsonManagedReference + public Set getInterfaces() { + return item.getInterfaces(); + } + + public String[] getTags() { + return item.getTags(); + } + + /** + * @return the fully qualified identifier for this service + */ + @Override + public String toString() { + if (item.getLandscape() == null) { + return item.getIdentifier(); + } + + return getFullyQualifiedIdentifier().toString(); + } + +} diff --git a/src/main/java/de/bonndan/nivio/output/dto/LandscapeApiModel.java b/src/main/java/de/bonndan/nivio/output/dto/LandscapeApiModel.java new file mode 100644 index 000000000..ef2ea7c59 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/dto/LandscapeApiModel.java @@ -0,0 +1,88 @@ +package de.bonndan.nivio.output.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import de.bonndan.nivio.assessment.kpi.KPI; +import de.bonndan.nivio.model.FullyQualifiedIdentifier; +import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeConfig; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import java.time.ZonedDateTime; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class LandscapeApiModel extends ComponentApiModel { + + @NonNull + private final Landscape landscape; + + public LandscapeApiModel(@NonNull final Landscape landscape) { + this.landscape = Objects.requireNonNull(landscape); + hateoasLinks.putAll(landscape.getLinks()); + } + + @NonNull + public String getIdentifier() { + return landscape.getIdentifier(); + } + + @NonNull + public FullyQualifiedIdentifier getFullyQualifiedIdentifier() { + return landscape.getFullyQualifiedIdentifier(); + } + + @NonNull + public String getName() { + return landscape.getName(); + } + + @Nullable + public String getContact() { + return landscape.getContact(); + } + + public LandscapeConfig getConfig() { + return landscape.getConfig(); + } + + public Set getGroups() { + return landscape.getGroupItems().stream() + .map(group -> new GroupApiModel(group, landscape.getItems().retrieve(group.getItems()))) + .collect(Collectors.toSet()); + } + + public String getDescription() { + return landscape.getDescription(); + } + + public String getOwner() { + return landscape.getOwner(); + } + + @Override + public Map getLabels() { + return getPublicLabels(landscape.getLabels()); + } + + public ZonedDateTime getLastUpdate() { + return landscape.getLastUpdate(); + } + + public String getIcon() { + return landscape.getLabel(Label._icondata); + } + + /** + * Returns all KPIs for the landscape. + * + * @return kpis, configured and initialized + */ + public Map getKpis() { + return landscape.getKpis(); + } +} diff --git a/src/main/java/de/bonndan/nivio/output/dto/RangeApiModel.java b/src/main/java/de/bonndan/nivio/output/dto/RangeApiModel.java new file mode 100644 index 000000000..8efd64a43 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/dto/RangeApiModel.java @@ -0,0 +1,42 @@ +package de.bonndan.nivio.output.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.commons.lang3.Range; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RangeApiModel { + + @NonNull + private final Range range; + + @Nullable + private final String description; + + public RangeApiModel(@NonNull final Range range) { + this(range, null); + } + + public RangeApiModel(@NonNull final Range range, @Nullable final String description) { + this.range = Objects.requireNonNull(range, "Non null range is required"); + this.description = description; + } + + @NonNull + public String getMinimum() { + return range.getMinimum().toString(); + } + + @NonNull + public String getMaximum() { + return range.getMaximum().toString(); + } + + @Nullable + public String getDescription() { + return description; + } +} diff --git a/src/main/java/de/bonndan/nivio/output/dto/RelationApiModel.java b/src/main/java/de/bonndan/nivio/output/dto/RelationApiModel.java new file mode 100644 index 000000000..ea1006413 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/dto/RelationApiModel.java @@ -0,0 +1,56 @@ +package de.bonndan.nivio.output.dto; + +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import com.fasterxml.jackson.annotation.JsonInclude; +import de.bonndan.nivio.model.Item; +import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.RelationType; +import org.springframework.lang.NonNull; +import org.springframework.util.StringUtils; + +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RelationApiModel { + + public static final String INBOUND = "inbound"; + public static final String OUTBOUND = "outbound"; + + @JsonIdentityReference(alwaysAsId = true) + public final Item source; + + @JsonIdentityReference(alwaysAsId = true) + public final Item target; + + public final String description; + + public final String format; + + public final RelationType type; + + public final String name; + + public final String id; + + public final String direction; + + public final Map labels; + + public RelationApiModel(@NonNull final Relation relation, @NonNull final Item owner) { + source = relation.getSource(); + target = relation.getTarget(); + description = relation.getDescription(); + format = relation.getFormat(); + type = relation.getType(); + id = relation.getIdentifier(); + labels = relation.getLabels(); + + if (relation.getSource().equals(owner)) { + name = !StringUtils.hasLength(target.getName()) ? target.getIdentifier() : target.getName(); + direction = OUTBOUND; + } else { + name = !StringUtils.hasLength(source.getName()) ? source.getIdentifier() : source.getName(); + direction = INBOUND; + } + } +} diff --git a/src/main/java/de/bonndan/nivio/output/icons/ExternalIcons.java b/src/main/java/de/bonndan/nivio/output/icons/ExternalIcons.java index 934460aba..c42692ff3 100644 --- a/src/main/java/de/bonndan/nivio/output/icons/ExternalIcons.java +++ b/src/main/java/de/bonndan/nivio/output/icons/ExternalIcons.java @@ -8,7 +8,6 @@ import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; -import javax.annotation.PostConstruct; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; @@ -17,8 +16,6 @@ /** * Loads images from external resources and converts them into data urls. Also provides shortcuts to common vendor icons. - * - * */ @Component public class ExternalIcons { @@ -27,25 +24,17 @@ public class ExternalIcons { private static final Logger LOGGER = LoggerFactory.getLogger(ExternalIcons.class); + private final Map vendorIconUrls = new HashMap<>(); private final Map imageCache = new ConcurrentHashMap<>(); private final HttpService httpService; - public ExternalIcons(HttpService httpService) { + + public ExternalIcons(HttpService httpService, ExternalIconsProvider icons) { this.httpService = httpService; + vendorIconUrls.putAll(icons.getUrls()); } - @PostConstruct - public void init() { - vendorIconUrls.put("apache/httpd", "http://www.apache.org/logos/res/httpd/httpd.png"); - vendorIconUrls.put("redhat/keycloak", "https://raw.githubusercontent.com/keycloak/keycloak-misc/master/logo/keycloak_icon_256px.png"); - vendorIconUrls.put("k8s", "https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png"); - vendorIconUrls.put("kubernetes", "https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png"); - - //redis.io/topics/trademark - vendorIconUrls.put("redis", "https://redis.io/images/redis-white.png"); - vendorIconUrls.put("prometheus", "https://raw.githubusercontent.com/prometheus/docs/master/static/prometheus_logo.png"); - } /** * Returns the original url of a vendor product icon. @@ -55,7 +44,7 @@ public void init() { */ public Optional getUrl(String vendor) { - if (StringUtils.isEmpty(vendor) || !vendorIconUrls.containsKey(vendor.toLowerCase())) { + if (!StringUtils.hasLength(vendor) || !vendorIconUrls.containsKey(vendor.toLowerCase())) { LOGGER.warn("Unknown vendor icon {}", vendor); return Optional.empty(); } diff --git a/src/main/java/de/bonndan/nivio/output/icons/ExternalIconsProvider.java b/src/main/java/de/bonndan/nivio/output/icons/ExternalIconsProvider.java new file mode 100644 index 000000000..b0c044c8c --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/icons/ExternalIconsProvider.java @@ -0,0 +1,24 @@ +package de.bonndan.nivio.output.icons; + +import de.bonndan.nivio.util.YamlPropertySourceFactory; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import java.util.Map; + +@Configuration +@ConfigurationProperties(prefix = "iconurls") +@PropertySource(value = "classpath:iconurls.yml", factory = YamlPropertySourceFactory.class) +public class ExternalIconsProvider { + private Map urls; + + public Map getUrls() { + return urls; + } + + public void setUrls(Map urls) { + this.urls = urls; + } +} + diff --git a/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java b/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java index ac8c63c72..722d7f43e 100644 --- a/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java +++ b/src/main/java/de/bonndan/nivio/output/icons/IconMapping.java @@ -1,45 +1,85 @@ package de.bonndan.nivio.output.icons; -import java.util.Arrays; -import java.util.Optional; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.Nullable; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; /** * Mapping of "known" icons (item.type) to Material Design icons. - * - * */ -public enum IconMapping { - - DEFAULT_ICON("cog"), - BACKEND("application-cog"), - CACHE("flash-circle"), - CONTAINER("inbox"), - FIREWALL("wall"), - FRONTEND("television-guide"), - HUMANUSER("account"), - INTERFACE("connection"), - KEYVALUESTORE("view-list"), - LOADBALANCER("call-split"), - MESSAGEQUEUE("tray-full"), - MOBILECLIENT("cellphone"), - SERVICE("application-cog"), - VOLUME("harddisk"), - WEBSERVICE("application"), - ; - - private final String icon; - - IconMapping(String icon) { - this.icon = icon; +public class IconMapping { + + private static final Logger LOGGER = LoggerFactory.getLogger(IconMapping.class); + + public static final String DEFAULT_ICON = "cog"; + + public static final String BACKEND = "backend"; + public static final String CACHE = "cache"; + public static final String CONTAINER = "container"; + public static final String DEPLOYMENT = "deployment"; + public static final String POD = "pod"; + public static final String FIREWALL = "firewall"; + public static final String FRONTEND = "frontend"; + public static final String INTERFACE = "interface"; + public static final String KEYVALUESTORE = "keyvaluestore"; + public static final String LOADBALANCER = "loadbalancer"; + public static final String MESSAGEQUEUE = "messagequeue"; + public static final String REPLICASET = "replicaset"; + public static final String SECRET = "secret"; + public static final String STATEFULSET = "statefulset"; + public static final String VOLUME = "volume"; + + private final Map iconsAndAliases = new HashMap<>(); + + public IconMapping() { + iconsAndAliases.put("webservice", "application"); + iconsAndAliases.put(CACHE, "flash-circle"); + iconsAndAliases.put(FIREWALL, "wall"); + iconsAndAliases.put(VOLUME, "harddisk"); + iconsAndAliases.put(BACKEND, "application-cog"); + iconsAndAliases.put(SECRET, "application-cog"); + iconsAndAliases.put(LOADBALANCER, "call-split"); + iconsAndAliases.put(STATEFULSET, "harddisk-plus"); + iconsAndAliases.put(REPLICASET, "content-copy"); + iconsAndAliases.put(KEYVALUESTORE, "view-list"); + iconsAndAliases.put(INTERFACE, "connection"); + iconsAndAliases.put(CONTAINER, "inbox"); + iconsAndAliases.put(FRONTEND, "television-guide"); + iconsAndAliases.put(MESSAGEQUEUE, "tray-full"); + iconsAndAliases.put(DEPLOYMENT, "rocket-launch"); + iconsAndAliases.put(POD, "application"); + + Path path = Paths.get("src", "main", "resources", "static", "icons", "meta.json"); + ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + try { + MetaEntry[] metaEntries = objectMapper.readValue(path.toFile(), MetaEntry[].class); + Arrays.stream(metaEntries).forEach(metaEntry -> { + iconsAndAliases.put(metaEntry.name, metaEntry.name); + if (metaEntry.aliases != null) { + Arrays.stream(metaEntry.aliases).forEach(s -> iconsAndAliases.put(s, metaEntry.name)); + } + }); + } catch (IOException e) { + LOGGER.error("Failed to read icon list", e); + } } - public static Optional of(String serviceType) { - return Arrays.stream(values()) - .filter(iconMapping -> iconMapping.name().equalsIgnoreCase(serviceType)) - .findFirst(); + public Optional getIcon(@Nullable final String nameOrAlias) { + return Optional.ofNullable(nameOrAlias) + .map(s -> s.toLowerCase(Locale.ROOT)) + .flatMap(s -> Optional.ofNullable(iconsAndAliases.get(s))); } - public String getIcon() { - return icon; + private static class MetaEntry { + // "ab-testing", + public String name; + public String[] aliases; } } diff --git a/src/main/java/de/bonndan/nivio/output/icons/IconService.java b/src/main/java/de/bonndan/nivio/output/icons/IconService.java index f1428be0a..19da35e68 100644 --- a/src/main/java/de/bonndan/nivio/output/icons/IconService.java +++ b/src/main/java/de/bonndan/nivio/output/icons/IconService.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.output.icons; import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.util.URLHelper; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -21,10 +20,12 @@ public class IconService { private final LocalIcons localIcons; private final ExternalIcons externalIcons; + private final IconMapping iconMapping; public IconService(LocalIcons localIcons, ExternalIcons externalIcons) { this.localIcons = localIcons; this.externalIcons = externalIcons; + this.iconMapping = new IconMapping(); } /** @@ -40,7 +41,7 @@ public String getIconUrl(Item item) { //icon label based String icon = item.getIcon(); - if (!StringUtils.isEmpty(icon)) { + if (StringUtils.hasLength(icon)) { if (icon.startsWith(DataUrlHelper.DATA_IMAGE)) { return icon; @@ -66,12 +67,12 @@ public String getIconUrl(Item item) { //type based String type = item.getType(); - if (StringUtils.isEmpty(type)) { + if (!StringUtils.hasLength(type)) { return localIcons.getDefaultIcon(); } //fallback to item.type - String iconName = IconMapping.of(type.toLowerCase()).map(IconMapping::getIcon).orElseGet(type::toLowerCase); + String iconName = iconMapping.getIcon(type.toLowerCase()).orElseGet(type::toLowerCase); return localIcons.getIconUrl(iconName).orElse(localIcons.getDefaultIcon()); } @@ -84,4 +85,4 @@ public String getIconUrl(Item item) { public Optional getExternalUrl(URL url) { return externalIcons.getUrl(url); } -} +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/output/icons/LocalIcons.java b/src/main/java/de/bonndan/nivio/output/icons/LocalIcons.java index 2ca6c381f..5da505ad5 100644 --- a/src/main/java/de/bonndan/nivio/output/icons/LocalIcons.java +++ b/src/main/java/de/bonndan/nivio/output/icons/LocalIcons.java @@ -43,12 +43,12 @@ public class LocalIcons { * @param iconFolder optional dir containing a different icon set */ public LocalIcons(@NonNull final String iconFolder) { - if (!StringUtils.isEmpty(Objects.requireNonNull(iconFolder))) { + if (StringUtils.hasLength(Objects.requireNonNull(iconFolder))) { this.iconFolder = iconFolder.endsWith("/") || iconFolder.endsWith("\\") ? iconFolder : iconFolder + File.separator; } else { this.iconFolder = DEFAULT_ICONS_FOLDER; } - defaultIcon = getIconUrl(DEFAULT_ICON.getIcon()).orElseThrow(() -> { + defaultIcon = getIconUrl(DEFAULT_ICON).orElseThrow(() -> { throw new RuntimeException(String.format(initErrorMsg, this.iconFolder)); }); } @@ -63,7 +63,7 @@ public LocalIcons() { * @return an url pointing to a file or a data url */ Optional getIconUrl(String icon) { - if (StringUtils.isEmpty(icon)) { + if (!StringUtils.hasLength(icon)) { return Optional.empty(); } @@ -105,9 +105,7 @@ private Optional asSVGDataUrl(String path) { Optional dataUrl = DataUrlHelper.asBase64(path).map(s -> DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + s); dataUrl.ifPresentOrElse( s -> iconDataUrls.put(path, s), - () -> { - LOGGER.warn("Failed to load svg icon {}", path); - } + () -> LOGGER.warn("Failed to load svg icon {}", path) ); return dataUrl; } diff --git a/src/main/java/de/bonndan/nivio/output/layout/AllGroupsLayout.java b/src/main/java/de/bonndan/nivio/output/layout/AllGroupsLayout.java index 777c1ad85..5518caa64 100644 --- a/src/main/java/de/bonndan/nivio/output/layout/AllGroupsLayout.java +++ b/src/main/java/de/bonndan/nivio/output/layout/AllGroupsLayout.java @@ -38,7 +38,7 @@ public AllGroupsLayout(Landscape landscape, Map groups, Map items) { items.forEach(item -> { final String group; - if (StringUtils.isEmpty(item.getGroup())) { + if (!StringUtils.hasLength(item.getGroup())) { LOGGER.warn("Item {} has no group, using " + Group.COMMON, item); group = Group.COMMON; } else { diff --git a/src/main/java/de/bonndan/nivio/output/layout/AppearanceProcessor.java b/src/main/java/de/bonndan/nivio/output/layout/AppearanceProcessor.java new file mode 100644 index 000000000..56fd96d30 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/layout/AppearanceProcessor.java @@ -0,0 +1,55 @@ +package de.bonndan.nivio.output.layout; + +import de.bonndan.nivio.model.Item; +import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.model.Labeled; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.output.icons.IconService; +import de.bonndan.nivio.util.URLHelper; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.util.Objects; + +/** + * Resolves color and icons for {@link de.bonndan.nivio.model.Component} + */ +@Service +public class AppearanceProcessor { + + private final IconService iconService; + + public AppearanceProcessor(IconService iconService) { + this.iconService = iconService; + } + + public void process(@NonNull final Landscape landscape) { + Objects.requireNonNull(landscape).getGroupItems().forEach(group -> { + setIconFillAppearance(group); + landscape.getItems().retrieve(group.getItems()).forEach(this::setIconFillAppearance); + }); + setIconFillAppearance(landscape); + } + + private void setIconFillAppearance(Labeled labeled) { + + if (labeled instanceof Item) { + labeled.setLabel(Label._icondata, iconService.getIconUrl((Item) labeled)); + } else { + String icon = labeled.getLabel(Label.icon); + if (StringUtils.hasLength(icon)) { + URLHelper.getURL(icon) + .flatMap(iconService::getExternalUrl) + .ifPresent(s -> labeled.setLabel(Label._icondata, s)); + } + } + + String fill = labeled.getLabel(Label.fill); + if (StringUtils.hasLength(fill)) { + URLHelper.getURL(fill) + .flatMap(iconService::getExternalUrl) + .ifPresent(s -> labeled.setLabel(Label._filldata, s)); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/output/layout/LayoutChangedEvent.java b/src/main/java/de/bonndan/nivio/output/layout/LayoutChangedEvent.java new file mode 100644 index 000000000..5ac1380ed --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/layout/LayoutChangedEvent.java @@ -0,0 +1,32 @@ +package de.bonndan.nivio.output.layout; + +import de.bonndan.nivio.input.ProcessingEvent; +import de.bonndan.nivio.model.Landscape; +import org.springframework.context.ApplicationEvent; +import org.springframework.lang.NonNull; + +public class LayoutChangedEvent extends ProcessingEvent { + + @NonNull + private final String msg; + + public LayoutChangedEvent(@NonNull final Landscape landscape, @NonNull final String msg) { + super(landscape.getFullyQualifiedIdentifier()); + this.msg = msg; + } + + @Override + public String getLevel() { + return ProcessingEvent.LOG_LEVEL_INFO; + } + + @Override + public String getType() { + return getClass().getSimpleName(); + } + + @Override + public String getMessage() { + return msg; + } +} diff --git a/src/main/java/de/bonndan/nivio/output/layout/LayoutConfig.java b/src/main/java/de/bonndan/nivio/output/layout/LayoutConfig.java new file mode 100644 index 000000000..6395823a3 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/layout/LayoutConfig.java @@ -0,0 +1,18 @@ +package de.bonndan.nivio.output.layout; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LayoutConfig { + + /** + * This could be made configurable, but for now there is only one layouter implementation. + * + * @return the organic layouter + */ + @Bean + public Layouter getLayouter() { + return new OrganicLayouter(); + } +} diff --git a/src/main/java/de/bonndan/nivio/output/layout/LayoutService.java b/src/main/java/de/bonndan/nivio/output/layout/LayoutService.java new file mode 100644 index 000000000..6f34552fb --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/layout/LayoutService.java @@ -0,0 +1,75 @@ +package de.bonndan.nivio.output.layout; + +import de.bonndan.nivio.assessment.Assessment; +import de.bonndan.nivio.assessment.AssessmentChangedEvent; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.output.Renderer; +import de.bonndan.nivio.output.map.RenderingRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationListener; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +/** + * Service to generate the graphical appearance of a landscape. + * + * Appearance must be determined after indexing, because values might be needed in api, too. + */ +@Service +public class LayoutService implements ApplicationListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(LayoutService.class); + + private final AppearanceProcessor appearanceProcessor; + private final Layouter layouter; + private final Renderer renderer; + private final RenderingRepository renderingRepository; + private final ApplicationEventPublisher eventPublisher; + + public LayoutService(final AppearanceProcessor appearanceProcessor, + final Layouter layouter, + final Renderer renderer, + final RenderingRepository renderingRepository, + final ApplicationEventPublisher eventPublisher + ) { + this.appearanceProcessor = appearanceProcessor; + this.layouter = layouter; + this.renderer = renderer; + this.renderingRepository = renderingRepository; + this.eventPublisher = eventPublisher; + } + + @Override + public void onApplicationEvent(@NonNull final AssessmentChangedEvent event) { + Landscape landscape = event.getLandscape(); + appearanceProcessor.process(landscape); + Assessment assessment = event.getAssessment(); + LayoutedComponent layout = layout(landscape); + + var debug = false; + var artefact = renderer.render(layout, assessment, debug); + renderingRepository.save(renderer.getRenderingType(), landscape, artefact, debug); + LOGGER.info("Generated {} rendering of landscape {} (debug: {})", renderer.getRenderingType(), landscape.getIdentifier(), debug); + eventPublisher.publishEvent(new LayoutChangedEvent(landscape, "Rendered landscape " + landscape.getIdentifier())); + } + + public LayoutedComponent layout(@NonNull final Landscape landscape) { + return layouter.layout(Objects.requireNonNull(landscape)); + } + + /** + * Layouts and renders the given landscape. + * + * @param landscape landscape + * @param assessment the related assessment + * @param debug flag to add debug info + * @return renderer artefact + */ + public Object render(@NonNull final Landscape landscape, @NonNull final Assessment assessment, boolean debug) { + return renderer.render(layout(landscape), Objects.requireNonNull(assessment), debug); + } +} diff --git a/src/main/java/de/bonndan/nivio/output/layout/LayoutedComponent.java b/src/main/java/de/bonndan/nivio/output/layout/LayoutedComponent.java index 1e470183b..7719377fb 100644 --- a/src/main/java/de/bonndan/nivio/output/layout/LayoutedComponent.java +++ b/src/main/java/de/bonndan/nivio/output/layout/LayoutedComponent.java @@ -13,7 +13,7 @@ /** * A value object to hold dimensions and position data of rendered {@link Component}s. - * + *

* Also holds children to allow recursive operations. */ public class LayoutedComponent { @@ -30,9 +30,8 @@ public class LayoutedComponent { @Nullable private String defaultColor; - public LayoutedComponent(@NonNull Component component, List opposites) { - Objects.requireNonNull(component); - this.component = component; + public LayoutedComponent(@NonNull final Component component, List opposites) { + this.component = Objects.requireNonNull(component); this.opposites = opposites; } @@ -91,7 +90,7 @@ public List getChildren() { public String getFill() { if (component instanceof Item) { - return ((Item) component).getLabel(Label.fill); + return ((Item) component).getLabel(Label._filldata); } return null; @@ -105,17 +104,21 @@ public String toString() { } public String getIcon() { - return component.getIcon(); + if (component instanceof Item) { + return ((Item) component).getLabel(Label._icondata); + } + + return null; } public String getColor() { - if (!StringUtils.isEmpty(component.getColor())) { + if (StringUtils.hasLength(component.getColor())) { return component.getColor(); } return defaultColor; } public void setDefaultColor(String color) { - this.defaultColor =color; + this.defaultColor = color; } } diff --git a/src/main/java/de/bonndan/nivio/output/layout/Layouter.java b/src/main/java/de/bonndan/nivio/output/layout/Layouter.java index db802d33c..ad429fe86 100644 --- a/src/main/java/de/bonndan/nivio/output/layout/Layouter.java +++ b/src/main/java/de/bonndan/nivio/output/layout/Layouter.java @@ -6,9 +6,8 @@ /** * Layouts / arranges landscapes. * - * @param type where layout values are stored */ -public interface Layouter { +public interface Layouter { /** * Arranges the landscape components. diff --git a/src/main/java/de/bonndan/nivio/output/layout/OrganicLayouter.java b/src/main/java/de/bonndan/nivio/output/layout/OrganicLayouter.java index f9c135371..7cf065d0c 100644 --- a/src/main/java/de/bonndan/nivio/output/layout/OrganicLayouter.java +++ b/src/main/java/de/bonndan/nivio/output/layout/OrganicLayouter.java @@ -17,19 +17,16 @@ /** * Applies {@link FastOrganicLayout} to landscape components and writes the rendered data to component labels. */ -public class OrganicLayouter implements Layouter { +public class OrganicLayouter implements Layouter { private static final Logger LOGGER = LoggerFactory.getLogger(OrganicLayouter.class); - public OrganicLayouter() { - } - @Override public LayoutedComponent layout(@NonNull final Landscape landscape) { Map subGraphs = new LinkedHashMap<>(); - Objects.requireNonNull(landscape).getGroups().forEach((name, groupItem) -> { - SubLayout subLayout = new SubLayout(groupItem, groupItem.getItems(), landscape.getConfig().getItemLayoutConfig()); + Objects.requireNonNull(landscape).getGroups().forEach((name, group) -> { + SubLayout subLayout = new SubLayout(group, landscape.getItems().retrieve(group.getItems()), landscape.getConfig().getItemLayoutConfig()); subGraphs.put(name, subLayout); }); diff --git a/src/main/java/de/bonndan/nivio/output/layout/SubLayout.java b/src/main/java/de/bonndan/nivio/output/layout/SubLayout.java index 0cee32937..7d6c89299 100644 --- a/src/main/java/de/bonndan/nivio/output/layout/SubLayout.java +++ b/src/main/java/de/bonndan/nivio/output/layout/SubLayout.java @@ -12,7 +12,7 @@ /** * Layout for one group (for the items INSIDE the group). - *

+ * */ public class SubLayout { @@ -42,11 +42,12 @@ public SubLayout(Component group, Set items, LandscapeConfig.LayoutConfig return; Item other = relationItem.getTarget(); - if (item.getGroup() == null) - throw new RuntimeException("Item " + item + "has no group"); - if (other.getGroup() == null) - throw new RuntimeException("Item " + other + "has no group"); - + if (item.getGroup() == null) { + throw new IllegalStateException(String.format("Item %s has no group", item)); + } + if (other.getGroup() == null) { + throw new IllegalStateException(String.format("Item %s has no group", other)); + } if (item.getGroup().equals(other.getGroup())) { relationTargets.add(other); diff --git a/src/main/java/de/bonndan/nivio/output/map/MapController.java b/src/main/java/de/bonndan/nivio/output/map/MapController.java index 18a6dde75..6a1d24dc7 100644 --- a/src/main/java/de/bonndan/nivio/output/map/MapController.java +++ b/src/main/java/de/bonndan/nivio/output/map/MapController.java @@ -3,6 +3,7 @@ import de.bonndan.nivio.api.NotFoundException; import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.model.LandscapeRepository; +import de.bonndan.nivio.output.map.svg.SVGRenderer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; @@ -21,11 +22,11 @@ public class MapController { public static final String PATH = "/render"; private final LandscapeRepository landscapeRepository; - private final RenderCache renderCache; + private final RenderingRepository renderingRepository; - public MapController(LandscapeRepository landscapeRepository, RenderCache renderCache) { + public MapController(LandscapeRepository landscapeRepository, RenderingRepository renderingRepository) { this.landscapeRepository = landscapeRepository; - this.renderCache = renderCache; + this.renderingRepository = renderingRepository; } @CrossOrigin(methods = RequestMethod.GET) @@ -38,14 +39,15 @@ public ResponseEntity svg(@PathVariable(name = "landscape") final String try { HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_TYPE, "image/svg+xml"); + String xml = (String) renderingRepository.get(SVGRenderer.RENDERING_TYPE, landscape, debug).orElseThrow(); return new ResponseEntity<>( - renderCache.getSVG(landscape, debug), + xml, headers, HttpStatus.OK ); } catch (Exception ex) { - LOGGER.warn("Could not render svg: ", ex); - throw ex; + LOGGER.warn("Could not obtain svg: ", ex); + throw new RuntimeException("Failed to obtains svg", ex); } } diff --git a/src/main/java/de/bonndan/nivio/output/map/RenderCache.java b/src/main/java/de/bonndan/nivio/output/map/RenderCache.java deleted file mode 100644 index 4ab8eace3..000000000 --- a/src/main/java/de/bonndan/nivio/output/map/RenderCache.java +++ /dev/null @@ -1,81 +0,0 @@ -package de.bonndan.nivio.output.map; - -import de.bonndan.nivio.assessment.Assessment; -import de.bonndan.nivio.assessment.AssessmentRepository; -import de.bonndan.nivio.input.ProcessingFinishedEvent; -import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.output.layout.LayoutedComponent; -import de.bonndan.nivio.output.layout.Layouter; -import de.bonndan.nivio.output.layout.OrganicLayouter; -import de.bonndan.nivio.output.map.svg.SVGRenderer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.lang.Nullable; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.Map; - -/** - * A service that caches map rendering. - */ -@Service -public class RenderCache implements ApplicationListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(RenderCache.class); - - /** - * cache map, key is FQI string representation (or debugged version) - */ - private final Map renderings = new HashMap<>(); - - private final AssessmentRepository assessmentRepository; - private final Layouter layouter; - private final SVGRenderer svgRenderer; - - public RenderCache(final SVGRenderer svgRenderer, AssessmentRepository assessmentRepository) { - this.assessmentRepository = assessmentRepository; - this.svgRenderer = svgRenderer; - layouter = new OrganicLayouter(); - } - - /** - * Returns an svg. - * - * @param landscape the landscape to render - * @param debug flag to enable debug messages - * @return the svg as string - */ - @Nullable - public String getSVG(Landscape landscape, boolean debug) { - - String key = getKey(landscape, debug); - if (!renderings.containsKey(key)) { - createCacheEntry(landscape, getAssessment(landscape), debug); - } - - return renderings.get(key); - } - - private String getKey(Landscape landscape, boolean debug) { - return landscape.getFullyQualifiedIdentifier().toString() + (debug ? "debug" : ""); - } - - private void createCacheEntry(Landscape landscape, Assessment assessment, boolean debug) { - LayoutedComponent layout = layouter.layout(landscape); - LOGGER.info("Generating SVG rendering of landscape {} (debug: {})", landscape.getIdentifier(), debug); - renderings.put(getKey(landscape, debug), svgRenderer.render(layout, assessment, debug).getXML()); - } - - @Override - public void onApplicationEvent(ProcessingFinishedEvent processingFinishedEvent) { - Landscape landscape = processingFinishedEvent.getLandscape(); - createCacheEntry(landscape, getAssessment(landscape), false); - } - - private Assessment getAssessment(Landscape landscape) { - var assessment = assessmentRepository.getAssessment(landscape.getFullyQualifiedIdentifier()); - return assessment.orElseGet(() -> assessmentRepository.createAssessment(landscape)); - } -} diff --git a/src/main/java/de/bonndan/nivio/output/map/RenderingRepository.java b/src/main/java/de/bonndan/nivio/output/map/RenderingRepository.java new file mode 100644 index 000000000..481a8c70b --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/map/RenderingRepository.java @@ -0,0 +1,50 @@ +package de.bonndan.nivio.output.map; + +import de.bonndan.nivio.model.Landscape; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; + +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A service that caches map rendering. + */ +@Service +public class RenderingRepository { + + /** + * cache map, key is FQI string representation (or debugged version) + */ + private final Map renderings = new ConcurrentHashMap<>(); + + /** + * Returns an svg. + * + * @param landscape the landscape to render + * @param debug flag to enable debug messages + * @return the svg as string + */ + @NonNull + public Optional get(@NonNull final String artefactType, @NonNull final Landscape landscape, boolean debug) { + return Optional.ofNullable(renderings.get(getKey(landscape, artefactType, debug))); + } + + /** + * Saves a rendered artefact. + * + * @param artefactType type artefact + * @param landscape the related landscape + * @param artefact the rendered artefact + * @param debug flag + */ + public void save(String artefactType, @NonNull final Landscape landscape, @NonNull final Object artefact, boolean debug) { + renderings.put(getKey(landscape, artefactType, debug), artefact); + } + + private String getKey(Landscape landscape, String type, boolean debug) { + return Objects.requireNonNull(landscape).getFullyQualifiedIdentifier() + Objects.requireNonNull(type) + (debug ? "debug" : ""); + } +} diff --git a/src/main/java/de/bonndan/nivio/output/map/hex/GroupAreaFactory.java b/src/main/java/de/bonndan/nivio/output/map/hex/GroupAreaFactory.java index ba22918ed..1f6f7fd2d 100644 --- a/src/main/java/de/bonndan/nivio/output/map/hex/GroupAreaFactory.java +++ b/src/main/java/de/bonndan/nivio/output/map/hex/GroupAreaFactory.java @@ -3,7 +3,6 @@ import de.bonndan.nivio.model.Group; import de.bonndan.nivio.model.Item; import de.bonndan.nivio.output.map.svg.HexPath; -import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,6 +18,8 @@ public class GroupAreaFactory { private static final Logger LOGGER = LoggerFactory.getLogger(GroupAreaFactory.class); + private GroupAreaFactory(){} + /** * Builds an areas of hex tiles belonging to a group. *

@@ -32,9 +33,8 @@ public class GroupAreaFactory { * @param group the group * @return all hexes the group consists of (an area) */ - public static Set getGroup(Map itemsToHexes, Group group) { + public static Set getGroup(Map itemsToHexes, Group group, Set items) { - Set items = group.getItems(); Set inArea = new HashSet<>(); if (!items.iterator().hasNext()) { @@ -42,6 +42,9 @@ public static Set getGroup(Map itemsToHexes, Group group) { return inArea; } + //simple occupations per item + addItemsAndNeighbours(itemsToHexes, items, inArea); + //build the area by adding paths addPathsBetweenClosestItems(itemsToHexes, items, inArea); @@ -57,6 +60,21 @@ public static Set getGroup(Map itemsToHexes, Group group) { return inArea; } + /** + * Every item itself and its neighbours are added + */ + private static void addItemsAndNeighbours(Map itemsToHexes, + Set items, + Set inArea + ) { + items.forEach(next -> { + LOGGER.debug("adding {} to group area", next); + Hex hex = itemsToHexes.get(next); + inArea.add(hex); + inArea.addAll(hex.neighbours()); + }); + } + /** * Generates paths between each item and its closest neighbour and added tiles of the paths to the group area. * @@ -74,13 +92,6 @@ private static void addPathsBetweenClosestItems(Map itemsToHexes, LOGGER.debug("adding {} to group area", next); Hex hex = itemsToHexes.get(next); - //the item itself is added automatically - inArea.add(hex); - //every "unregistered" neighbour is added automatically - hex.neighbours().forEach(neigh -> { - if (!itemsToHexes.containsKey(neigh)) - inArea.add(neigh); - }); Optional closest = getClosestItem(next, items, itemsToHexes, connected); if (closest.isEmpty()) { @@ -191,7 +202,7 @@ static Set getBridges(Set inArea, int minSides) { * * @param sidesWithNeighbours numbers of sides having a same-group neighbour (0..5) */ - static private boolean hasOppositeNeighbours(List sidesWithNeighbours) { + private static boolean hasOppositeNeighbours(List sidesWithNeighbours) { for (int i = 0; i < sidesWithNeighbours.size(); i++) { Integer integer = sidesWithNeighbours.get(i); diff --git a/src/main/java/de/bonndan/nivio/output/map/hex/Hex.java b/src/main/java/de/bonndan/nivio/output/map/hex/Hex.java index 4a7fafa96..50f8f6909 100644 --- a/src/main/java/de/bonndan/nivio/output/map/hex/Hex.java +++ b/src/main/java/de/bonndan/nivio/output/map/hex/Hex.java @@ -40,9 +40,16 @@ public class Hex { //double DEFAULT_ICON_SIZE public static final int HEX_SIZE = 2 * DEFAULT_ICON_SIZE; + public static final int SOUTH_EAST = 0; + public static final int SOUTH = 1; + public static final int SOUTH_WEST = 2; + public static final int NORTH_WEST = 3; + public static final int NORTH = 4; + public static final int NORTH_EAST = 5; + /** * q coordinate - *

+ * * For coords see https://www.redblobgames.com/grids/hexagons/#coordinates */ public final int q; @@ -65,7 +72,7 @@ public class Hex { */ public Hex(int q, int r, int s) { if (q + r + s != 0) { - throw new RuntimeException("q + r + s must be 0"); + throw new IllegalArgumentException("q + r + s must be 0"); } this.q = q; this.r = r; @@ -100,7 +107,7 @@ public static Hex of(long x, long y, float scaling) { double s = -q - r; if (Math.round(q + r + s) != 0) { - throw new RuntimeException("q + r + s must be 0"); + throw new IllegalArgumentException("q + r + s must be 0"); } int qi = (int) Math.round(q); @@ -172,6 +179,16 @@ public static Hex topLeft(Collection area) { return topLeft.get(); } + public int getDirectionTo(@NonNull final Hex hex) { + List neighbours = neighbours(); + for (int i = 0, neighboursSize = neighbours.size(); i < neighboursSize; i++) { + Hex hex1 = neighbours.get(i); + if (hex1.equals(hex)) return i; + } + + throw new IllegalArgumentException("Not an adjacent hex given."); + } + /** * flat orientation (flat top) @@ -207,11 +224,14 @@ private Hex direction(int _direction) { /** * see https://www.redblobgames.com/grids/hexagons/implementation.html#hex-geometry + * + * @param corner number + * @param size hex size */ - private Point2D.Double hex_corner_offset(int corner, int s) { - Point2D.Double size = new Point2D.Double(s, s); + public static Point2D.Double getCornerCoordinates(float corner, int size) { + Point2D.Double point = new Point2D.Double(size, size); double angle = 2.0 * Math.PI * (startAngle + corner) / 6; - return new Point2D.Double(size.x * Math.cos(angle), size.y * Math.sin(angle)); + return new Point2D.Double(point.x * Math.cos(angle), point.y * Math.sin(angle)); } /** @@ -225,7 +245,7 @@ public ArrayList asPoints(int size) { ArrayList corners = new ArrayList<>(); Point2D.Double center = toPixel(); for (int i = 0; i < 6; i++) { - Point2D.Double offset = hex_corner_offset(i, size); + Point2D.Double offset = getCornerCoordinates(i, size); corners.add( new Point2D.Double(Math.round((center.x + offset.x)*10)/10f, Math.round((center.y + offset.y)*10)/10f) ); diff --git a/src/main/java/de/bonndan/nivio/output/map/hex/HexMap.java b/src/main/java/de/bonndan/nivio/output/map/hex/HexMap.java index 64261adc2..d05d8204a 100644 --- a/src/main/java/de/bonndan/nivio/output/map/hex/HexMap.java +++ b/src/main/java/de/bonndan/nivio/output/map/hex/HexMap.java @@ -72,10 +72,11 @@ public Optional getPath(Item start, Item target) { * Returns all hexes which form a group area. * * @param group the group with items + * @param items * @return a set of (adjacent) hexes */ - public Set getGroupArea(Group group) { - Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); + public Set getGroupArea(Group group, Set items) { + Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, items); inArea.forEach(hex -> hexesToItems.putIfAbsent(hex, UUID.randomUUID())); return inArea; } diff --git a/src/main/java/de/bonndan/nivio/output/map/hex/PathFinder.java b/src/main/java/de/bonndan/nivio/output/map/hex/PathFinder.java index 20d7e7904..95ff0a05e 100644 --- a/src/main/java/de/bonndan/nivio/output/map/hex/PathFinder.java +++ b/src/main/java/de/bonndan/nivio/output/map/hex/PathFinder.java @@ -41,14 +41,11 @@ private Tile getBest() { for (int i = open.size() - 1; i >= 0; i--) { // pick the lowest sum of move and heuristic - if (open.get(i).sumCosts < tmp.sumCosts) { - tmp = open.get(i); - - //or equal sum and lower heuristic - } else if (open.get(i).sumCosts == tmp.sumCosts && open.get(i).heuristicCosts < tmp.heuristicCosts) { + boolean lowestCost = open.get(i).sumCosts < tmp.sumCosts; + boolean equalCostLowerHeuristic = open.get(i).sumCosts == tmp.sumCosts && open.get(i).heuristicCosts < tmp.heuristicCosts; + if (lowestCost || equalCostLowerHeuristic) { tmp = open.get(i); } - } open.remove(tmp); @@ -84,7 +81,7 @@ public Optional getPath(Hex startHex, Hex destHex) { * Limit the amount of loops for better performance */ if (depth >= DEPTH_MAX) { - LOGGER.error(String.format("Max depth exceeded searching path from %s to %s", startHex, destHex)); + LOGGER.error("Max depth exceeded searching path from {} to {}", startHex, destHex); return Optional.empty(); } @@ -166,10 +163,10 @@ public Optional getPath(Hex startHex, Hex destHex) { tileBetween = tileBetween.getParent(); if (path.contains(tileBetween)) { //already contains the parent - throw new RuntimeException("Path already contains the parent."); + throw new IllegalStateException("Path already contains the parent."); } if (!dst.equals(tileBetween) && !start.equals(tileBetween) && tileBetween.hex.item != null) { - throw new RuntimeException(String.format("Path from %s to %s runs through item %s!", start, dst, tileBetween)); + throw new IllegalStateException(String.format("Path from %s to %s runs through item %s!", start, dst, tileBetween)); } path.add(tileBetween); @@ -190,7 +187,6 @@ public Optional getPath(Hex startHex, Hex destHex) { return Optional.of(new HexPath(path.stream().map(tile -> tile.hex).collect(Collectors.toList()))); } - private List getNeighbours(Tile current) { return current.hex.neighbours().stream() diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/HexPath.java b/src/main/java/de/bonndan/nivio/output/map/svg/HexPath.java index 9c2d35ab4..2b4e34908 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/HexPath.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/HexPath.java @@ -14,7 +14,8 @@ public class HexPath { private final List hexes; private final List points = new ArrayList<>(); - private final List bends; + private List bends; + private List directions; private final Point2D.Double endPoint; /** @@ -22,12 +23,12 @@ public class HexPath { */ public HexPath(final List hexes) { this.hexes = hexes; - this.bends = calcBends(hexes); + calcBends(hexes); this.endPoint = calcPoints(); } /** - * @return a list of strings forming a path of cubic curves + * @return the endpoint of a list of strings forming a path of cubic curves */ private Point2D.Double calcPoints() { points.add("M"); @@ -59,19 +60,21 @@ private Point2D.Double calcPoints() { newAfter.y = next.y + (point.y - next.y) / 10; points.addAll(List.of(String.valueOf(newAfter.x), ",", String.valueOf(newAfter.y))); return new Point2D.Double(point.x, point.y); - } else { - points.addAll(List.of(String.valueOf(newAfter.x), ",", String.valueOf(newAfter.y), " L")); } + + points.addAll(List.of(String.valueOf(newAfter.x), ",", String.valueOf(newAfter.y), " L")); + } else { if (isLast) { var newAfter = new Point2D.Double(); - newAfter.x = point.x - (point.x - prev.x) / 2; - newAfter.y = point.y - (point.y - prev.y) / 2; + //2.1 to prevent that the same point is hit as above (results in broken dataflow markers) + newAfter.x = point.x - (point.x - prev.x) / 2.1; + newAfter.y = point.y - (point.y - prev.y) / 2.1; points.addAll(List.of(" ", String.valueOf(newAfter.x), ",", String.valueOf(newAfter.y))); return new Point2D.Double(newAfter.x, newAfter.y); - } else { - points.addAll(List.of(" ", String.valueOf(point.x), ",", String.valueOf(point.y), " L")); } + + points.addAll(List.of(" ", String.valueOf(point.x), ",", String.valueOf(point.y), " L")); } } return null; @@ -115,23 +118,38 @@ private boolean isBend(Hex hex) { * Returns the bends from a list of adjacent hexes (a chain). * * @param hexes the hex chain - * @return all hexes which are bends / curves */ - public static List calcBends(final List hexes) { + void calcBends(final List hexes) { - final List bends = new ArrayList<>(); + bends = new ArrayList<>(); + directions = new ArrayList<>(); var i = 0; for (i = 1; i < hexes.size() - 1; i++) { var prev = hexes.get(i - 1); var cur = hexes.get(i); var next = hexes.get(i + 1); + + //bends var qBend = (prev.q == cur.q && next.q != cur.q) || (prev.q != cur.q && next.q == cur.q); var rBend = (prev.r == cur.r && next.r != cur.r) || (prev.r != cur.r && next.r == cur.r); if (qBend || rBend) { bends.add(cur); } + + //directions + directions.add(prev.getDirectionTo(cur)); + + if (i == hexes.size() - 2) { + directions.add(cur.getDirectionTo(next)); + } } + } + + public List getBends() { + return Collections.unmodifiableList(bends); + } - return bends; + public List getDirections() { + return Collections.unmodifiableList(directions); } } diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java index b088ce303..39c49ea2f 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGDocument.java @@ -1,10 +1,7 @@ package de.bonndan.nivio.output.map.svg; import de.bonndan.nivio.assessment.*; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.*; import de.bonndan.nivio.output.layout.LayoutedComponent; import de.bonndan.nivio.output.map.hex.Hex; import de.bonndan.nivio.output.map.hex.HexMap; @@ -41,11 +38,16 @@ public class SVGDocument extends Component { private boolean debug = false; private HexMap hexMap; + private static final String CLASS = "class"; + private static final String WIDTH = "width"; + private static final String HEIGHT = "height"; + + public SVGDocument(@NonNull final LayoutedComponent layouted, @Nullable final Assessment assessment, @Nullable final String cssStyles) { this.layouted = Objects.requireNonNull(layouted); this.landscape = (Landscape) layouted.getComponent(); this.assessment = assessment == null ? AssessmentFactory.createAssessment(Map.of()) : assessment; - this.cssStyles = StringUtils.isEmpty(cssStyles) ? "" : cssStyles; + this.cssStyles = !StringUtils.hasLength(cssStyles) ? "" : cssStyles; } public void setDebug(boolean debug) { @@ -75,27 +77,28 @@ public DomContent render() { Item item = (Item) layoutedItem.getComponent(); //collect patterns for icons - if (!StringUtils.isEmpty(layoutedItem.getFill())) { - SVGPattern SVGPattern = new SVGPattern(layoutedItem.getFill()); - defs.add(SVGPattern.render()); + if (StringUtils.hasLength(layoutedItem.getFill())) { + SVGPattern svgPattern = new SVGPattern(layoutedItem.getFill()); + defs.add(svgPattern.render()); } //render icons SVGItemLabel label = new SVGItemLabel(item); Point2D.Double pos = hexMap.hexForItem(item).toPixel(); - List itemStatuses = assessment.getResults().get(item.getFullyQualifiedIdentifier()); - SVGItem SVGItem = new SVGItem(label.render(), layoutedItem, itemStatuses, pos); - items.add(SVGItem.render()); + List itemStatuses = assessment.getResults().get(item.getFullyQualifiedIdentifier().toString()); + SVGItem svgItem = new SVGItem(label.render(), layoutedItem, itemStatuses, pos); + items.add(svgItem.render()); }); }); List groupAreas = new ArrayList<>(); List groups = layouted.getChildren().stream().map(groupLayout -> { Group group = (Group) groupLayout.getComponent(); - Set groupArea = hexMap.getGroupArea(group); - List groupStatuses = assessment.getResults().get(group.getFullyQualifiedIdentifier()); - SVGGroupArea area = SVGGroupArea.forGroup(group, groupArea, Assessable.getWorst(groupStatuses), debug); + Set groupArea = hexMap.getGroupArea(group, landscape.getItems().retrieve(group.getItems())); + List groupStatuses = assessment.getResults().get(group.getFullyQualifiedIdentifier().toString()); + Status groupStatus = Assessable.getWorst(groupStatuses).stream().map(StatusValue::getStatus).findFirst().orElse(Status.UNKNOWN); + SVGGroupArea area = SVGGroupArea.forGroup(group, groupArea, groupStatus, debug); groupAreas.add(area); return area.render(); }).collect(Collectors.toList()); @@ -108,7 +111,6 @@ public DomContent render() { //render background hexes defs.add(SVGBackgroundFactory.getHex()); - List background = new ArrayList<>( //SVGBackgroundFactory.getBackgroundTiles(dimension) ); @@ -123,10 +125,10 @@ public DomContent render() { .attr("version", "1.1") .attr("xmlns", "http://www.w3.org/2000/svg") .attr("xmlns:xlink", "http://www.w3.org/1999/xlink") - .attr("width", dimension.cartesian.horMax) - .attr("height", dimension.cartesian.vertMax) + .attr(WIDTH, dimension.cartesian.horMax) + .attr(HEIGHT, dimension.cartesian.vertMax) .attr("viewBox", dimension.cartesian.asViewBox()) - .attr("class", "map") + .attr(CLASS, "map") .with(background) .with(logo, title) @@ -141,14 +143,15 @@ public DomContent render() { @Nullable private DomContent getLogo(SVGDimension dimension) { DomContent logo = null; - String logoUrl = landscape.getIcon(); //has been set by appearance resolver - if (!StringUtils.isEmpty(logoUrl)) { + String logoUrl = landscape.getLabel(Label._icondata); //has been set by appearance resolver + if (StringUtils.hasLength(logoUrl)) { logo = SvgTagCreator.image() .attr("xlink:href", logoUrl) .attr("x", dimension.cartesian.horMin - dimension.cartesian.padding) .attr("y", dimension.cartesian.vertMin - dimension.cartesian.padding + 80) - .attr("width", LABEL_WIDTH) - .attr("height", LABEL_WIDTH); + .attr(WIDTH, LABEL_WIDTH) + .attr(HEIGHT, LABEL_WIDTH) + .attr(CLASS, "logo"); } return logo; } @@ -157,7 +160,7 @@ private ContainerTag getTitle(SVGDimension dimension) { return SvgTagCreator.text(landscape.getName()) .attr("x", dimension.cartesian.horMin - dimension.cartesian.padding) .attr("y", dimension.cartesian.vertMin - dimension.cartesian.padding + 60) - .attr("class", "title"); + .attr(CLASS, "title"); } /** @@ -165,17 +168,15 @@ private ContainerTag getTitle(SVGDimension dimension) { */ private List getRelations(LayoutedComponent layouted) { List relations = new ArrayList<>(); - layouted.getChildren().forEach(layoutedGroup -> { - layoutedGroup.getChildren().forEach(layoutedItem -> { - Item item = (Item) layoutedItem.getComponent(); - LOGGER.debug("Adding {} relations for {}", item.getRelations().size(), item.getFullyQualifiedIdentifier()); - item.getRelations().stream() - .filter(rel -> rel.getSource().equals(item)) //do not paint twice / incoming (inverse) relations - .map(rel -> getSvgRelation(layoutedItem, item, rel)) - .filter(Objects::nonNull) - .forEach(relations::add); - }); - }); + layouted.getChildren().forEach(layoutedGroup -> layoutedGroup.getChildren().forEach(layoutedItem -> { + Item item = (Item) layoutedItem.getComponent(); + LOGGER.debug("Adding {} relations for {}", item.getRelations().size(), item.getFullyQualifiedIdentifier()); + item.getRelations().stream() + .filter(rel -> rel.getSource().equals(item)) //do not paint twice / incoming (inverse) relations + .map(rel -> getSvgRelation(layoutedItem, item, rel)) + .filter(Objects::nonNull) + .forEach(relations::add); + })); return relations; } @@ -194,5 +195,4 @@ private SVGRelation getSvgRelation(LayoutedComponent layoutedItem, Item source, public String getXML() { return render().render(); } -} - +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupArea.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupArea.java index 69854c297..99a9f62b0 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupArea.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupArea.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.output.map.svg; import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Group; import de.bonndan.nivio.output.map.hex.Hex; import j2html.tags.ContainerTag; @@ -37,7 +36,7 @@ class SVGGroupArea extends Component { private final List outlines; @NonNull - private final StatusValue groupStatus; + private final Status groupStatus; @NonNull private final Point2D.Double anchor; @@ -52,7 +51,7 @@ class SVGGroupArea extends Component { */ public static SVGGroupArea forGroup(@NonNull final Group group, @NonNull final Set inArea, - @NonNull final StatusValue groupStatus, + @NonNull final Status groupStatus, boolean debug ) { var fill = Objects.requireNonNull(group).getColor(); @@ -68,7 +67,7 @@ public static SVGGroupArea forGroup(@NonNull final Group group, SVGGroupArea(@NonNull final Group group, @NonNull final Set groupArea, @NonNull final List outlines, - @NonNull final StatusValue groupStatus + @NonNull final Status groupStatus ) { this.group = Objects.requireNonNull(group); this.groupArea = Objects.requireNonNull(groupArea); @@ -89,7 +88,7 @@ public static SVGGroupArea forGroup(@NonNull final Group group, public DomContent render() { List territoryHexes = outlines != null ? new ArrayList<>(outlines) : new ArrayList<>(); String fqi = group.getFullyQualifiedIdentifier().jsonValue(); - if (StringUtils.isEmpty(fqi)) { + if (!StringUtils.hasLength(fqi)) { // we can still render an svg, but area will not be clickable LOGGER.warn("Empty group fqi in SVG group area, group {}", group); } diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactory.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactory.java index 9a2c114bd..089e05d46 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactory.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactory.java @@ -77,7 +77,7 @@ private List getOutline(@NonNull final Hex start, @NonNull final Set pointsPath = BorderHexesGroupOutline.getPath(borderHexes, groupArea); /* style of multiple hexes*/ List territoryHexes = groupArea.stream() - .map(hex -> new SVGHex(hex, fillId, fillId).render()) + .map(hex -> new SVGHex(hex, fillId, fillId, debug).render()) .collect(Collectors.toList()); containerTags.addAll(territoryHexes); break; @@ -99,7 +99,7 @@ private List getOutline(@NonNull final Hex start, @NonNull final Set ContainerTag svgPath = SvgTagCreator.path() .attr("d", pointsPath) .attr("fill", "none") - .condAttr(!StringUtils.isEmpty(fillId), "stroke", fillId) + .condAttr(StringUtils.hasLength(fillId), "stroke", fillId) .attr("stroke-width", 3); containerTags.add(svgPath); } @@ -143,7 +143,7 @@ private static Position getNext(@NonNull Position startPosition, Set allInG //return the first group item in rotation direction if (allInGroup.contains(neighbour)) { - //Since we rotate clockwise we know that we hex adjacent to both start and neighbour must be free (otherwise + //Since we rotate clockwise we know that the hex adjacent to both start and neighbour must be free (otherwise //that one would have been returned). Hence the next search should start there. return new Position(neighbour, i - 1); } @@ -154,12 +154,12 @@ private static Position getNext(@NonNull Position startPosition, Set allInG i = -1; //continue at zero in next cycle repeats++; } else { - throw new RuntimeException("Could not pick non-empty neighbor"); + throw new IllegalStateException("Could not pick non-empty neighbor"); } } } - throw new RuntimeException("getNext starting at " + start + " could not find neighbour to follow " + neighbours); + throw new IllegalStateException("getNext starting at " + start + " could not find neighbour to follow " + neighbours); } static class Position { diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGHex.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGHex.java index d41e77d50..73f2c5315 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGHex.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGHex.java @@ -2,6 +2,7 @@ import de.bonndan.nivio.output.map.hex.Hex; import j2html.tags.DomContent; +import org.springframework.lang.NonNull; import org.springframework.util.StringUtils; import java.util.stream.Collectors; @@ -17,19 +18,24 @@ public class SVGHex extends Component { private boolean debug = false; - public SVGHex(Hex hex, String fillId, String stroke) { + public SVGHex(@NonNull final Hex hex, String fillId, String stroke) { this.hex = hex; this.fillId = fillId; this.stroke = stroke; } + public SVGHex(@NonNull final Hex hex, String fillId, String stroke, boolean debug) { + this(hex, fillId, stroke); + this.debug = debug; + } + public DomContent render() { return SvgTagCreator.polygon() .attr("stroke-width", 1) .attr("points", asPoints(hex)) - .condAttr(!StringUtils.isEmpty(stroke), "stroke", stroke) - .condAttr(!StringUtils.isEmpty(fillId), "fill", fillId) - .condAttr(!StringUtils.isEmpty(fillId), "fill-opacity", String.valueOf(0.4)) + .condAttr(StringUtils.hasLength(stroke), "stroke", stroke) + .condAttr(StringUtils.hasLength(fillId), "fill", fillId) + .condAttr(StringUtils.hasLength(fillId), "fill-opacity", String.valueOf(0.4)) .condAttr(debug, "data-hex-coords", hex.q + "," + hex.r) ; } diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGItem.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGItem.java index 1f2888c85..bec38f95c 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGItem.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGItem.java @@ -64,7 +64,7 @@ class SVGItem extends Component { public DomContent render() { boolean hasText = false; - boolean hasFill = !StringUtils.isEmpty(layoutedComponent.getFill()); + boolean hasFill = StringUtils.hasLength(layoutedComponent.getFill()); var fillId = hasFill ? "url(#" + SVGPattern.idForLink(layoutedComponent.getFill()) + ")" : "white"; DomContent content = null; Item item = (Item) layoutedComponent.getComponent(); @@ -73,7 +73,7 @@ public DomContent render() { * use the shortname as text instead, if it is shorter than 3 chars (utf8: one "symbol"), font size is increased */ String shortName = item.getLabel(Label.shortname); - if (!hasFill && StringUtils.isEmpty(item.getType()) && !StringUtils.isEmpty(shortName)) { + if (!hasFill && !StringUtils.hasLength(item.getType()) && StringUtils.hasLength(shortName)) { String className = shortName.length() < 3 ? "itemShortnameIcon" : "itemShortname"; content = new SVGLabelText(shortName, "0", "3", className).render() .attr("text-anchor", "middle"); @@ -82,7 +82,7 @@ public DomContent render() { } DomContent icon = null; - if (!hasFill && !hasText && !StringUtils.isEmpty(layoutedComponent.getIcon())) { + if (!hasFill && !hasText && StringUtils.hasLength(layoutedComponent.getIcon())) { final int size = DEFAULT_ICON_SIZE * 3; final int trans = Math.round(size / 2f); icon = SvgTagCreator.image() @@ -96,14 +96,14 @@ public DomContent render() { String stroke = "#" + (layoutedComponent.getColor() != null ? layoutedComponent.getColor() : Color.GRAY); ContainerTag statusCircle = null; if (itemStatuses != null) { - StatusValue worst = Assessable.getWorst(itemStatuses); - if (worst.getStatus() != Status.UNKNOWN) { + Status worst = Assessable.getWorst(itemStatuses).stream().findFirst().map(StatusValue::getStatus).orElse(Status.UNKNOWN); + if (worst != Status.UNKNOWN) { statusCircle = SvgTagCreator.circle() .attr("cx", 70) .attr("cy", 70) .attr("r", DEFAULT_ICON_SIZE / 2) .attr("stroke", "grey") - .attr("fill", worst.getStatus().getName()) + .attr("fill", worst.getName()) ; } } @@ -113,7 +113,7 @@ public DomContent render() { .attr("cx", 0) .attr("cy", 0) .attr("r", DEFAULT_ICON_SIZE * 2) - .condAttr(!StringUtils.isEmpty(fillId), "fill", fillId) + .condAttr(StringUtils.hasLength(fillId), "fill", fillId) .attr("stroke", stroke) .attr("data-x", String.format(Locale.ENGLISH, "%.2f", pixel.x)) .attr("data-y", String.format(Locale.ENGLISH, "%.2f", pixel.y)); diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGItemLabel.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGItemLabel.java index 89dbcbf5e..4afb76d30 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGItemLabel.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGItemLabel.java @@ -18,7 +18,7 @@ class SVGItemLabel extends Component { private final String identifier; SVGItemLabel(Item item) { - name = StringUtils.isEmpty(item.getName()) ? item.getIdentifier() : item.getName(); + name = !StringUtils.hasLength(item.getName()) ? item.getIdentifier() : item.getName(); id = getId(item); identifier = item.getFullyQualifiedIdentifier().jsonValue(); } diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java index e9346bc97..7d4fe179e 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRelation.java @@ -2,20 +2,24 @@ import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.assessment.StatusValue; +import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Lifecycle; import de.bonndan.nivio.model.Relation; import de.bonndan.nivio.model.RelationType; import j2html.tags.ContainerTag; import j2html.tags.DomContent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; -import java.awt.geom.Point2D; import java.util.Optional; +import static de.bonndan.nivio.output.map.hex.Hex.SOUTH; import static de.bonndan.nivio.output.map.svg.SVGDocument.DATA_IDENTIFIER; import static de.bonndan.nivio.output.map.svg.SVGDocument.VISUAL_FOCUS_UNSELECTED; +import static de.bonndan.nivio.output.map.svg.SVGRenderer.DEFAULT_ICON_SIZE; import static de.bonndan.nivio.output.map.svg.SvgTagCreator.g; /** @@ -23,7 +27,10 @@ */ class SVGRelation extends Component { + private static final Logger LOGGER = LoggerFactory.getLogger(SVGRelation.class); + public static final String MARKER_ID = "arrow"; + public static final int BASIC_STROKE_WIDTH = 20; private final HexPath hexPath; private final String fill; @@ -44,8 +51,8 @@ class SVGRelation extends Component { @Nullable final StatusValue statusValue ) { this.hexPath = hexPath; - if (StringUtils.isEmpty(fill)) { - throw new RuntimeException("Fill color cannot be empty."); + if (!StringUtils.hasLength(fill)) { + throw new IllegalArgumentException("Fill color cannot be empty."); } this.fill = fill; this.relation = relation; @@ -64,13 +71,25 @@ public DomContent render() { ContainerTag shadow = null; - int innerStrokeWidth = 20; + float factor = Optional.ofNullable(relation.getLabel(Label.weight)).map(s -> { + try { + float v = Float.parseFloat(s); + if (v > 5f) { + v = 5; + } + return v; + } catch (NumberFormatException e) { + LOGGER.warn("Invalid weight: {}", s); + return 1f; + } + }).orElse(1f); + int innerStrokeWidth = Math.round(5 * factor); if (statusValue != null && !statusValue.getStatus().equals(Status.UNKNOWN)) { String statusColor = statusValue.getStatus().getName(); shadow = SvgTagCreator.path() .attr("d", points) .attr("stroke", statusColor) - .attr("stroke-width", 24); + .attr("stroke-width", Math.round(BASIC_STROKE_WIDTH * factor)); } ContainerTag path = SvgTagCreator.path() @@ -82,20 +101,16 @@ public DomContent render() { path.attr("opacity", "0.5"); } - ContainerTag endMarker = null; if (RelationType.DATAFLOW.equals(relation.getType())) { - //path.attr("marker-mid", String.format("url(#%s)", SVGRelation.MARKER_ID)); path.attr("fill", fillId); path.attr("stroke-dasharray", 15); - } else { - endMarker = SvgTagCreator.circle() - .attr("cx", hexPath.getEndPoint().x) - .attr("cy", hexPath.getEndPoint().y) - .attr("r", 35) - .attr("fill", fillId); } - return addAttributes(g(shadow, endMarker, path, label(bezierPath, fillId)), relation); + var lastDirection =hexPath.getDirections().isEmpty() ? SOUTH : hexPath.getDirections().get(hexPath.getDirections().size()-1); + SvgRelationEndMarker marker = new SvgRelationEndMarker(hexPath.getEndPoint(), relation.getType(), fillId, lastDirection); + ContainerTag endMarker = marker.render(); + + return addAttributes(g(shadow, path, endMarker, label(relation.getLabel(Label.label), bezierPath, fillId)), relation); } public HexPath getHexPath() { @@ -103,7 +118,7 @@ public HexPath getHexPath() { } private ContainerTag addAttributes(ContainerTag g, Relation relation) { - String type = !StringUtils.isEmpty(relation.getType()) ? relation.getType().name() : "-"; + String type = relation.getType() != null ? relation.getType().name() : "-"; g.attr("data-type", type) .attr("data-source", relation.getSource().getFullyQualifiedIdentifier().jsonValue()) .attr("data-target", relation.getTarget().getFullyQualifiedIdentifier().jsonValue()) @@ -113,33 +128,12 @@ private ContainerTag addAttributes(ContainerTag g, Relation relation) { return g; } - private ContainerTag label(BezierPath bezierPath, String fillId) { - Point2D.Float point = bezierPath.eval(0.49f); - Point2D.Float point2 = bezierPath.eval(0.51f); - return alongPath(getText(), point, point2, fillId, 0, true); - } - - private String getText() { - return Optional.ofNullable(relation.getFormat()).orElse(""); - } - - private ContainerTag alongPath(String text, Point2D.Float point, Point2D.Float point2, String fillId, int xOffset, boolean upright) { - - var degrees = Math.atan2((point2.y - point.y), (point2.x - point.x)) * 180 / Math.PI; - if (upright && (degrees > 90 || degrees < -90)) { - degrees += 180; //always upright - } - String transform = "translate(" + round(point.getX()) + ' ' + round(point.getY() - 10) + ") rotate(" + round(degrees) + " 0 0)"; - - if (text == null) { - text = ""; + @Nullable + private ContainerTag label(String text, BezierPath bezierPath, String fillId) { + if (!StringUtils.hasLength(text)) { + return null; } - return SvgTagCreator.text(text) - .attr("x", xOffset) - .attr("y", 0) - .attr("font-size", "4em") - .condAttr(!StringUtils.isEmpty(fillId), "fill", fillId) - .attr("transform", transform); + return new SvgRelationLabel(text, bezierPath.eval(0.49f), bezierPath.eval(0.51f), fillId, true).render(); } /** @@ -149,13 +143,13 @@ private ContainerTag alongPath(String text, Point2D.Float point, Point2D.Float p */ public static ContainerTag dataflowMarker() { ContainerTag path = SvgTagCreator.path().attr("d", "M 0 0 L 10 5 L 0 10 z") - .attr("fill", "#ffffff"); + .attr("fill", "grey"); return SvgTagCreator.marker() .attr("id", MARKER_ID) - .attr("markerWidth", 10) - .attr("markerHeight", 10) - .attr("refX", 0) + .attr("markerWidth", DEFAULT_ICON_SIZE) + .attr("markerHeight", DEFAULT_ICON_SIZE) + .attr("refX", 14) .attr("refY", 5) .attr("orient", "auto") .attr("viewBox", "0 0 10 10") diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRenderer.java b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRenderer.java index cb5a64539..4f921c39d 100644 --- a/src/main/java/de/bonndan/nivio/output/map/svg/SVGRenderer.java +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SVGRenderer.java @@ -20,11 +20,12 @@ * Turns the layouted landscape into a SVG image. */ @Service -public class SVGRenderer implements Renderer { +public class SVGRenderer implements Renderer { private static final Logger LOGGER = LoggerFactory.getLogger(SVGRenderer.class); public static final int DEFAULT_ICON_SIZE = 50; + public static final String RENDERING_TYPE = "svg"; private final MapStyleSheetFactory mapStyleSheetFactory; @@ -33,21 +34,29 @@ public SVGRenderer(MapStyleSheetFactory mapStyleSheetFactory) { } @Override - public SVGDocument render(@NonNull final LayoutedComponent landscape, @Nullable final Assessment assessment, boolean debug) { + public String render(@NonNull final LayoutedComponent landscape, @Nullable final Assessment assessment, boolean debug) { SVGDocument svgDocument = new SVGDocument(landscape, assessment, getStyles((Landscape) landscape.getComponent())); svgDocument.setDebug(debug); - return svgDocument; + return svgDocument.getXML(); } @Override - public void render(@NonNull final LayoutedComponent landscape, @NonNull final Assessment assessment, @NonNull final File file, boolean debug) { + public void render(@NonNull final LayoutedComponent landscape, + @NonNull final Assessment assessment, + @NonNull final File file, boolean debug + ) { try (FileWriter fileWriter = new FileWriter(file)) { - fileWriter.write(render(landscape, assessment, debug).getXML()); + fileWriter.write(render(landscape, assessment, debug)); } catch (IOException e) { LOGGER.error("Failed to render to file", e); } } + @Override + public String getRenderingType() { + return RENDERING_TYPE; + } + private String getStyles(Landscape landscape) { String css = ""; try (InputStream resourceAsStream = getClass().getResourceAsStream("/static/css/svg.css")) { diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SvgRelationEndMarker.java b/src/main/java/de/bonndan/nivio/output/map/svg/SvgRelationEndMarker.java new file mode 100644 index 000000000..620cabb5a --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SvgRelationEndMarker.java @@ -0,0 +1,104 @@ +package de.bonndan.nivio.output.map.svg; + +import de.bonndan.nivio.model.RelationType; +import de.bonndan.nivio.output.map.hex.Hex; +import j2html.tags.ContainerTag; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; + +import java.awt.geom.Point2D; +import java.util.Objects; + +import static de.bonndan.nivio.output.map.hex.Hex.*; + +/** + * Renders an {@link SVGRelation} end marker. + */ +class SvgRelationEndMarker { + + private static final String MARKER_POINTS = "25,5 48,50 5,50"; + private static final int HALF_MARKER_SIZE = 25; + + private final Point2D.Double endPoint; + private final RelationType type; + private final String fillId; + private final int lastDirection; + + /** + * @param endPoint end point of the path + * @param type relation type + * @param fillColor color + * @param lastDirection direction of the last path tile to determine rotation angle + */ + SvgRelationEndMarker(@NonNull final Point2D.Double endPoint, + @Nullable final RelationType type, + @Nullable final String fillColor, + int lastDirection + ) { + this.endPoint = Objects.requireNonNull(endPoint); + this.type = type; + this.fillId = fillColor; + this.lastDirection = lastDirection; + } + + ContainerTag render() { + if (RelationType.DATAFLOW.equals(type)) { + + var hexDirCorrection = lastDirection - Hex.NORTH; + var degree = hexDirCorrection * 60; + var offset = offset(lastDirection); + double tx = endPoint.x - HALF_MARKER_SIZE + offset.x; + double ty = endPoint.y - HALF_MARKER_SIZE + offset.y; + return SvgTagCreator.polygon() + .attr("transform", String.format("translate(%s %s) rotate(%d 25 25)", tx, ty, degree)) + .attr("points", MARKER_POINTS) + .attr("fill", fillId); + } else { + return SvgTagCreator.circle() + .attr("cx", endPoint.x) + .attr("cy", endPoint.y) + .attr("r", 35) + .attr("fill", fillId); + } + } + + /** + * @param degree rotation degree + * @return the point of the tip + */ + private Point2D.Double offset(int degree) { + + switch (lastDirection) { + + case SOUTH: + degree = 0; + break; + + case SOUTH_WEST: + degree = 60; + break; + + case NORTH_WEST: + degree = 120; + break; + + case NORTH: + degree = 180; + break; + case NORTH_EAST: + degree = 240; + break; + + case SOUTH_EAST: + degree = 300; + break; + } + + var radius = HALF_MARKER_SIZE; + var t = Math.toRadians(degree); + int x = (int) Math.round(Math.sin(t) * radius); + int y = (int) Math.round(Math.cos(t) * radius); + + return new Point2D.Double(x, -y); + } +} diff --git a/src/main/java/de/bonndan/nivio/output/map/svg/SvgRelationLabel.java b/src/main/java/de/bonndan/nivio/output/map/svg/SvgRelationLabel.java new file mode 100644 index 000000000..c324cec0e --- /dev/null +++ b/src/main/java/de/bonndan/nivio/output/map/svg/SvgRelationLabel.java @@ -0,0 +1,54 @@ +package de.bonndan.nivio.output.map.svg; + +import j2html.tags.ContainerTag; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; + +import java.awt.geom.Point2D; +import java.util.Objects; + +public class SvgRelationLabel extends Component { + + private final String transform; + private final String text; + private final String fillId; + + /** + * Creates a new label object. + * + * @param text the text to display + * @param point first point + * @param point2 second point (diffed to first to determine angle) + * @param fillId color + * @param upright flag to enforce text upright + */ + public SvgRelationLabel(@NonNull final String text, + @NonNull final Point2D.Float point, + @NonNull final Point2D.Float point2, + @Nullable final String fillId, + final boolean upright + ) { + this.text = Objects.requireNonNull(text, "Label text is empty"); + Objects.requireNonNull(point, "First point is null"); + Objects.requireNonNull(point2, "Second point is null"); + + this.fillId = fillId; + + var degrees = Math.atan2((point2.y - point.y), (point2.x - point.x)) * 180 / Math.PI; + if (upright && (degrees > 90 || degrees < -90)) { + degrees += 180; //always upright + } + transform = "translate(" + round(point.getX()) + ' ' + round(point.getY() - 10) + ") rotate(" + round(degrees) + " 0 0)"; + } + + public ContainerTag render() { + return SvgTagCreator.text(text) + .attr("x", 0) + .attr("y", 0) + .attr("text-anchor", "middle") + .attr("font-size", "1.5em") + .condAttr(StringUtils.hasLength(fillId), "fill", fillId) + .attr("transform", transform); + } +} diff --git a/src/main/java/de/bonndan/nivio/search/ItemIndex.java b/src/main/java/de/bonndan/nivio/search/ItemIndex.java index a4fc80bb2..b4f8d628b 100644 --- a/src/main/java/de/bonndan/nivio/search/ItemIndex.java +++ b/src/main/java/de/bonndan/nivio/search/ItemIndex.java @@ -9,11 +9,10 @@ import com.googlecode.cqengine.query.parser.sql.SQLParser; import com.googlecode.cqengine.resultset.ResultSet; import de.bonndan.nivio.input.dto.ItemDescription; +import de.bonndan.nivio.model.Component; import de.bonndan.nivio.model.FullyQualifiedIdentifier; import de.bonndan.nivio.model.ItemComponent; import de.bonndan.nivio.util.URLHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.StringUtils; @@ -35,7 +34,6 @@ */ public class ItemIndex { - private static final Logger LOGGER = LoggerFactory.getLogger(ItemIndex.class); public static final String CQE_FIELD_FQI = "fqi"; /** @@ -183,12 +181,12 @@ public T pick(final ItemDescription itemDescription) { */ @NonNull public T pick(final String identifier, String group) { - if (StringUtils.isEmpty(identifier)) { + if (!StringUtils.hasLength(identifier)) { throw new IllegalArgumentException("Identifier to pick is empty"); } return find(identifier, group).orElseThrow(() -> - new RuntimeException(String.format("Element '%s' not found in collection %s.", identifier , all())) + new NoSuchElementException(String.format("Element '%s' not found in collection %s.", identifier , all())) ); } @@ -199,14 +197,14 @@ public T pick(final String identifier, String group) { * @return the item or null */ public Optional find(String identifier, String group) { - if (StringUtils.isEmpty(identifier)) { + if (!StringUtils.hasLength(identifier)) { throw new IllegalArgumentException("Identifier to find is empty"); } List found = findAll(identifier, group); if (found.size() > 1) { - throw new RuntimeException("Ambiguous result for " + group + "/" + identifier + ": " + found + " in collection "); + throw new SearchException(String.format("Ambiguous result for %s/%s: %s in collection ", group, identifier, found)); } return Optional.ofNullable((found.size() == 1) ? found.get(0) : null); @@ -222,7 +220,7 @@ public Optional find(ItemMatcher itemMatcher) { List found = findAll(itemMatcher); if (found.size() > 1) { - throw new RuntimeException("Ambiguous result for " + itemMatcher + ": " + found + " in collection."); + throw new SearchException(String.format("Ambiguous result for %s: %s in collection.", itemMatcher, found)); } return Optional.ofNullable((found.size() == 1) ? found.get(0) : null); @@ -233,7 +231,7 @@ public List cqnQueryOnIndex(String condition) { ResultSet results = parser.retrieve(index, condition); return results.stream().collect(Collectors.toList()); } catch (InvalidQueryException e) { - throw new RuntimeException(String.format("Failed to run query '%s'", condition), e); + throw new SearchException(String.format("Failed to run query '%s'", condition), e); } } @@ -308,10 +306,20 @@ public void remove(T item) { * Retrieves all Items corresponding the set of FQIs. * * @param fullyQualifiedIdentifiers a set of fqis - * @return a set of components (e.g. items) + * @return a set of components (e.g. items) in the same order as the given FQIs */ public Set retrieve(@NonNull Set fullyQualifiedIdentifiers) { Query nativeQuery = in(CQE_ATTR_FQI, fullyQualifiedIdentifiers); - return index.retrieve(nativeQuery).stream().collect(Collectors.toUnmodifiableSet()); + Map collect = index.retrieve(nativeQuery).stream().collect(Collectors.toMap(Component::getFullyQualifiedIdentifier, o -> o)); + LinkedHashSet result = new LinkedHashSet<>(); + fullyQualifiedIdentifiers.forEach(fqi -> result.add( + Optional.ofNullable(collect.get(fqi)) + .orElseThrow(() -> new NoSuchElementException(String.format("Could not retrieve item with fqi %s: Mismatching state of item index?", fqi))) + )); + return result; + } + + public T pick(FullyQualifiedIdentifier fqi) { + return pick(fqi.getItem(), fqi.getGroup()); } } diff --git a/src/main/java/de/bonndan/nivio/search/ItemMatcher.java b/src/main/java/de/bonndan/nivio/search/ItemMatcher.java index d578c0444..c25607ee6 100644 --- a/src/main/java/de/bonndan/nivio/search/ItemMatcher.java +++ b/src/main/java/de/bonndan/nivio/search/ItemMatcher.java @@ -39,9 +39,9 @@ public static ItemMatcher build( ItemMatcher fqi = new ItemMatcher(); fqi.landscape = StringUtils.trimAllWhitespace(landscapeIdentifier == null ? "" : landscapeIdentifier.toLowerCase()); - if (!StringUtils.isEmpty(groupIdentifier)) + if (StringUtils.hasLength(groupIdentifier)) fqi.group = StringUtils.trimAllWhitespace(groupIdentifier.toLowerCase()); - if (!StringUtils.isEmpty(itemIdentifier)) + if (StringUtils.hasLength(itemIdentifier)) fqi.item = StringUtils.trimAllWhitespace(itemIdentifier.toLowerCase()); return fqi; @@ -65,7 +65,7 @@ public static Optional forTarget(String string) { } if (URLHelper.getURL(string).isPresent()) { - LOGGER.debug(String.format("ItemMatcher does not work with URLs: %s", string)); + LOGGER.debug("ItemMatcher does not work with URLs: {}", string); return Optional.empty(); } diff --git a/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java b/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java index 8360fd260..c20fa2486 100644 --- a/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java +++ b/src/main/java/de/bonndan/nivio/search/SearchDocumentFactory.java @@ -24,9 +24,16 @@ public class SearchDocumentFactory { private static final Logger LOGGER = LoggerFactory.getLogger(SearchDocumentFactory.class); + private SearchDocumentFactory() {} + public static final String LUCENE_FIELD_IDENTIFIER = "identifier"; public static final String LUCENE_FIELD_NAME = "name"; public static final String LUCENE_FIELD_DESCRIPTION = "description"; + + /** + * This is used to collect strings which should be directly searchable + */ + public static final String LUCENE_FIELD_GENERIC = "generic"; public static final String LUCENE_FIELD_CONTACT = "contact"; public static final String LUCENE_FIELD_FQI = "fqi"; public static final String LUCENE_FIELD_COMPONENT_TYPE = "component"; @@ -64,7 +71,6 @@ public static Document from(@NonNull final Item item, @Nullable List addTextField = (field, value) -> Optional.ofNullable(value) .ifPresentOrElse( val -> document.add(new TextField(field, val, Field.Store.YES)), @@ -81,24 +87,32 @@ public static Document from(@NonNull final Item item, @Nullable List genericStrings = new ArrayList<>(); //add all labels by their key item.getLabels().forEach((labelKey, val) -> { - if (StringUtils.isEmpty(val)) + if (!StringUtils.hasLength(val)) return; addTextField.accept(labelKey, val); + + //add non-prefixed label values to generic field + if (!labelKey.contains(Label.DELIMITER)) { + genericStrings.add(val); + } }); //add links, title as key (duplicates are ok) item.getLinks().forEach((s, link) -> { if (link == null) return; - String val = StringUtils.isEmpty(link.getName()) ? "" : link.getName() + " "; + String val = !StringUtils.hasLength(link.getName()) ? "" : link.getName() + " "; val += link.getHref(); addTextField.accept(s, val); }); //tags (searchable) - Arrays.stream(item.getTags()).forEach(tag -> addTextField.accept(LUCENE_FIELD_TAG, tag.toLowerCase(Locale.ROOT))); + Arrays.stream(item.getTags()) + .map(tag -> tag.toLowerCase(Locale.ROOT)) + .forEach(tag -> addTextField.accept(LUCENE_FIELD_TAG, tag)); //networks item.getLabels(Label.network).forEach((key, value) -> addTextField.accept(LUCENE_FIELD_NETWORK, value.toLowerCase(Locale.ROOT))); @@ -110,17 +124,18 @@ public static Document from(@NonNull final Item item, @Nullable List addTextField.accept(LUCENE_FIELD_FRAMEWORK, s)); - //kpis, fields are prefixed to prevent name collisions (kpis can have any names) statusValues.forEach(statusValue -> { - final String field = statusValue.getField().startsWith(StatusValue.SUMMARY_LABEL) ? - StatusValue.SUMMARY_LABEL : statusValue.getField(); - addTextField.accept(KPI_FACET_PREFIX + field, statusValue.getStatus().getName()); + addTextField.accept(KPI_FACET_PREFIX + statusValue.getField(), statusValue.getStatus().getName()); }); + //frameworks name (label keys) + addTextField.accept(LUCENE_FIELD_GENERIC, StringUtils.collectionToDelimitedString(genericStrings, " ")); + addFacets(document, item, statusValues); return document; } @@ -162,9 +177,7 @@ private static void addFacets(final Document document, final Item item, List { - final String field = statusValue.getField().startsWith(StatusValue.SUMMARY_LABEL) ? - StatusValue.SUMMARY_LABEL : statusValue.getField(); - addFacetField.accept(KPI_FACET_PREFIX + field, statusValue.getStatus().getName()); + addFacetField.accept(KPI_FACET_PREFIX + statusValue.getField(), statusValue.getStatus().getName()); }); } -} +} \ No newline at end of file diff --git a/src/main/java/de/bonndan/nivio/search/SearchEngineException.java b/src/main/java/de/bonndan/nivio/search/SearchEngineException.java new file mode 100644 index 000000000..31ce9b3b6 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/search/SearchEngineException.java @@ -0,0 +1,13 @@ +package de.bonndan.nivio.search; + +import java.io.IOException; + +public class SearchEngineException extends RuntimeException { + public SearchEngineException(String message, IOException e) { + super(message, e); + } + + public SearchEngineException(String message) { + super(message); + } +} diff --git a/src/main/java/de/bonndan/nivio/search/SearchException.java b/src/main/java/de/bonndan/nivio/search/SearchException.java new file mode 100644 index 000000000..564e7b965 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/search/SearchException.java @@ -0,0 +1,12 @@ +package de.bonndan.nivio.search; + + +public class SearchException extends RuntimeException { + public SearchException(String message) { + super(message); + } + + public SearchException(String message, Throwable e) { + super(message, e); + } +} diff --git a/src/main/java/de/bonndan/nivio/search/SearchIndex.java b/src/main/java/de/bonndan/nivio/search/SearchIndex.java index a61399632..1489e239b 100644 --- a/src/main/java/de/bonndan/nivio/search/SearchIndex.java +++ b/src/main/java/de/bonndan/nivio/search/SearchIndex.java @@ -50,9 +50,15 @@ public class SearchIndex { public static final String WILDCARD = "*"; public static final String WHITESPACE = " "; public static final String FACET_DELIMITER = ":"; + private static final String[] MULTI_FIELD_QUERY_FIELDS = { + LUCENE_FIELD_IDENTIFIER, + LUCENE_FIELD_NAME, + LUCENE_FIELD_DESCRIPTION, + LUCENE_FIELD_GENERIC, + }; - private final Directory searchIndex; - private final Directory taxoIndex; + private final Directory searchIndexDir; + private final Directory taxoIndexDir; /** * Creates a new empty index. @@ -63,8 +69,8 @@ public SearchIndex(@NonNull final String identifier) { try { var tmpdir = System.getProperty("java.io.tmpdir"); var fsSafeIdentifier = StringUtils.trimTrailingCharacter(identifier.replaceAll("[^0-9a-fA-F]", "_"), File.separatorChar); - searchIndex = new MMapDirectory(Path.of(tmpdir, "nivio-document-index", fsSafeIdentifier)); - taxoIndex = new MMapDirectory(Path.of(tmpdir, "nivio-facet-index", fsSafeIdentifier)); + searchIndexDir = new MMapDirectory(Path.of(tmpdir, "nivio-document-index", fsSafeIdentifier)); + taxoIndexDir = new MMapDirectory(Path.of(tmpdir, "nivio-facet-index", fsSafeIdentifier)); } catch (IOException e) { LOGGER.error(String.format("Failed to create search index: %s", e.getMessage())); throw new SearchIndexCreationException("Failed to create search index.", e); @@ -85,18 +91,18 @@ public void indexForSearch(@NonNull final Landscape landscape, @NonNull final As /** * Creates a search index based in a snapshot of current items state (later modifications won't be shown). */ - private void indexItems(Set items, Map> results) { + private void indexItems(Set items, Map> assessments) { try { FacetsConfig config = SearchDocumentFactory.getConfig(); - TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoIndex, IndexWriterConfig.OpenMode.CREATE); - IndexWriter writer = new IndexWriter(searchIndex, new IndexWriterConfig(new StandardAnalyzer())); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoIndexDir, IndexWriterConfig.OpenMode.CREATE); + IndexWriter writer = new IndexWriter(searchIndexDir, new IndexWriterConfig(new StandardAnalyzer())); writer.deleteAll(); for (Item item : items) { - writer.addDocument(config.build(taxoWriter, from(item, results.get(item.getFullyQualifiedIdentifier())))); + writer.addDocument(config.build(taxoWriter, from(item, assessments.get(item.getFullyQualifiedIdentifier().toString())))); } IOUtils.close(writer, taxoWriter); } catch (IOException e) { - throw new RuntimeException("Failed to update search index", e); + throw new SearchEngineException("Failed to update search index", e); } } @@ -115,7 +121,7 @@ public Set search(@NonNull final String queryString) { .map(doc -> FullyQualifiedIdentifier.from(doc.get(LUCENE_FIELD_FQI))) .collect(Collectors.toSet()); } catch (IOException | ParseException e) { - throw new RuntimeException(String.format("Failed to execute search for '%s'", queryString)); + throw new SearchEngineException(String.format("Failed to execute search for '%s'", queryString)); } } @@ -125,7 +131,7 @@ public Set search(@NonNull final String queryString) { private String rewriteQuery(final String query) { return Arrays.stream(query.split(WHITESPACE)) .map(s -> { - if (StringUtils.isEmpty(s) || "or".equalsIgnoreCase(s) || "and".equalsIgnoreCase(s)) { + if (!StringUtils.hasLength(s) || "or".equalsIgnoreCase(s) || "and".equalsIgnoreCase(s)) { return s; } if (s.endsWith(FACET_DELIMITER)) { @@ -146,10 +152,10 @@ private String rewriteQuery(final String query) { */ public List facets() { try { - DirectoryReader ireader = DirectoryReader.open(searchIndex); + DirectoryReader ireader = DirectoryReader.open(searchIndexDir); IndexSearcher searcher = new IndexSearcher(ireader); - DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoIndex); + DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoIndexDir); FacetsCollector fc = new FacetsCollector(); FacetsConfig config = getConfig(); FacetsCollector.search(searcher, new MatchAllDocsQuery(), 10, fc); @@ -161,15 +167,15 @@ public List facets() { LOGGER.warn("Unable to get the facets for the given query error: ", e); } - return null; + return Collections.emptyList(); } private List documentSearch(String queryString) throws IOException, ParseException { - DirectoryReader ireader = DirectoryReader.open(searchIndex); + DirectoryReader ireader = DirectoryReader.open(searchIndexDir); IndexSearcher isearcher = new IndexSearcher(ireader); // Parse a simple query that searches for "text": - QueryParser parser = new MultiFieldQueryParser(new String[]{LUCENE_FIELD_IDENTIFIER, LUCENE_FIELD_NAME, LUCENE_FIELD_DESCRIPTION}, new StandardAnalyzer()); + QueryParser parser = new MultiFieldQueryParser(MULTI_FIELD_QUERY_FIELDS, new StandardAnalyzer()); parser.setAllowLeadingWildcard(true); parser.setSplitOnWhitespace(true); parser.setDefaultOperator(QueryParser.Operator.AND); diff --git a/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java b/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java index a160a1514..06e390042 100644 --- a/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java +++ b/src/main/java/de/bonndan/nivio/search/SearchIndexingEventListener.java @@ -1,7 +1,7 @@ package de.bonndan.nivio.search; -import de.bonndan.nivio.assessment.AssessmentRepository; -import de.bonndan.nivio.input.ProcessingFinishedEvent; +import de.bonndan.nivio.assessment.Assessment; +import de.bonndan.nivio.assessment.AssessmentChangedEvent; import de.bonndan.nivio.model.Landscape; import org.springframework.context.event.EventListener; import org.springframework.lang.NonNull; @@ -13,18 +13,12 @@ @Component public class SearchIndexingEventListener { - private final AssessmentRepository assessmentRepository; - - public SearchIndexingEventListener(AssessmentRepository assessmentRepository) { - this.assessmentRepository = assessmentRepository; - } - - @EventListener(ProcessingFinishedEvent.class) - public void onProcessingFinishedEvent(@NonNull ProcessingFinishedEvent event) { + @EventListener(AssessmentChangedEvent.class) + public void onProcessingFinishedEvent(@NonNull final AssessmentChangedEvent event) { final Landscape landscape = event.getLandscape(); + final Assessment assessment = event.getAssessment(); final SearchIndex searchIndex = landscape.getSearchIndex(); - //we create a new assessment here, since the landscape has changed - searchIndex.indexForSearch(landscape, assessmentRepository.createAssessment(landscape)); + searchIndex.indexForSearch(landscape, assessment); } } diff --git a/src/main/java/de/bonndan/nivio/util/FrontendMapping.java b/src/main/java/de/bonndan/nivio/util/FrontendMapping.java new file mode 100644 index 000000000..9d933d7d0 --- /dev/null +++ b/src/main/java/de/bonndan/nivio/util/FrontendMapping.java @@ -0,0 +1,35 @@ +package de.bonndan.nivio.util; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.validation.annotation.Validated; + +import java.util.Map; + +@Configuration +@ConfigurationProperties(prefix = "frontendmapping") +@PropertySource(value = "classpath:frontendMapping.yml", factory = YamlPropertySourceFactory.class) +@Validated +public class FrontendMapping { + private Map keys; + + private Map descriptions; + + public Map getKeys() { + return keys; + } + + public Map getDescriptions() { + return descriptions; + } + + public void setKeys(Map keys) { + this.keys = keys; + } + + public void setDescriptions(Map descriptions) { + this.descriptions = descriptions; + } + +} diff --git a/src/main/java/de/bonndan/nivio/util/YamlPropertySourceFactory.java b/src/main/java/de/bonndan/nivio/util/YamlPropertySourceFactory.java new file mode 100644 index 000000000..1f6f7d5ab --- /dev/null +++ b/src/main/java/de/bonndan/nivio/util/YamlPropertySourceFactory.java @@ -0,0 +1,29 @@ +package de.bonndan.nivio.util; + +import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.core.env.PropertiesPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.support.EncodedResource; +import org.springframework.core.io.support.PropertySourceFactory; +import org.springframework.lang.NonNull; + +import java.io.IOException; + +public class YamlPropertySourceFactory implements PropertySourceFactory { + + @Override + @NonNull + public PropertySource createPropertySource(String name, EncodedResource encodedResource) + throws IOException { + YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean(); + factory.setResources(encodedResource.getResource()); + + var properties = factory.getObject(); + var filename = encodedResource.getResource().getFilename(); + if (properties == null || filename == null) { + throw new IOException(); + } + + return new PropertiesPropertySource(filename, properties); + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ff11316a6..d8324ddd2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,6 +15,9 @@ spring: auth: true starttls.enable: true + mustache: + check-template-location: false + logging: level: root: INFO @@ -40,14 +43,44 @@ management: nivio: baseUrl: ${NIVIO_BASE_URL:} - version: #project.version# + version: ^project.version^-^git.commit.id.abbrev^ pollingMilliseconds: 30000 # 30 secs # iconFolder: /a/local/path brandingForeground: ${NIVIO_BRANDING_FOREGROUND:7022F2} brandingBackground: ${NIVIO_BRANDING_BACKGROUND:161618} brandingSecondary: ${NIVIO_BRANDING_SECONDARY:22F2C2} brandingLogoUrl: ${NIVIO_BRANDING_LOGO_URL:} - brandingMessage: ${NIVIO_BRANDING_MESSAGE:Welcome to nivio} + brandingMessage: ${NIVIO_BRANDING_MESSAGE:All Landscapes} + seed: ${SEED:} + demo: ${DEMO:} + + +observerconfig: + scanDelay: + KubernetesObserver: 1 + + +gitlab: # add new environment variables + hostUrl: ${GITLAB_HOST_URL:} + personalAccessToken: ${GITLAB_PERSONAL_ACCESS_TOKEN:} + username: ${GITLAB_USERNAME:} + password: ${GITLAB_PASSWORD:} + + +github: # add new environment variables + login: ${GITHUB_LOGIN:} + password: ${GITHUB_PASSWORD:} + oauth: ${GITHUB_OAUTH:} + jwt: ${GITHUB_JWT:} + +sonar: # add new environment variables + serverUrl: ${SONAR_SERVER_URL:} + login: ${SONAR_LOGIN:} + password: ${SONAR_PASSWORD:} + proxyHost: ${SONAR_PROXY_HOST:} + proxyPort: ${SONAR_PROXY_PORT:} + + --- spring: @@ -58,4 +91,4 @@ spring: profiles: local server: - port: 8080 \ No newline at end of file + port: 8080 diff --git a/src/main/resources/frontendMapping.yml b/src/main/resources/frontendMapping.yml new file mode 100644 index 000000000..661e2d9be --- /dev/null +++ b/src/main/resources/frontendMapping.yml @@ -0,0 +1,6 @@ +frontendmapping: + keys: + shortname: short name + END_OF_LIFE: end of life + descriptions: + END_OF_LIFE: An end-of-life product is a product at the end of the product lifecycle which prevents users from receiving updates, indicating that the product is at the end of its useful life. \ No newline at end of file diff --git a/src/main/resources/iconurls.yml b/src/main/resources/iconurls.yml new file mode 100644 index 000000000..eff1dea15 --- /dev/null +++ b/src/main/resources/iconurls.yml @@ -0,0 +1,8 @@ +iconurls: + urls: + apache/httpd: http://www.apache.org/logos/res/httpd/httpd.png + redhat/keycloak: https://raw.githubusercontent.com/keycloak/keycloak-misc/master/logo/keycloak_icon_256px.png + k8s: https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png + kubernetes: https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png + redis: https://redis.io/images/redis-white.png + prometheus: https://raw.githubusercontent.com/prometheus/docs/master/static/prometheus_logo.png \ No newline at end of file diff --git a/src/main/resources/k8sLabelConfig.json b/src/main/resources/k8sLabelConfig.json new file mode 100644 index 000000000..7990880ee --- /dev/null +++ b/src/main/resources/k8sLabelConfig.json @@ -0,0 +1,8 @@ +{ + "active": true, + "minMatchingLabel": 2, + "level": { + "DeploymentItemAdapter": 1, + "StatefulSetItemAdapter": 0 + } +} \ No newline at end of file diff --git a/src/main/resources/static/css/svg.css b/src/main/resources/static/css/svg.css index aad628f5e..3f4ba8f64 100644 --- a/src/main/resources/static/css/svg.css +++ b/src/main/resources/static/css/svg.css @@ -10,10 +10,6 @@ stroke-width: 0.8em; } -.map g.label { - cursor: pointer; -} - .map g.label { stroke-width: 0.1em; fill: white; @@ -41,28 +37,3 @@ stroke-linecap: butt; stroke-linejoin: round; } - -.map g.relation { - cursor: pointer; -} - -.map g.groupArea { - cursor: pointer; -} - -/* hexagon */ -.map g.groupArea.unselected polygon { - fill-opacity: 0.05 -} - -.map g.item.unselected circle { - stroke: grey; -} - -.map g.relation.unselected path { - stroke: grey; -} - -.map g.relation.unselected circle { - fill: grey; -} \ No newline at end of file diff --git a/src/main/resources/static/icons/meta.json b/src/main/resources/static/icons/meta.json new file mode 100644 index 000000000..621a9a0f9 --- /dev/null +++ b/src/main/resources/static/icons/meta.json @@ -0,0 +1 @@ +[{"id":"CBFA6722-0EE6-49B4-B5C2-0B177A5523C2","name":"ab-testing","codepoint":"F01C9","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Richins","version":"4.0.96"},{"id":"5B09B959-4A49-4674-9035-6CFD3D157C3F","name":"abacus","codepoint":"F16E0","aliases":[],"tags":["Math"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"E20665F3-5354-46C2-9162-4202B20DCA05","name":"abjad-arabic","codepoint":"F1328","aliases":["writing-system-arabic"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"FC508376-0233-498A-ABF8-B289241031FF","name":"abjad-hebrew","codepoint":"F1329","aliases":["writing-system-hebrew"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"E211A028-22EA-4A78-9306-FC8FF8494D02","name":"abugida-devanagari","codepoint":"F132A","aliases":["writing-system-devanagari"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"F782C16A-0558-4347-AB62-3E4A8DD299AD","name":"abugida-thai","codepoint":"F132B","aliases":["writing-system-thai"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"4F013652-22DE-48CF-886B-A0FB995E8B41","name":"access-point","codepoint":"F0003","aliases":["wireless"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"45F0D360-E817-4152-A66E-EF019E10ED47","name":"access-point-check","codepoint":"F1538","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"AAFAB208-B7D5-44A0-915F-761A83D295A3","name":"access-point-minus","codepoint":"F1539","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"06048943-9EE5-4FE2-91D7-7DA162E55203","name":"access-point-network","codepoint":"F0002","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"6DC5A262-63FE-4C77-A66C-B323DF4F82BF","name":"access-point-network-off","codepoint":"F0BE1","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"ED942A44-4B13-47E6-A674-E376C338F671","name":"access-point-off","codepoint":"F1511","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"41E38A13-4B9B-4260-81EA-1DB407986154","name":"access-point-plus","codepoint":"F153A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"2E102C4D-6301-46CA-A3D8-35270CE751C5","name":"access-point-remove","codepoint":"F153B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"E76EC23F-AB71-49B3-9173-841544527A20","name":"account","codepoint":"F0004","aliases":["person","user"],"tags":["Account \/ User","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"3D869F3A-8C3E-4ECB-829E-7785230FA680","name":"account-alert","codepoint":"F0005","aliases":["user-alert","account-warning","user-warning","person-alert","person-warning"],"tags":["Account \/ User","Alert \/ Error"],"author":"Austin Andrews","version":"1.5.54"},{"id":"858CE593-C905-42C6-ABA5-99379EBD95AE","name":"account-alert-outline","codepoint":"F0B50","aliases":["user-alert-outline","account-warning-outline","user-warning-outline","person-warning-outline","person-alert-outline"],"tags":["Account \/ User","Alert \/ Error"],"author":"Coffeemate","version":"3.0.39"},{"id":"34EAE057-F0E4-476A-B988-9BD149263BDF","name":"account-arrow-left","codepoint":"F0B51","aliases":["user-arrow-left","person-arrow-left"],"tags":["Account \/ User"],"author":"Coffeemate","version":"3.0.39"},{"id":"D46BABF7-60F1-41B8-BE5E-5D52367FE58C","name":"account-arrow-left-outline","codepoint":"F0B52","aliases":["user-arrow-left-outline","person-arrow-left-outline"],"tags":["Account \/ User"],"author":"Coffeemate","version":"3.0.39"},{"id":"6C4EDCE5-0741-4BF4-B16A-112892C6AB98","name":"account-arrow-right","codepoint":"F0B53","aliases":["user-arrow-right","person-arrow-right"],"tags":["Account \/ User"],"author":"Coffeemate","version":"3.0.39"},{"id":"7CB2DA6F-D0F6-4A7A-A761-E53B564744E8","name":"account-arrow-right-outline","codepoint":"F0B54","aliases":["user-arrow-right-outline","person-arrow-right-outline"],"tags":["Account \/ User"],"author":"Coffeemate","version":"3.0.39"},{"id":"474D0A31-E56A-4780-9417-DCF8D9A38830","name":"account-box","codepoint":"F0006","aliases":["selfie","user-box","person-box","contact"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"D612088F-9D2A-424A-9403-046993A3EB14","name":"account-box-multiple","codepoint":"F0934","aliases":["switch-account","user-box-multiple","account-boxes","user-boxes","person-box-multiple","person-boxes"],"tags":["Account \/ User"],"author":"Google","version":"2.4.85"},{"id":"31302999-CD15-4F1F-A5D2-374D90F15099","name":"account-box-multiple-outline","codepoint":"F100A","aliases":[],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"537261C5-1AF6-478F-A8BA-4349865D9C1C","name":"account-box-outline","codepoint":"F0007","aliases":["selfie-outline","user-box-outline","portrait","contact-outline","person-box-outline"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"31CE9FF1-9698-4ED6-8E9B-392840E55DDE","name":"account-cancel","codepoint":"F12DF","aliases":["user-cancel","user-block","person-cancel","person-block"],"tags":["Account \/ User"],"author":"Simran","version":"4.8.95"},{"id":"D2CDB839-C734-46EA-A4DE-085CBF29DD0F","name":"account-cancel-outline","codepoint":"F12E0","aliases":["user-cancel-outline","user-block-outline","person-cancel-outline","person-block-outline"],"tags":["Account \/ User"],"author":"Simran","version":"4.8.95"},{"id":"E3270EE8-3F41-481F-9B15-E8925C62A83C","name":"account-cash","codepoint":"F1097","aliases":[],"tags":["Account \/ User","Banking"],"author":"Contributors","version":"4.2.95"},{"id":"582FFF95-D87F-4A58-A3C1-F1A352BF8F56","name":"account-cash-outline","codepoint":"F1098","aliases":[],"tags":["Account \/ User","Banking"],"author":"Contributors","version":"4.2.95"},{"id":"F3C76352-A033-4969-BBC4-99E2BEE84FAE","name":"account-check","codepoint":"F0008","aliases":["user-check","account-tick","user-tick","person-check","person-tick","how-to-reg"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"50F80B8D-C424-4FC1-9A2E-81715787C240","name":"account-check-outline","codepoint":"F0BE2","aliases":["account-tick-outline","user-check-outline","user-tick-outline","person-check-outline","person-tick-outline","how-to-reg-outline"],"tags":["Account \/ User"],"author":"Google","version":"3.2.89"},{"id":"431A5DA2-1B7E-4B86-8EAE-BEE1099048A1","name":"account-child","codepoint":"F0A89","aliases":["user-child","person-child","guardian"],"tags":["Account \/ User"],"author":"Google","version":"2.7.94"},{"id":"AF386BC9-683F-42B4-97DA-C256CF82C79F","name":"account-child-circle","codepoint":"F0A8A","aliases":["user-child-circle","person-child-circle","guardian-circle"],"tags":["Account \/ User"],"author":"Google","version":"2.7.94"},{"id":"B8194820-B46C-41EB-921A-4DD7DDF9BE1F","name":"account-child-outline","codepoint":"F10C8","aliases":[],"tags":["Account \/ User"],"author":"Sascha Wohlgemuth","version":"4.3.95"},{"id":"1D7E8F31-998D-442A-80E6-EBB8DFA8CBA2","name":"account-circle","codepoint":"F0009","aliases":["user-circle","person-circle"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"17CE7627-5016-43F9-B42D-AFAAFA0A0564","name":"account-circle-outline","codepoint":"F0B55","aliases":["user-circle-outline","person-circle-outline"],"tags":["Account \/ User"],"author":"Google","version":"3.0.39"},{"id":"E9851E02-790A-40FD-918A-BB1145051470","name":"account-clock","codepoint":"F0B56","aliases":["user-clock","account-pending","person-clock"],"tags":["Account \/ User","Date \/ Time"],"author":"Coffeemate","version":"3.0.39"},{"id":"AA800DB2-3369-412C-B881-0F99863D13F7","name":"account-clock-outline","codepoint":"F0B57","aliases":["user-clock-outline","account-pending-outline","person-clock-outline"],"tags":["Account \/ User","Date \/ Time"],"author":"Coffeemate","version":"3.0.39"},{"id":"CA7B4B4E-B909-48F5-B93B-7A024D6A9AAA","name":"account-cog","codepoint":"F1370","aliases":["account-settings"],"tags":["Account \/ User","Settings"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"7B40CAE5-6B01-4E2E-8F23-60ECAB9DAC9F","name":"account-cog-outline","codepoint":"F1371","aliases":["account-settings-outline"],"tags":["Account \/ User","Settings"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"A6964E10-1CF0-41FA-BDCA-A77C9C6F30AF","name":"account-convert","codepoint":"F000A","aliases":["user-convert","person-convert"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BED42D20-9EEE-4297-81DC-A72F2F9D935D","name":"account-convert-outline","codepoint":"F1301","aliases":[],"tags":["Account \/ User"],"author":"Simran","version":"4.8.95"},{"id":"18963ABD-E908-4E3C-B8DA-D87916F269F7","name":"account-cowboy-hat","codepoint":"F0E9B","aliases":[],"tags":["Account \/ User"],"author":"Augustin Ursu","version":"3.7.94"},{"id":"3696B7DF-3E12-44EF-B27F-E171AEB5241F","name":"account-details","codepoint":"F0631","aliases":["user-details","person-details"],"tags":["Account \/ User","Settings"],"author":"Google","version":"1.6.50"},{"id":"B9137734-8DC1-41D1-9B34-CEDBB1742A39","name":"account-details-outline","codepoint":"F1372","aliases":["person-details-outline","user-details-outline"],"tags":["Account \/ User","Settings"],"author":"Simran","version":"4.9.95"},{"id":"66271DF7-FF11-4998-9C03-F096CE407E4C","name":"account-edit","codepoint":"F06BC","aliases":["user-edit","person-edit"],"tags":["Account \/ User","Edit \/ Modify"],"author":"Michael Richins","version":"1.8.36"},{"id":"2374A15A-0DC7-458D-A8BD-766E55DFB0AF","name":"account-edit-outline","codepoint":"F0FFB","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.0.96"},{"id":"7B8F1133-B47B-46C0-AAC0-FD87F06B038D","name":"account-group","codepoint":"F0849","aliases":["user-group","users-group","person-group","people-group","accounts-group"],"tags":["Account \/ User"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"7DFB1292-669B-4769-A107-FA3359281270","name":"account-group-outline","codepoint":"F0B58","aliases":["user-group-outline","users-group-outline","person-group-outline","people-group-outline","accounts-group-outline"],"tags":["Account \/ User"],"author":"GreenTurtwig","version":"3.0.39"},{"id":"54665F14-32CD-41E3-B5C5-0E9ABDD3A317","name":"account-hard-hat","codepoint":"F05B5","aliases":["worker","construction"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"1.5.54"},{"id":"15C54239-5327-4962-95CD-721512C6B27F","name":"account-heart","codepoint":"F0899","aliases":["user-heart","person-heart"],"tags":["Account \/ User","Medical \/ Hospital"],"author":"Michael Irigoyen","version":"2.2.43"},{"id":"66013F5C-F7FD-4974-AB80-E624C3E0A5E9","name":"account-heart-outline","codepoint":"F0BE3","aliases":["user-heart-outline","person-heart-outline"],"tags":["Account \/ User","Medical \/ Hospital"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"645E04E6-A328-45DD-9B22-03E2296837B1","name":"account-key","codepoint":"F000B","aliases":["user-key","person-key"],"tags":["Account \/ User"],"author":"REJack","version":"1.5.54"},{"id":"85086B0D-4678-4B8E-9824-308F59F09C0F","name":"account-key-outline","codepoint":"F0BE4","aliases":["user-key-outline","person-key-outline"],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"BD94D7C7-DFDF-419F-862E-FB1AC3263967","name":"account-lock","codepoint":"F115E","aliases":["account-security","account-secure","user-lock","person-lock"],"tags":["Account \/ User","Lock"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"F0E25FF6-2E45-4F3D-B9E3-6F251A6B1651","name":"account-lock-outline","codepoint":"F115F","aliases":["account-security-outline","account-secure-outline","person-lock-outline","user-lock-outline"],"tags":["Account \/ User","Lock"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"9CF96408-1A24-4040-AD04-011183CC9ABC","name":"account-minus","codepoint":"F000D","aliases":["user-minus","person-minus"],"tags":["Account \/ User"],"author":"REJack","version":"1.5.54"},{"id":"C03476FC-2655-4137-862E-28D714E93A50","name":"account-minus-outline","codepoint":"F0AEC","aliases":["user-minus-outline","person-minus-outline"],"tags":["Account \/ User"],"author":"Peter Noble","version":"2.8.94"},{"id":"A8C2EE6C-31B9-4D51-B941-8128FDD77A96","name":"account-multiple","codepoint":"F000E","aliases":["people","user-multiple","group","accounts","users","person-multiple"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"3B3E2DF7-1E21-476A-8473-7F1EAA514D1F","name":"account-multiple-check","codepoint":"F08C5","aliases":["user-multiple-check","account-multiple-tick","accounts-check","accounts-tick","users-check","users-tick","user-multiple-tick","person-multiple-check","person-multiple-tick","people-check","people-tick"],"tags":["Account \/ User"],"author":"Roberto Graham","version":"2.3.50"},{"id":"4391B451-368F-4E41-82C5-63A89A2CDE69","name":"account-multiple-check-outline","codepoint":"F11FE","aliases":["user-multiple-check-outline","account-multiple-tick-outline","accounts-check-outline","accounts-tick-outline","users-check-outline","users-tick-outline","user-multiple-tick-outline","person-multiple-check-outline","person-multiple-tick-outline","people-check-outline","people-tick-outline"],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.6.95"},{"id":"BD31FA9F-EC76-44E9-A9F3-A85F83045D78","name":"account-multiple-minus","codepoint":"F05D3","aliases":["user-multiple-minus","accounts-minus","users-minus","people-minus","person-multiple-minus"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"45C692AD-F1E8-404C-BED2-9FD58F0690CD","name":"account-multiple-minus-outline","codepoint":"F0BE5","aliases":["accounts-minus-outline","people-minus-outline","user-multiple-minus-outline","users-minus-outline","person-multiple-minus-outline"],"tags":["Account \/ User"],"author":"Google","version":"3.2.89"},{"id":"30C6B7FE-4496-4961-B36F-E0FBC4F2696E","name":"account-multiple-outline","codepoint":"F000F","aliases":["user-multiple-outline","people-outline","accounts-outline","users-outline"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"047F8AC1-524D-4077-BCEB-434FE1C50C8B","name":"account-multiple-plus","codepoint":"F0010","aliases":["user-multiple-plus","group-add","accounts-plus","users-plus","person-multiple-plus","people-plus","person-multiple-add","people-add","account-multiple-add","accounts-add","user-multiple-add","users-add","invite"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"AFF0AB6B-616A-4C18-8E28-EE8067224EED","name":"account-multiple-plus-outline","codepoint":"F0800","aliases":["group-add-outline","user-multiple-plus-outline","accounts-plus-outline","users-plus-outline","person-multiple-plus-outline","people-plus-outline","person-multiple-add-outline","people-add-outline","account-multiple-add-outline","accounts-add-outline","user-multiple-add-outline","users-add-outline","invite"],"tags":["Account \/ User"],"author":"Google","version":"2.1.19"},{"id":"998E10E4-B96A-4DB2-9793-3E1C31D42501","name":"account-multiple-remove","codepoint":"F120A","aliases":["user-multiple-remove","person-multiple-remove"],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.6.95"},{"id":"618B092A-7228-4E70-A95C-7EB4EC1BA2FB","name":"account-multiple-remove-outline","codepoint":"F120B","aliases":["user-multiple-remove-outline","person-multiple-remove-outline"],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.6.95"},{"id":"306F2F2C-4B76-40E9-9561-BC3AD271D6BA","name":"account-music","codepoint":"F0803","aliases":["artist"],"tags":["Account \/ User"],"author":"Google","version":"2.1.19"},{"id":"A8CC9CFF-A5DE-4FC8-A4AC-BCE153F767F8","name":"account-music-outline","codepoint":"F0CE9","aliases":["artist-outline"],"tags":["Account \/ User"],"author":"GreenTurtwig","version":"3.3.92"},{"id":"8F49C741-4ED8-4DD3-A22E-310C039EDDA6","name":"account-network","codepoint":"F0011","aliases":["user-network","person-network"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2EEA7799-E0DA-4E9B-880E-B5975A6FC11F","name":"account-network-outline","codepoint":"F0BE6","aliases":["user-network-outline","person-network-outline"],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"2306EFC9-3375-4D03-A631-A32BD72075EC","name":"account-off","codepoint":"F0012","aliases":["user-off","person-off"],"tags":["Account \/ User"],"author":"Simran","version":"1.5.54"},{"id":"231E3EA7-A7EC-41A0-A594-032040488448","name":"account-off-outline","codepoint":"F0BE7","aliases":["user-off-outline","person-off-outline"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"3.2.89"},{"id":"79ECAAC6-71DC-406C-A9B7-57C5F0BAA9E0","name":"account-outline","codepoint":"F0013","aliases":["user-outline","perm-identity","person-outline"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"66556BA4-6B65-4ED9-B813-AD33CA8C2CCF","name":"account-plus","codepoint":"F0014","aliases":["register","user-plus","person-add","account-add","person-plus","user-add","invite"],"tags":["Account \/ User","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"1095C7C6-C264-4415-BD6D-A2078242477E","name":"account-plus-outline","codepoint":"F0801","aliases":["person-add-outline","register-outline","user-plus-outline","account-add-outline","person-plus-outline","user-add-outline","invite"],"tags":["Account \/ User"],"author":"GreenTurtwig","version":"2.1.19"},{"id":"163F4ADF-F6CC-42D0-AEED-DB61351C624C","name":"account-question","codepoint":"F0B59","aliases":["user-help","account-question-mark","account-help","user-question","person-question","person-help"],"tags":["Account \/ User"],"author":"Coffeemate","version":"3.0.39"},{"id":"C5217A29-708E-4340-AE2D-89A33F364A97","name":"account-question-outline","codepoint":"F0B5A","aliases":["account-question-mark-outline","user-help-outline","account-help-outline","user-question-outline","person-question-outline","person-help-outline"],"tags":["Account \/ User"],"author":"Coffeemate","version":"3.0.39"},{"id":"AD1CDB51-AAD9-411A-A81F-8D718A843FDE","name":"account-reactivate","codepoint":"F152B","aliases":[],"tags":["Account \/ User"],"author":"Fran\u00e7ois Risoud","version":"5.4.55"},{"id":"9CB5E1B3-D7AA-4BD2-9966-89CDAC0BF710","name":"account-reactivate-outline","codepoint":"F152C","aliases":[],"tags":["Account \/ User"],"author":"Fran\u00e7ois Risoud","version":"5.4.55"},{"id":"0A1FDBBB-9E1C-480E-BC1D-725778D0851B","name":"account-remove","codepoint":"F0015","aliases":["user-remove","person-remove"],"tags":["Account \/ User"],"author":"REJack","version":"1.5.54"},{"id":"9F89EDE8-E95A-401D-9532-7F0DCD6AE321","name":"account-remove-outline","codepoint":"F0AED","aliases":["user-remove-outline","person-remove-outline"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"2.8.94"},{"id":"48E9C474-C544-4868-9966-C3A8D7808FCA","name":"account-search","codepoint":"F0016","aliases":["user-search","person-search"],"tags":["Account \/ User"],"author":"GreenTurtwig","version":"1.5.54"},{"id":"F6808872-4EB9-43AF-BD74-BDA6861E1862","name":"account-search-outline","codepoint":"F0935","aliases":["user-search-outline","person-search-outline"],"tags":["Account \/ User"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"A975CEEA-FDFD-49A2-A618-E74A3FF87A63","name":"account-settings","codepoint":"F0630","aliases":["user-settings","person-settings"],"tags":["Account \/ User","Settings"],"author":"Austin Andrews","version":"1.6.50"},{"id":"CA95C904-F98B-43D4-A896-DF5E174A0F72","name":"account-settings-outline","codepoint":"F10C9","aliases":[],"tags":["Account \/ User"],"author":"Sascha Wohlgemuth","version":"4.3.95"},{"id":"1E04960E-FFFE-439D-A5FD-C51E7291DA6F","name":"account-star","codepoint":"F0017","aliases":["user-star","person-star"],"tags":["Account \/ User"],"author":"REJack","version":"1.5.54"},{"id":"3B63C1BC-9FB2-4F41-86CF-93D6117585E9","name":"account-star-outline","codepoint":"F0BE8","aliases":["user-star-outline","person-star-outline"],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"DF632613-259D-4C5E-9718-0EB3057290AF","name":"account-supervisor","codepoint":"F0A8B","aliases":["user-supervisor","person-supervisor"],"tags":["Account \/ User"],"author":"Google","version":"2.7.94"},{"id":"741E5459-89DC-4045-B02E-3FB74F636143","name":"account-supervisor-circle","codepoint":"F0A8C","aliases":["user-supervisor-circle","person-supervisor-circle"],"tags":["Account \/ User"],"author":"Google","version":"2.7.94"},{"id":"51B2A4EF-1F20-44EA-BC57-D1B3129C496C","name":"account-supervisor-circle-outline","codepoint":"F14EC","aliases":[],"tags":["Account \/ User"],"author":"Google","version":"5.4.55"},{"id":"B640886A-F3F0-4FE4-AC74-4AE1407E264F","name":"account-supervisor-outline","codepoint":"F112D","aliases":[],"tags":["Account \/ User"],"author":"Sascha Wohlgemuth","version":"4.4.95"},{"id":"FC4F4C4D-83C2-493F-9606-CA80E44BFEF8","name":"account-switch","codepoint":"F0019","aliases":["user-switch","accounts-switch","users-switch","person-switch","people-switch"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"1.5.54"},{"id":"82D545A0-9A8E-4363-A462-883526E48330","name":"account-switch-outline","codepoint":"F04CB","aliases":[],"tags":["Account \/ User"],"author":"Simran","version":"1.5.54"},{"id":"5EF0B9EA-FECB-409C-999C-FE1ECF0C8B01","name":"account-tie","codepoint":"F0CE3","aliases":["person-tie","user-tie"],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"0D809FB8-6A27-4972-B4E5-6A308963FD8B","name":"account-tie-outline","codepoint":"F10CA","aliases":[],"tags":["Account \/ User"],"author":"Sascha Wohlgemuth","version":"4.3.95"},{"id":"7EAF1288-141D-4C8E-91E6-891D04BAE32C","name":"account-tie-voice","codepoint":"F1308","aliases":[],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"F835F775-8FC4-4E85-9B26-7C95F8F45B05","name":"account-tie-voice-off","codepoint":"F130A","aliases":[],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"6CDB4F0E-41EC-409E-A2E0-87785BDAC858","name":"account-tie-voice-off-outline","codepoint":"F130B","aliases":[],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"5712C24C-E8EE-48CD-9E6F-9712AD2BA502","name":"account-tie-voice-outline","codepoint":"F1309","aliases":[],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"F1EEA910-2CD7-448A-A12F-A1BD0FDC6010","name":"account-voice","codepoint":"F05CB","aliases":["record-voice-over","speak","talk","speaking","talking"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"3334E19F-962D-45B4-BE11-F009E1192165","name":"adjust","codepoint":"F001A","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"839928F4-21EA-472B-94A0-C7DFBD6C263A","name":"adobe","codepoint":"F0936","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.4.85"},{"id":"4C7A5C71-F3C9-4BD7-B123-C71BE81CAFB7","name":"adobe-acrobat","codepoint":"F0F9D","aliases":["pdf"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"4.0.96"},{"id":"FACEA69B-49F0-4588-BDEC-693965AD4649","name":"air-conditioner","codepoint":"F001B","aliases":["ac-unit"],"tags":["Home Automation","Automotive"],"author":"Simran","version":"1.5.54"},{"id":"C9AF90F5-7CE7-4251-9BA2-3A614B4882AA","name":"air-filter","codepoint":"F0D43","aliases":["water-filter","filter"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"41485B7B-F175-4627-90EB-640C9C60B27C","name":"air-horn","codepoint":"F0DAC","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"3.5.94"},{"id":"C35492EC-7A43-444E-86A1-B3E960A86950","name":"air-humidifier","codepoint":"F1099","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"9B86205A-73F4-4DB6-9F2C-73654EDF4D52","name":"air-humidifier-off","codepoint":"F1466","aliases":["air-dehumidifier"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"C1621283-2EDC-43C5-9108-812DCAD0BC12","name":"air-purifier","codepoint":"F0D44","aliases":[],"tags":["Home Automation"],"author":"Google","version":"3.4.93"},{"id":"26929F83-C254-41C2-8B0D-B4D95EACAD3E","name":"airbag","codepoint":"F0BE9","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"3E1D81B2-7DF1-4AAF-9598-4995B8D8E5CC","name":"airballoon","codepoint":"F001C","aliases":["hot-air-balloon"],"tags":["Transportation + Other","Transportation + Flying"],"author":"Austin Andrews","version":"1.5.54"},{"id":"67E3294D-960F-4CD8-B4DB-3AAB13D6E17C","name":"airballoon-outline","codepoint":"F100B","aliases":["hot-air-balloon-outline"],"tags":["Transportation + Flying"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"5AE3D483-1E1C-49DE-92FF-21C6B93FD52F","name":"airplane","codepoint":"F001D","aliases":["aeroplane","airplanemode-active","flight","local-airport","flight-mode","plane"],"tags":["Transportation + Flying","Navigation"],"author":"Google","version":"1.5.54"},{"id":"634EE7E8-8280-4CF1-B642-0921E740B6DB","name":"airplane-landing","codepoint":"F05D4","aliases":["aeroplane-landing","flight-land","plane-landing"],"tags":["Transportation + Flying"],"author":"Google","version":"1.5.54"},{"id":"D2D1D38E-ABE7-47B6-9405-DC6BDBA1C335","name":"airplane-off","codepoint":"F001E","aliases":["aeroplane-off","airplanemode-inactive","flight-mode-off","plane-off"],"tags":["Transportation + Flying"],"author":"Google","version":"1.5.54"},{"id":"2B9BB7A1-A94B-4D24-8308-5599504317C2","name":"airplane-takeoff","codepoint":"F05D5","aliases":["aeroplane-takeoff","flight-takeoff","plane-takeoff","airplane-take-off"],"tags":["Transportation + Flying"],"author":"Google","version":"1.5.54"},{"id":"62C9DAA4-6718-44A9-BCD3-2401D96BE1E7","name":"airport","codepoint":"F084B","aliases":[],"tags":["Places","Transportation + Flying"],"author":"Michael Irigoyen","version":"2.1.99"},{"id":"9A1AAF33-6F36-4987-9E8C-798E34D919A9","name":"alarm","codepoint":"F0020","aliases":["access-alarms","alarm-clock"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"02423F51-52A3-4F45-8373-05CA8E8D57B7","name":"alarm-bell","codepoint":"F078E","aliases":[],"tags":["Notification"],"author":"Michael Richins","version":"2.0.46"},{"id":"6DCCA48F-E413-4C45-BFE5-8E3C8BE61A4E","name":"alarm-check","codepoint":"F0021","aliases":["alarm-on","alarm-tick","alarm-clock-check","alarm-clock-tick"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"B6D88F9D-A85A-4943-A61C-7D33FB0EBF4F","name":"alarm-light","codepoint":"F078F","aliases":[],"tags":[],"author":"Michael Richins","version":"2.0.46"},{"id":"E328D226-0D09-402D-BCAA-A7630396F168","name":"alarm-light-off","codepoint":"F171E","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"70D649B6-0FA1-4465-A92C-BB362D4D5FAD","name":"alarm-light-off-outline","codepoint":"F171F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"F6F4DACD-B15B-49FD-8ACC-FAE0E994435A","name":"alarm-light-outline","codepoint":"F0BEA","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.2.89"},{"id":"67D410AB-495A-41BD-B9D8-20A7DFBBF623","name":"alarm-multiple","codepoint":"F0022","aliases":["alarms","alarm-clock-multiple","alarm-clocks"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2C35D0DC-0191-4DFF-AF19-066F88DE56FE","name":"alarm-note","codepoint":"F0E71","aliases":[],"tags":[],"author":"Michael Richins","version":"3.7.94"},{"id":"2ECA27D9-8F96-4B03-A7BF-B74468CFCBF9","name":"alarm-note-off","codepoint":"F0E72","aliases":[],"tags":[],"author":"Michael Richins","version":"3.7.94"},{"id":"DD224DD6-9A65-47AB-8838-90FE346A7768","name":"alarm-off","codepoint":"F0023","aliases":["alarm-clock-off"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"AB8BCA23-EA1C-4A27-B535-4F373F1451E6","name":"alarm-panel","codepoint":"F15C4","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"60F9887C-36C5-4E6A-B282-4BACB99120BC","name":"alarm-panel-outline","codepoint":"F15C5","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"6D93F44C-83F7-4446-A5CD-E4135C8644D7","name":"alarm-plus","codepoint":"F0024","aliases":["add-alarm","alarm-clock-plus","alarm-clock-add","alarm-add"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"28F85724-265B-4C24-9975-DDDF788A99E5","name":"alarm-snooze","codepoint":"F068E","aliases":["alarm-clock-snooze"],"tags":["Date \/ Time"],"author":"Google","version":"1.7.12"},{"id":"8529D611-F581-4808-95BE-271FB1A6C2FD","name":"album","codepoint":"F0025","aliases":["vinyl","record"],"tags":["Audio","Music"],"author":"Google","version":"1.5.54"},{"id":"9FF7DF3F-D575-433B-9C9A-69C58363C186","name":"alert","codepoint":"F0026","aliases":["warning","report-problem"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"7B5D47A1-5658-4169-94C7-0C41E7179DD2","name":"alert-box","codepoint":"F0027","aliases":["warning-box"],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"1.5.54"},{"id":"D37BD379-9466-4E87-AD27-087CF72F076D","name":"alert-box-outline","codepoint":"F0CE4","aliases":["warning-box-outline"],"tags":["Alert \/ Error"],"author":"Peter Noble","version":"3.3.92"},{"id":"C7EDD5B7-95D4-4D83-A4E3-95D8A16A4887","name":"alert-circle","codepoint":"F0028","aliases":["warning-circle","error"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"68F19F47-B38B-4370-B299-4EE2BF2619A5","name":"alert-circle-check","codepoint":"F11ED","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"4.5.95"},{"id":"BB715CDA-DE45-4983-A33F-10C6141F4FEA","name":"alert-circle-check-outline","codepoint":"F11EE","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"4.5.95"},{"id":"0F4002B4-3C3D-43C4-939F-A998B2C59177","name":"alert-circle-outline","codepoint":"F05D6","aliases":["warning-circle-outline","error-outline","git-issue"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"B4866C08-2DAE-4B0A-8942-E057094B3C76","name":"alert-decagram","codepoint":"F06BD","aliases":["new-releases","warning-decagram"],"tags":["Alert \/ Error"],"author":"Google","version":"1.8.36"},{"id":"B2984FA7-4B68-4191-8835-EB768C58DD10","name":"alert-decagram-outline","codepoint":"F0CE5","aliases":["warning-decagram-outline"],"tags":["Alert \/ Error"],"author":"Peter Noble","version":"3.3.92"},{"id":"233D24FC-6BAE-44C4-BE98-7178560C4A32","name":"alert-minus","codepoint":"F14BB","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"044D1C2C-2EA5-4058-A3B0-0550BD2E3170","name":"alert-minus-outline","codepoint":"F14BE","aliases":[],"tags":["Alert \/ Error"],"author":"Contributors","version":"5.3.45"},{"id":"9BC1A338-CD03-4D39-BE46-E9DE5EE51A2F","name":"alert-octagon","codepoint":"F0029","aliases":["warning-octagon","report","stop-alert"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"90994A54-72AA-498F-8806-AAD466CC21BD","name":"alert-octagon-outline","codepoint":"F0CE6","aliases":["warning-octagon-outline","stop-alert-outline"],"tags":["Alert \/ Error"],"author":"Peter Noble","version":"3.3.92"},{"id":"124F37BE-27F6-4524-9655-A18D28E91CA6","name":"alert-octagram","codepoint":"F0767","aliases":["warning-octagram"],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"1.9.32"},{"id":"2AD21B3E-77C1-4027-9AE9-7655246D9DFF","name":"alert-octagram-outline","codepoint":"F0CE7","aliases":["warning-octagram-outline"],"tags":["Alert \/ Error"],"author":"Peter Noble","version":"3.3.92"},{"id":"4E574535-954C-42F5-BE5B-DF3716DB7C5A","name":"alert-outline","codepoint":"F002A","aliases":["warning-outline"],"tags":["Alert \/ Error"],"author":"Simran","version":"1.5.54"},{"id":"6D804890-36C6-43DC-B93D-B289A4C04D8F","name":"alert-plus","codepoint":"F14BA","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"5.3.45"},{"id":"C5512AAF-943C-4025-8FAB-F14D896F2C14","name":"alert-plus-outline","codepoint":"F14BD","aliases":[],"tags":["Alert \/ Error"],"author":"Contributors","version":"5.3.45"},{"id":"EF9A06FC-5167-4AE0-AB4E-FAD8C705E8C2","name":"alert-remove","codepoint":"F14BC","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"926FBBF9-9299-4E27-BB55-9CE300F50FDE","name":"alert-remove-outline","codepoint":"F14BF","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"C8354F93-0DA4-48B4-97B3-4BDE2C0046AB","name":"alert-rhombus","codepoint":"F11CE","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Richins","version":"4.5.95"},{"id":"C9724C30-FDBB-4A14-BC0B-59F0E6826DC3","name":"alert-rhombus-outline","codepoint":"F11CF","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Richins","version":"4.5.95"},{"id":"CD43AC33-8EE0-42BE-A7E0-3CCB31D8C5D3","name":"alien","codepoint":"F089A","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.2.43"},{"id":"F673BEC2-F616-4A5A-B33B-4CD776D80819","name":"alien-outline","codepoint":"F10CB","aliases":[],"tags":[],"author":"Sascha Wohlgemuth","version":"4.3.95"},{"id":"05901A9E-71D5-47D9-B5E1-DC55B687E8E0","name":"align-horizontal-center","codepoint":"F11C3","aliases":["align-horizontal-centre"],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"91ED2206-4D41-48DB-964F-5E3AC50F899D","name":"align-horizontal-left","codepoint":"F11C2","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"5FEBC8BB-061B-4D91-BD96-88285B5C2E23","name":"align-horizontal-right","codepoint":"F11C4","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"AA5D11B7-D45D-4505-938E-8BEF8C1A79F0","name":"align-vertical-bottom","codepoint":"F11C5","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"04AE9704-928E-4272-B7FA-BD2ABC38ABE0","name":"align-vertical-center","codepoint":"F11C6","aliases":["align-vertical-centre"],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"9069B66B-C7CA-478D-BE02-BC9863E27FDB","name":"align-vertical-top","codepoint":"F11C7","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"5596E6E7-916E-4870-9346-5D46BC86C0D5","name":"all-inclusive","codepoint":"F06BE","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"76B6381F-14CA-4453-8B28-184C508D003B","name":"allergy","codepoint":"F1258","aliases":["hand","rash","germ"],"tags":["Medical \/ Hospital"],"author":"Michael Richins","version":"4.7.95"},{"id":"0B93DD30-B279-4997-BD6D-AC86E29D34CA","name":"alpha","codepoint":"F002B","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Austin Andrews","version":"1.5.54"},{"id":"8A55BEB9-D57B-43DA-9905-7216E3EB7057","name":"alpha-a","codepoint":"F0AEE","aliases":["alphabet-a","letter-a"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"1AC5B76A-B93F-4F9B-851D-C3DAF9743046","name":"alpha-a-box","codepoint":"F0B08","aliases":["alphabet-a-box","letter-a-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"B501FBBD-91FA-4567-8D4A-BD933FECCE7B","name":"alpha-a-box-outline","codepoint":"F0BEB","aliases":["alphabet-a-box-outline","letter-a-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"71A79E36-29B9-4543-B386-399F950641E2","name":"alpha-a-circle","codepoint":"F0BEC","aliases":["alphabet-a-circle","letter-a-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"6BB0D642-F5B7-4903-977C-325FE1F068FF","name":"alpha-a-circle-outline","codepoint":"F0BED","aliases":["alphabet-a-circle-outline","letter-a-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"910DF87E-809E-40D6-886F-34E581899455","name":"alpha-b","codepoint":"F0AEF","aliases":["alphabet-b","letter-b"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"057EDDAB-65B4-495C-A473-71F759BC6FD9","name":"alpha-b-box","codepoint":"F0B09","aliases":["alphabet-b-box","letter-b-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"ACEAA38C-D83E-4812-AFF3-A063F0226825","name":"alpha-b-box-outline","codepoint":"F0BEE","aliases":["alphabet-b-box-outline","letter-b-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"433A1CBB-57A4-44DA-8B93-B65AF6E54B1D","name":"alpha-b-circle","codepoint":"F0BEF","aliases":["alphabet-b-circle","letter-b-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"5CBD1C34-B372-4DA7-9FF1-19DD9B3D9C3A","name":"alpha-b-circle-outline","codepoint":"F0BF0","aliases":["alphabet-b-circle-outline","letter-b-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"F5F53184-51BB-46A3-AB67-D799A1D15F7F","name":"alpha-c","codepoint":"F0AF0","aliases":["alphabet-c","letter-c"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"F7A4DF3D-18C8-4717-AD58-247CEFF7EDE3","name":"alpha-c-box","codepoint":"F0B0A","aliases":["alphabet-c-box","letter-c-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"9EB832F8-B389-47AA-ADDA-A2163E75DC20","name":"alpha-c-box-outline","codepoint":"F0BF1","aliases":["alphabet-c-box-outline","letter-c-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"19229F43-9ACD-477E-9A30-9D2731080026","name":"alpha-c-circle","codepoint":"F0BF2","aliases":["alphabet-c-circle","letter-c-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"23362597-17A2-4413-BE28-65B36F4591E7","name":"alpha-c-circle-outline","codepoint":"F0BF3","aliases":["alphabet-c-circle-outline","letter-c-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"0A79E0A4-CE86-431C-A152-57492815C31E","name":"alpha-d","codepoint":"F0AF1","aliases":["alphabet-d","letter-d","drive"],"tags":["Automotive","Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"5299B671-D7CF-4D68-B439-92E3056A104A","name":"alpha-d-box","codepoint":"F0B0B","aliases":["alphabet-d-box","letter-d-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"5D512B06-6DF4-4BC7-A307-81512F828192","name":"alpha-d-box-outline","codepoint":"F0BF4","aliases":["alphabet-d-box-outline","letter-d-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"758D2479-2950-4C5E-8FDC-C0FFA2EBE114","name":"alpha-d-circle","codepoint":"F0BF5","aliases":["alphabet-d-circle","letter-d-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"6B6C0FE9-544A-4098-A5B2-823160140EE7","name":"alpha-d-circle-outline","codepoint":"F0BF6","aliases":["alphabet-d-circle-outline","letter-d-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"3B3F5AA2-8A97-4A66-BD4A-7AA105901B61","name":"alpha-e","codepoint":"F0AF2","aliases":["alphabet-e","letter-e"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"15C859D5-210D-4C8B-BB14-7A2B92ADB1C2","name":"alpha-e-box","codepoint":"F0B0C","aliases":["alphabet-e-box","letter-e-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"6C02F23D-4684-4018-9E47-624103B0653E","name":"alpha-e-box-outline","codepoint":"F0BF7","aliases":["alphabet-e-box-outline","letter-e-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"D1367C3A-1884-4A3E-A90F-0AAB3DDCACF1","name":"alpha-e-circle","codepoint":"F0BF8","aliases":["alphabet-e-circle","letter-e-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"CD51D79A-B691-4B46-BABF-6A419EE2716A","name":"alpha-e-circle-outline","codepoint":"F0BF9","aliases":["alphabet-e-circle-outline","letter-e-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"6E5FB32C-27B6-4ECE-8F88-65D8E29D1CD8","name":"alpha-f","codepoint":"F0AF3","aliases":["alphabet-f","letter-f"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"1E5D6AAB-6056-4CEE-88EC-87FBE2C84FF0","name":"alpha-f-box","codepoint":"F0B0D","aliases":["alphabet-f-box","letter-f-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"304C0008-2989-4DC9-8927-AE51F7B44F6C","name":"alpha-f-box-outline","codepoint":"F0BFA","aliases":["alphabet-f-box-outline","letter-f-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"317A9E55-62CC-4A55-B851-483EB546D022","name":"alpha-f-circle","codepoint":"F0BFB","aliases":["alphabet-f-circle","letter-f-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"46706811-B9CA-4F96-B201-63E658BE1F6D","name":"alpha-f-circle-outline","codepoint":"F0BFC","aliases":["alphabet-f-circle-outline","letter-f-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"4B7C3083-DFDF-402E-9D71-CABE04305297","name":"alpha-g","codepoint":"F0AF4","aliases":["alphabet-g","letter-g"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"A2781290-35AD-441F-B02C-15A0AB49B74D","name":"alpha-g-box","codepoint":"F0B0E","aliases":["alphabet-g-box","letter-g-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"D9ED1661-B57E-47E9-B727-F03BC035DE4D","name":"alpha-g-box-outline","codepoint":"F0BFD","aliases":["alphabet-g-box-outline","letter-g-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"5DB072AE-CE38-4FA8-A41D-0C7443DA3481","name":"alpha-g-circle","codepoint":"F0BFE","aliases":["alphabet-g-circle","letter-g-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"780BAB12-D647-4E55-BD56-487367D70FD0","name":"alpha-g-circle-outline","codepoint":"F0BFF","aliases":["alphabet-g-circle-outline","letter-g-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"99A5A78F-6759-4C02-A5D2-DA8FA3DDBBA9","name":"alpha-h","codepoint":"F0AF5","aliases":["alphabet-h","letter-h"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"180E5F6A-8C7E-4B29-92C1-94C97D1266B9","name":"alpha-h-box","codepoint":"F0B0F","aliases":["alphabet-h-box","letter-h-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"7568D810-145E-41E7-8447-E2257339D5D8","name":"alpha-h-box-outline","codepoint":"F0C00","aliases":["alphabet-h-box-outline","letter-h-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"FC1C719F-CE44-4B8A-A2A8-5DE6E02405D2","name":"alpha-h-circle","codepoint":"F0C01","aliases":["alphabet-h-circle","letter-h-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"29BA4374-825B-46E4-8E81-FC027000A16F","name":"alpha-h-circle-outline","codepoint":"F0C02","aliases":["alphabet-h-circle-outline","letter-h-circle-outline","helipad"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"C34618B6-174E-42C7-AD23-B65FCAC93D74","name":"alpha-i","codepoint":"F0AF6","aliases":["alphabet-i","letter-i","roman-numeral-1"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"4D933A0E-88F5-4712-8BA1-0E60290A6623","name":"alpha-i-box","codepoint":"F0B10","aliases":["alphabet-i-box","letter-i-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"E7CF351D-BC47-44AC-BA3E-D61F99D11026","name":"alpha-i-box-outline","codepoint":"F0C03","aliases":["alphabet-i-box-outline","letter-i-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"0CAD67D2-EFF3-442E-91D6-1C27D759C1DD","name":"alpha-i-circle","codepoint":"F0C04","aliases":["alphabet-i-circle","letter-i-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"4AAE84B4-CF3E-4736-A420-DD188452F819","name":"alpha-i-circle-outline","codepoint":"F0C05","aliases":["alphabet-i-circle-outline","letter-i-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"C964FFC4-AA90-4AF6-B604-352082207789","name":"alpha-j","codepoint":"F0AF7","aliases":["alphabet-j","letter-j"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"1472FB12-4CBA-476C-8F57-E1CB5E4213A6","name":"alpha-j-box","codepoint":"F0B11","aliases":["alphabet-j-box","letter-j-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"52E82BF4-8023-49C2-A4CB-AF3A88B43D1A","name":"alpha-j-box-outline","codepoint":"F0C06","aliases":["alphabet-j-box-outline","letter-j-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"90C7D800-47CA-4E5E-860D-8AAB0F6C51DC","name":"alpha-j-circle","codepoint":"F0C07","aliases":["alphabet-j-circle","letter-j-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"0A0B3839-C0D3-422A-B688-E59F4927AA6F","name":"alpha-j-circle-outline","codepoint":"F0C08","aliases":["alphabet-j-circle-outline","letter-j-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"358C06F7-7E39-4023-A9FC-2C02F275B84B","name":"alpha-k","codepoint":"F0AF8","aliases":["alphabet-k","letter-k"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"EF778205-36FD-4C55-BDFB-0373983C95D4","name":"alpha-k-box","codepoint":"F0B12","aliases":["alphabet-k-box","letter-k-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"FD913715-7C1E-4E80-9A44-34992AADB3E6","name":"alpha-k-box-outline","codepoint":"F0C09","aliases":["alphabet-k-box-outline","letter-k-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"1F260841-CE76-48D8-BACE-8935459D850E","name":"alpha-k-circle","codepoint":"F0C0A","aliases":["alphabet-k-circle","letter-k-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"F4E2D505-4C0D-4184-9F62-FDD7A450F6E7","name":"alpha-k-circle-outline","codepoint":"F0C0B","aliases":["alphabet-k-circle-outline","letter-k-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"C4CFE00B-0978-482B-8E9E-F1DD4B21B45B","name":"alpha-l","codepoint":"F0AF9","aliases":["alphabet-l","letter-l"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"7E7BF31C-C3FA-4744-B214-FF8D15753ED5","name":"alpha-l-box","codepoint":"F0B13","aliases":["alphabet-l-box","letter-l-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"C0044FE0-893A-4429-A57F-9C58DFBE36CC","name":"alpha-l-box-outline","codepoint":"F0C0C","aliases":["alphabet-l-box-outline","letter-l-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"B1456398-80C2-4D10-B7D3-A79BE026E457","name":"alpha-l-circle","codepoint":"F0C0D","aliases":["alphabet-l-circle","letter-l-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"F62EB8C2-6037-474B-8D48-FD635163D3A6","name":"alpha-l-circle-outline","codepoint":"F0C0E","aliases":["alphabet-l-circle-outline","letter-l-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"31B62839-D838-41FE-86B8-313070BBB0A9","name":"alpha-m","codepoint":"F0AFA","aliases":["alphabet-m","letter-m"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"AB678336-D11A-4426-92A8-AA520A4F282B","name":"alpha-m-box","codepoint":"F0B14","aliases":["alphabet-m-box","letter-m-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"147229CF-1402-4406-8E94-B83CC64248E2","name":"alpha-m-box-outline","codepoint":"F0C0F","aliases":["alphabet-m-box-outline","letter-m-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"88D09175-8E63-4542-BBE7-6B8D7EC16EBE","name":"alpha-m-circle","codepoint":"F0C10","aliases":["alphabet-m-circle","letter-m-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"F85ABB66-FEE7-46ED-9DE3-AB3B24597863","name":"alpha-m-circle-outline","codepoint":"F0C11","aliases":["alphabet-m-circle-outline","letter-m-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"528E55D8-A774-4678-9D76-42EEFDF5FE3E","name":"alpha-n","codepoint":"F0AFB","aliases":["alphabet-n","letter-n","neutral"],"tags":["Automotive","Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"8A547BE1-B4F5-4080-824D-998618AF2542","name":"alpha-n-box","codepoint":"F0B15","aliases":["alphabet-n-box","letter-n-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"DF0B3005-5E38-4E53-9025-981EFA45D8FD","name":"alpha-n-box-outline","codepoint":"F0C12","aliases":["alphabet-n-box-outline","letter-n-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"929903C6-6867-4884-8A02-7D72F1C44F2D","name":"alpha-n-circle","codepoint":"F0C13","aliases":["alphabet-n-circle","letter-n-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"8DA6710E-B31C-42C1-BB43-1B903D4B5CA5","name":"alpha-n-circle-outline","codepoint":"F0C14","aliases":["alphabet-n-circle-outline","letter-n-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"67F8B291-3AA9-4C70-AEAB-0150A40909FB","name":"alpha-o","codepoint":"F0AFC","aliases":["alphabet-o","letter-o"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"53B24801-62B0-46AC-9474-90DCA470E506","name":"alpha-o-box","codepoint":"F0B16","aliases":["alphabet-o-box","letter-o-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"9563FB80-4D77-4800-B7DF-CCFDD00A49DD","name":"alpha-o-box-outline","codepoint":"F0C15","aliases":["alphabet-o-box-outline","letter-o-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"5DB486E7-89A5-45A6-8926-007B37DBC7D9","name":"alpha-o-circle","codepoint":"F0C16","aliases":["alphabet-o-circle","letter-o-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"485D936E-F9F7-4D89-A2CC-2C11268EAC1A","name":"alpha-o-circle-outline","codepoint":"F0C17","aliases":["alphabet-o-circle-outline","letter-o-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"750E27F3-36FF-423A-8AAD-F2FE833D9028","name":"alpha-p","codepoint":"F0AFD","aliases":["alphabet-p","letter-p","park"],"tags":["Automotive","Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"A2775802-5936-4F9A-9E7F-54D2EA8CC0E9","name":"alpha-p-box","codepoint":"F0B17","aliases":["alphabet-p-box","letter-p-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"B9B61AA9-C657-4C73-8C75-2A01C08672A6","name":"alpha-p-box-outline","codepoint":"F0C18","aliases":["alphabet-p-box-outline","letter-p-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"172BAE9F-C813-407E-A1D0-CBB548C3F9D8","name":"alpha-p-circle","codepoint":"F0C19","aliases":["alphabet-p-circle","letter-p-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"5FF2B25B-8414-4FC9-BBEB-5D51901FB709","name":"alpha-p-circle-outline","codepoint":"F0C1A","aliases":["alphabet-p-circle-outline","letter-p-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"7DAD6E06-5D6E-4827-A20E-526F2F5AF4C9","name":"alpha-q","codepoint":"F0AFE","aliases":["alphabet-q","letter-q"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"4B916C98-B981-4822-90D2-3EADCAE01FA3","name":"alpha-q-box","codepoint":"F0B18","aliases":["alphabet-q-box","letter-q-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"C30942DA-E2FB-41A1-A0A5-3FB004E8FC67","name":"alpha-q-box-outline","codepoint":"F0C1B","aliases":["alphabet-q-box-outline","letter-q-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"03AA79A3-ADEF-4B0E-8023-455FAD721515","name":"alpha-q-circle","codepoint":"F0C1C","aliases":["alphabet-q-circle","letter-q-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"43F96FE9-53D0-4C4E-AEC3-773656C97E41","name":"alpha-q-circle-outline","codepoint":"F0C1D","aliases":["alphabet-q-circle-outline","letter-q-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"A1C326AD-B2A8-4A9A-98AA-B657C101EB2F","name":"alpha-r","codepoint":"F0AFF","aliases":["alphabet-r","letter-r","reverse"],"tags":["Automotive","Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"0089397E-6983-4161-9D06-77F3598119DD","name":"alpha-r-box","codepoint":"F0B19","aliases":["alphabet-r-box","letter-r-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"206DB27B-1F78-481F-8E8E-1A78F8221EF7","name":"alpha-r-box-outline","codepoint":"F0C1E","aliases":["alphabet-r-box-outline","letter-r-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"A0CA4573-5B82-4760-BB23-7D1413DE7257","name":"alpha-r-circle","codepoint":"F0C1F","aliases":["alphabet-r-circle","letter-r-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"3EFEFA7D-EE69-4813-93AB-096C148CC74B","name":"alpha-r-circle-outline","codepoint":"F0C20","aliases":["alphabet-r-circle-outline","letter-r-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"5E4ECB99-9DA0-419C-AADE-F2F7AE91FF6A","name":"alpha-s","codepoint":"F0B00","aliases":["alphabet-s","letter-s"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"2BC531B2-987E-411F-B3AE-3686F24F3B05","name":"alpha-s-box","codepoint":"F0B1A","aliases":["alphabet-s-box","letter-s-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"839A6E89-0555-4B05-BADA-B0D0C665E885","name":"alpha-s-box-outline","codepoint":"F0C21","aliases":["alphabet-s-box-outline","letter-s-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"2F13C710-300C-4287-9320-C84024C1002D","name":"alpha-s-circle","codepoint":"F0C22","aliases":["alphabet-s-circle","letter-s-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"17018533-C274-4E75-86DB-2D0DB1F4B45E","name":"alpha-s-circle-outline","codepoint":"F0C23","aliases":["alphabet-s-circle-outline","letter-s-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"DEAF6AD9-9AB9-4B59-B47D-830357A4B665","name":"alpha-t","codepoint":"F0B01","aliases":["alphabet-t","letter-t"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"3FDF524A-6293-4401-BEDE-7768370743CE","name":"alpha-t-box","codepoint":"F0B1B","aliases":["alphabet-t-box","letter-t-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"5AB643B8-7A4C-470B-9C0C-3A3E1E730623","name":"alpha-t-box-outline","codepoint":"F0C24","aliases":["alphabet-t-box-outline","letter-t-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"6A41607E-FD2D-49EB-B6A5-67472ECF381E","name":"alpha-t-circle","codepoint":"F0C25","aliases":["alphabet-t-circle","letter-t-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"63897F2D-C1BC-46D0-96D8-82CCC8AB8E9C","name":"alpha-t-circle-outline","codepoint":"F0C26","aliases":["alphabet-t-circle-outline","letter-t-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"7404138B-11FC-441F-9F64-2CADF3EED84F","name":"alpha-u","codepoint":"F0B02","aliases":["alphabet-u","letter-u"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"B383312A-D001-4F27-95D9-9C705B7529E7","name":"alpha-u-box","codepoint":"F0B1C","aliases":["alphabet-u-box","letter-u-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"CAA94F37-3C12-4A17-A0CF-F093E39F5463","name":"alpha-u-box-outline","codepoint":"F0C27","aliases":["alphabet-u-box-outline","letter-u-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"C47AD771-D938-41ED-B07A-28499959E3BF","name":"alpha-u-circle","codepoint":"F0C28","aliases":["alphabet-u-circle","letter-u-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"12B388EE-036B-45AF-8390-122E6BA125CF","name":"alpha-u-circle-outline","codepoint":"F0C29","aliases":["alphabet-u-circle-outline","letter-u-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"6A261917-D952-4EFD-B8A4-9A91BCF67DE1","name":"alpha-v","codepoint":"F0B03","aliases":["alphabet-v","letter-v","roman-numeral-5"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"C3B68231-EFA7-4988-BED2-9C158A812AC4","name":"alpha-v-box","codepoint":"F0B1D","aliases":["alphabet-v-box","letter-v-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"784EF15E-8476-47B9-BACA-D440F60A371E","name":"alpha-v-box-outline","codepoint":"F0C2A","aliases":["alphabet-v-box-outline","letter-v-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"C97A782B-26C7-4732-804F-D7D5BE126D5D","name":"alpha-v-circle","codepoint":"F0C2B","aliases":["alphabet-v-circle","letter-v-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"F6CE363B-41A6-411A-9FDE-D36E24013012","name":"alpha-v-circle-outline","codepoint":"F0C2C","aliases":["alphabet-v-circle-outline","letter-v-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"DFACCE73-8433-472E-AAB6-6471BBFDC82C","name":"alpha-w","codepoint":"F0B04","aliases":["alphabet-w","letter-w"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"E63E39FF-8E9F-470F-9CDD-55B2703E620A","name":"alpha-w-box","codepoint":"F0B1E","aliases":["alphabet-w-box","letter-w-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"B844FAFE-5491-4441-9C3E-23F2AB148E10","name":"alpha-w-box-outline","codepoint":"F0C2D","aliases":["alphabet-w-box-outline","letter-w-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"8718E128-006E-4009-A718-A104B4C8E3A4","name":"alpha-w-circle","codepoint":"F0C2E","aliases":["alphabet-w-circle","letter-w-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"24152C0F-8019-42D1-B4F2-3917388A8987","name":"alpha-w-circle-outline","codepoint":"F0C2F","aliases":["alphabet-w-circle-outline","letter-w-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"44344AAE-07D8-455B-AA2E-68474E8829FE","name":"alpha-x","codepoint":"F0B05","aliases":["alphabet-x","letter-x","roman-numeral-10"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"25BBD26F-C8D4-4E4D-899C-57D910EECA55","name":"alpha-x-box","codepoint":"F0B1F","aliases":["alphabet-x-box","letter-x-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"98537673-0A9D-4982-A0E0-BFD69A0C1401","name":"alpha-x-box-outline","codepoint":"F0C30","aliases":["alphabet-x-box-outline","letter-x-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"BF0C5599-EFCE-44ED-AD08-3CE99DFC9802","name":"alpha-x-circle","codepoint":"F0C31","aliases":["alphabet-x-circle","letter-x-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"8B9761E9-9101-4850-8DCA-D8B63193A20B","name":"alpha-x-circle-outline","codepoint":"F0C32","aliases":["alphabet-x-circle-outline","letter-x-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"CD6A13CC-DA14-42AD-A4A0-2A99EA3E5E3D","name":"alpha-y","codepoint":"F0B06","aliases":["alphabet-y","letter-y"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"00418BEF-11B7-4644-8F57-3CBB7D8F9760","name":"alpha-y-box","codepoint":"F0B20","aliases":["alphabet-y-box","letter-y-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"929FF46B-C6B6-4973-BB7E-44C232F149AC","name":"alpha-y-box-outline","codepoint":"F0C33","aliases":["alphabet-y-box-outline","letter-y-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"07D04396-8CE9-47A0-80BF-9D7055655F81","name":"alpha-y-circle","codepoint":"F0C34","aliases":["alphabet-y-circle","letter-y-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"94DF1C7C-7FDE-4AD8-B6F9-B23C3C4DA478","name":"alpha-y-circle-outline","codepoint":"F0C35","aliases":["alphabet-y-circle-outline","letter-y-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"E82C7336-9ECE-4BA9-84BA-AA229FBF4E37","name":"alpha-z","codepoint":"F0B07","aliases":["alphabet-z","letter-z"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"175F93C9-39AA-4076-A997-B1984D5CE960","name":"alpha-z-box","codepoint":"F0B21","aliases":["alphabet-z-box","letter-z-box"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"EB6335C7-9EA1-4EB3-BCA5-2DF54F8B50C8","name":"alpha-z-box-outline","codepoint":"F0C36","aliases":["alphabet-z-box-outline","letter-z-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"1F60D37E-2D88-48D1-A291-D3F59D171E55","name":"alpha-z-circle","codepoint":"F0C37","aliases":["alphabet-z-circle","letter-z-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"63AF9496-BE67-43F7-9DE4-341E0EDC0C62","name":"alpha-z-circle-outline","codepoint":"F0C38","aliases":["alphabet-z-circle-outline","letter-z-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"68AC0195-57C1-4759-8814-FA18DFE0351B","name":"alphabet-aurebesh","codepoint":"F132C","aliases":["writing-system-aurebesh"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"197B613F-AF17-41DE-B2A6-7FCB8D86C366","name":"alphabet-cyrillic","codepoint":"F132D","aliases":["writing-system-cyrillic"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"5E1EDFBD-2E67-41E1-8E23-F835614DBBD9","name":"alphabet-greek","codepoint":"F132E","aliases":["writing-system-greek"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"07851190-1E8F-43D3-A5BF-01A120C0A3FB","name":"alphabet-latin","codepoint":"F132F","aliases":["writing-system-latin"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"169593B8-F579-4167-B49C-5F353BBABB00","name":"alphabet-piqad","codepoint":"F1330","aliases":["writing-system-piqad"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"48C4C59F-80F3-454B-94B2-1951506F38C1","name":"alphabet-tengwar","codepoint":"F1337","aliases":["writing-system-tengwar"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"EAD8BAC5-EE7C-4553-9316-F45094CF9C7A","name":"alphabetical","codepoint":"F002C","aliases":["letters","a-b-c","abc"],"tags":["Alpha \/ Numeric"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5C6F0A6B-362A-4EBF-9E0C-57E7405429AE","name":"alphabetical-off","codepoint":"F100C","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Richins","version":"4.1.95"},{"id":"87F9C7D3-2B22-45A0-A1A8-1060ECA2B0DD","name":"alphabetical-variant","codepoint":"F100D","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Richins","version":"4.1.95"},{"id":"5C408382-5124-4A1E-9603-C510614D4C63","name":"alphabetical-variant-off","codepoint":"F100E","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Richins","version":"4.1.95"},{"id":"1F7A2F31-3549-4F3C-A95E-E7356033A601","name":"altimeter","codepoint":"F05D7","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"9AE6BA3C-694B-47D5-99C3-7D063228F053","name":"amazon","codepoint":"F002D","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"DD3492E1-1F83-4E41-8BA9-9E6A1380D235","name":"amazon-alexa","codepoint":"F08C6","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.3.50"},{"id":"B0DB559B-A9D4-473A-AF6D-C72559CCC9D9","name":"ambulance","codepoint":"F002F","aliases":[],"tags":["Transportation + Road","Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"0F3F828D-7F80-4571-A5B5-296FAC62FFB9","name":"ammunition","codepoint":"F0CE8","aliases":["bullets"],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"CC5AC69B-0EAA-454A-8757-4F670F478952","name":"ampersand","codepoint":"F0A8D","aliases":["and"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"4A952C8C-7A6F-4028-A974-48E4DCE299CF","name":"amplifier","codepoint":"F0030","aliases":[],"tags":["Home Automation","Music"],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"E2914725-030B-4979-BCDE-87FCD4435F7F","name":"amplifier-off","codepoint":"F11B5","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"8A3C8CCE-D798-446B-A283-90129AD847C9","name":"anchor","codepoint":"F0031","aliases":[],"tags":["Transportation + Water"],"author":"Google","version":"1.5.54"},{"id":"4633B767-FF29-411D-8C04-69057C6B65B2","name":"android","codepoint":"F0032","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"46DE4030-CBE2-401D-82A0-50B99DE514D1","name":"android-auto","codepoint":"F0A8E","aliases":[],"tags":["Automotive","Brand \/ Logo"],"author":"Google","version":"2.7.94"},{"id":"F9923FF1-E31E-4C03-BBB7-438704CF3909","name":"android-debug-bridge","codepoint":"F0033","aliases":["adb"],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"55847C89-2AE5-4F91-85AA-761FD8CE57F0","name":"android-messages","codepoint":"F0D45","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"B156B15D-86F9-40E0-8B8E-421F78BE5509","name":"android-studio","codepoint":"F0034","aliases":["math-compass-variant"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B4A236B3-E14B-4A64-8EDD-A48128013388","name":"angle-acute","codepoint":"F0937","aliases":[],"tags":["Math"],"author":"Haley Halcyon","version":"2.4.85"},{"id":"7A6B88D9-B385-4A6B-84C8-8280456944E4","name":"angle-obtuse","codepoint":"F0938","aliases":[],"tags":["Math"],"author":"Haley Halcyon","version":"2.4.85"},{"id":"77550809-9FBB-4283-BA57-7C48AB2B86C0","name":"angle-right","codepoint":"F0939","aliases":[],"tags":["Math"],"author":"Haley Halcyon","version":"2.4.85"},{"id":"549F8173-7E91-411F-9ECF-D04D2B64B386","name":"angular","codepoint":"F06B2","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"1.7.22"},{"id":"8A82CBEA-C1B3-40C2-96C2-DED8D83DA446","name":"angularjs","codepoint":"F06BF","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"1.8.36"},{"id":"4FE8F135-8FF9-427B-8857-122FBB0A300A","name":"animation","codepoint":"F05D8","aliases":["auto-awesome-motion"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"5DCFE57B-82CA-401A-A797-3C12F1BF4080","name":"animation-outline","codepoint":"F0A8F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"093AE881-42E2-46B9-B833-894DDC2FE368","name":"animation-play","codepoint":"F093A","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"423AD280-5A46-49AF-B4C7-20C5E1640002","name":"animation-play-outline","codepoint":"F0A90","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"34EEAB55-08C0-4C84-A580-CAF1FA926D94","name":"ansible","codepoint":"F109A","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.2.95"},{"id":"B6F97155-147F-4D03-9C71-7668E5EA2712","name":"antenna","codepoint":"F1119","aliases":[],"tags":[],"author":"Google","version":"4.3.95"},{"id":"C72FF17B-D0E1-4641-9802-B6BA993D5910","name":"anvil","codepoint":"F089B","aliases":[],"tags":[],"author":"Nick","version":"2.2.43"},{"id":"B94C01C7-0851-4FD4-AEFD-CCD63F65C093","name":"apache-kafka","codepoint":"F100F","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"4.1.95"},{"id":"ABE80259-E64D-4BF4-BC6E-1D8FFA16636F","name":"api","codepoint":"F109B","aliases":[],"tags":["Developer \/ Languages"],"author":"Google","version":"4.2.95"},{"id":"22B88F3A-28F4-41FA-A63B-721699E2A8B2","name":"api-off","codepoint":"F1257","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"2829275C-A01C-42CD-A195-447629791D04","name":"apple","codepoint":"F0035","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"CD5DD59A-965F-455E-912B-9535BFD134E0","name":"apple-airplay","codepoint":"F001F","aliases":["apple"],"tags":["Home Automation"],"author":"Contributors","version":"1.5.54"},{"id":"FAEC5B00-46A8-49AD-87DA-765891B9E387","name":"apple-finder","codepoint":"F0036","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"BDB8AF3D-28BD-4FF2-AED0-36108C1B0543","name":"apple-icloud","codepoint":"F0038","aliases":["apple-mobileme"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"9B0B7248-3416-4D43-9CE1-13D70949EAA1","name":"apple-ios","codepoint":"F0037","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"070FF4A9-7726-4682-8ABD-AC1800B8D83E","name":"apple-keyboard-caps","codepoint":"F0632","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"03043022-A59D-4E31-B385-E6D94D3D9B92","name":"apple-keyboard-command","codepoint":"F0633","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"F24769F6-25C3-4244-8C64-13A514E7CAAD","name":"apple-keyboard-control","codepoint":"F0634","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"C06A94E2-9606-484B-BC0D-D0B9A2FBA76F","name":"apple-keyboard-option","codepoint":"F0635","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"5AF5B660-DDD5-446A-8AC9-102776DBBBC9","name":"apple-keyboard-shift","codepoint":"F0636","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"F79DE68B-BB98-41F7-9B5D-69C8926AB9B0","name":"apple-safari","codepoint":"F0039","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"55C0C50F-9F4D-44C4-A84B-C79F645A8604","name":"application","codepoint":"F0614","aliases":["web-asset"],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"A3B1663D-87F0-4E57-BAF4-5CB9D0CC6B17","name":"application-cog","codepoint":"F1577","aliases":["application-settings"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"19852AF4-396B-4BA7-B9A1-3E412D49290A","name":"application-export","codepoint":"F0DAD","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.5.94"},{"id":"0870BDBC-060F-49E5-B72C-CA06949643AF","name":"application-import","codepoint":"F0DAE","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.5.94"},{"id":"EB7E0628-A5CC-4E23-9AD1-CC35CC4E3722","name":"application-settings","codepoint":"F1555","aliases":[],"tags":["Settings"],"author":"CoreyVidal","version":"5.5.55"},{"id":"B5A9F91C-21A0-415A-AC77-B4318137C32D","name":"approximately-equal","codepoint":"F0F9E","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"8EE13AEC-B8FF-4E25-9D5B-8447B0310133","name":"approximately-equal-box","codepoint":"F0F9F","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"7F5B9650-26E7-4A88-A6D1-2C338778651D","name":"apps","codepoint":"F003B","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"3EEC66E4-C03F-4701-B151-1C8048D19505","name":"apps-box","codepoint":"F0D46","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"B7F8E18D-C18D-4EA1-BABE-BE0E48BDCF2D","name":"arch","codepoint":"F08C7","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.3.50"},{"id":"9C2AD144-9997-4169-983C-879DCCD62760","name":"archive","codepoint":"F003C","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"41367FBC-DCE3-4202-AF33-3AD576C3FD7C","name":"archive-alert","codepoint":"F14FD","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"5.4.55"},{"id":"1D17B03B-9147-4067-8F5E-88773D68289E","name":"archive-alert-outline","codepoint":"F14FE","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"5.4.55"},{"id":"237B205E-C03C-424A-93F9-8C771FE01A38","name":"archive-arrow-down","codepoint":"F1259","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"133BA980-E797-4DB3-9C92-F59AC3DB3399","name":"archive-arrow-down-outline","codepoint":"F125A","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"43E8F715-D3DB-4CAA-9355-88E22C7E4D28","name":"archive-arrow-up","codepoint":"F125B","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"643EF8E3-148D-4858-85C6-A965822B74CF","name":"archive-arrow-up-outline","codepoint":"F125C","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"4B8AAB0C-9EB8-44D9-B1DF-C2EE6ACB91BE","name":"archive-outline","codepoint":"F120E","aliases":[],"tags":[],"author":"James Coyle","version":"4.6.95"},{"id":"F7613EF8-368F-4AA6-B833-7246A01C3961","name":"arm-flex","codepoint":"F0FD7","aliases":[],"tags":[],"author":"Contributors","version":"4.2.95"},{"id":"D64BE31F-BA1D-48E0-B747-A1422392EC2D","name":"arm-flex-outline","codepoint":"F0FD6","aliases":[],"tags":[],"author":"Contributors","version":"4.2.95"},{"id":"7F57A003-5F4E-46CF-9099-51B8D05381F8","name":"arrange-bring-forward","codepoint":"F003D","aliases":[],"tags":["Arrange","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"679C0678-9688-49FD-BA71-BED740A09267","name":"arrange-bring-to-front","codepoint":"F003E","aliases":[],"tags":["Arrange","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"677B1C90-BB0B-4F73-8EEA-D6E8FA709A6D","name":"arrange-send-backward","codepoint":"F003F","aliases":[],"tags":["Arrange","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"86145497-4CAA-41D6-A14E-0DD3FEE7721E","name":"arrange-send-to-back","codepoint":"F0040","aliases":[],"tags":["Arrange","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5540E986-54E7-4FBF-A62F-9937B9E4F78D","name":"arrow-all","codepoint":"F0041","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"25DD11B1-DE14-49E3-A54F-B01DCC45798D","name":"arrow-bottom-left","codepoint":"F0042","aliases":["arrow-down-left"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B34E6142-64AF-43FE-A565-2FAEEA35B800","name":"arrow-bottom-left-bold-outline","codepoint":"F09B7","aliases":["arrow-down-left-bold-outline"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"73858F0F-F08D-4D54-A3C1-54E794E9C097","name":"arrow-bottom-left-thick","codepoint":"F09B8","aliases":["arrow-down-left-thick","arrow-bottom-left-bold","arrow-down-left-bold"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"D2582EA8-570A-4CB9-81A0-5DB3308BF6BD","name":"arrow-bottom-left-thin-circle-outline","codepoint":"F1596","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"F7CB7031-655F-43BE-9165-F6C2CEC047B4","name":"arrow-bottom-right","codepoint":"F0043","aliases":["arrow-down-right"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"ABD34714-B566-4EDF-B876-93BFB6D254CB","name":"arrow-bottom-right-bold-outline","codepoint":"F09B9","aliases":["arrow-down-right-bold-outline"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"01AD77CD-8F92-4E32-A752-387203BC9FF8","name":"arrow-bottom-right-thick","codepoint":"F09BA","aliases":["arrow-down-right-thick","arrow-bottom-right-bold","arrow-down-right-bold"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"26479C31-47EF-4EDA-B11E-323B136B7A6B","name":"arrow-bottom-right-thin-circle-outline","codepoint":"F1595","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"86BB43B4-910B-4174-8455-661875054171","name":"arrow-collapse","codepoint":"F0615","aliases":["arrow-compress"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.6.50"},{"id":"54364780-8F31-4B23-8085-ABE21EA55926","name":"arrow-collapse-all","codepoint":"F0044","aliases":["arrow-compress-all"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9989309E-22E1-46F6-B710-6717D1C5EA11","name":"arrow-collapse-down","codepoint":"F0792","aliases":["arrow-compress-down"],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"56953ABE-D834-4DC6-A44B-87A3BF1181BA","name":"arrow-collapse-horizontal","codepoint":"F084C","aliases":[],"tags":["Arrow"],"author":"Google","version":"2.1.99"},{"id":"9F794864-D790-48F3-A8B4-31AEC3BB17FD","name":"arrow-collapse-left","codepoint":"F0793","aliases":["arrow-compress-left"],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"FFED25A5-FD40-4274-9EE3-6B26F5C03584","name":"arrow-collapse-right","codepoint":"F0794","aliases":["arrow-compress-right"],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"1E02D94D-6931-4CB8-8836-5276B076D811","name":"arrow-collapse-up","codepoint":"F0795","aliases":["arrow-compress-up"],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"1D7700E7-2963-479F-81E1-910E2566894F","name":"arrow-collapse-vertical","codepoint":"F084D","aliases":["compress"],"tags":["Arrow"],"author":"Google","version":"2.1.99"},{"id":"61D65F86-CEB6-4CCC-8B88-00A4D0AD37C4","name":"arrow-decision","codepoint":"F09BB","aliases":["proxy"],"tags":["Arrow"],"author":"Michael Richins","version":"2.5.94"},{"id":"B115DB5B-AAF9-4C39-BC44-9E573E3154A1","name":"arrow-decision-auto","codepoint":"F09BC","aliases":["proxy-auto"],"tags":[],"author":"Michael Richins","version":"2.5.94"},{"id":"FA34CDF8-9B5D-40D2-97D5-00F41438A185","name":"arrow-decision-auto-outline","codepoint":"F09BD","aliases":["proxy-auto-outline"],"tags":[],"author":"Michael Richins","version":"2.5.94"},{"id":"7731818A-2C14-4B22-8758-9C7604BA6F3B","name":"arrow-decision-outline","codepoint":"F09BE","aliases":["proxy-outline"],"tags":["Arrow"],"author":"Michael Richins","version":"2.5.94"},{"id":"3821BF79-5857-47BE-84E3-A100B7247535","name":"arrow-down","codepoint":"F0045","aliases":["arrow-downward","arrow-bottom"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CA8684F7-5654-4AE0-9840-9C3AD9611D19","name":"arrow-down-bold","codepoint":"F072E","aliases":["arrow-bottom-bold"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"545DF72E-705C-46AC-BABE-94F6C304CFAB","name":"arrow-down-bold-box","codepoint":"F072F","aliases":["arrow-bottom-bold-box"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"2D68AA5F-ACA1-45AA-873B-AD077377E698","name":"arrow-down-bold-box-outline","codepoint":"F0730","aliases":["arrow-bottom-bold-box-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"E4AFC38F-01B3-452D-BDD7-A08EA66D53FA","name":"arrow-down-bold-circle","codepoint":"F0047","aliases":["arrow-bottom-bold-circle"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1DA60E82-C1F0-449C-8157-7014A7C9E749","name":"arrow-down-bold-circle-outline","codepoint":"F0048","aliases":["arrow-bottom-bold-circle-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1F47DB52-28B0-40B7-836F-F6F2C58F2412","name":"arrow-down-bold-hexagon-outline","codepoint":"F0049","aliases":["arrow-bottom-bold-hexagon-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"517A69FA-E66C-469C-908F-E0CD723EBE8A","name":"arrow-down-bold-outline","codepoint":"F09BF","aliases":["arrow-bottom-bold-outline"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"04449961-F211-4FB7-BD87-EDA5F828B41D","name":"arrow-down-box","codepoint":"F06C0","aliases":["arrow-bottom-box"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.8.36"},{"id":"51D021A8-C3E1-477C-8BBF-DD4B84549515","name":"arrow-down-circle","codepoint":"F0CDB","aliases":["arrow-bottom-circle"],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"E7EF8487-25AE-4CD6-8D04-4F90C60B3DCC","name":"arrow-down-circle-outline","codepoint":"F0CDC","aliases":["arrow-bottom-circle-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"34BD0C0B-AF54-4BFC-A539-35D67612C4AC","name":"arrow-down-drop-circle","codepoint":"F004A","aliases":["arrow-drop-down-circle","arrow-bottom-drop-circle"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"65BE2EE5-23A5-49F8-A7A2-AEDD25C9C661","name":"arrow-down-drop-circle-outline","codepoint":"F004B","aliases":["arrow-bottom-drop-circle-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"E345145F-AD51-4B6F-8F7B-EC22C34E4E89","name":"arrow-down-thick","codepoint":"F0046","aliases":["arrow-bottom-thick","arrow-down-bold","arrow-bottom-bold"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6BDA2640-A009-416F-95F8-EE91CB931B66","name":"arrow-down-thin-circle-outline","codepoint":"F1599","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"F75C0670-7074-4756-BF30-7840D1C47E09","name":"arrow-expand","codepoint":"F0616","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.6.50"},{"id":"14842517-5BC4-49B6-86F2-8D6DC8870786","name":"arrow-expand-all","codepoint":"F004C","aliases":[],"tags":["Arrow","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2338FC6A-1234-4A1F-AF6D-CFD45C92A2DF","name":"arrow-expand-down","codepoint":"F0796","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"B48C3976-1304-4E32-9D69-0062A48018FB","name":"arrow-expand-horizontal","codepoint":"F084E","aliases":[],"tags":["Arrow"],"author":"Google","version":"2.1.99"},{"id":"FDF3C8E5-7AD6-4428-90EC-9426E56B5478","name":"arrow-expand-left","codepoint":"F0797","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"FF7885EC-2A34-4149-A4F8-626135606D7F","name":"arrow-expand-right","codepoint":"F0798","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"C13A62FF-DCC7-40DA-9326-C7FA77E4610F","name":"arrow-expand-up","codepoint":"F0799","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"2.0.46"},{"id":"3B6EC96B-24CB-4CCE-AE9F-AA1787987C63","name":"arrow-expand-vertical","codepoint":"F084F","aliases":[],"tags":["Arrow"],"author":"Google","version":"2.1.99"},{"id":"AE7BA87E-D5CF-415E-8641-ADE156760E93","name":"arrow-horizontal-lock","codepoint":"F115B","aliases":["scroll-horizontal-lock"],"tags":["Lock","Arrow"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"C21995A9-094F-4EA8-9127-BA0506B240A6","name":"arrow-left","codepoint":"F004D","aliases":["arrow-back"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"E990CF7B-A7D8-444E-99FE-24930ABF2FA6","name":"arrow-left-bold","codepoint":"F0731","aliases":[],"tags":["Arrow","Automotive"],"author":"Austin Andrews","version":"1.9.32"},{"id":"B7333E10-D6D6-4F86-A163-3A486C0B839D","name":"arrow-left-bold-box","codepoint":"F0732","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"E95F06DD-DD66-4CD1-AAAC-AAA870CE6AC7","name":"arrow-left-bold-box-outline","codepoint":"F0733","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"D40EF576-5116-4176-9F9D-C9E491517321","name":"arrow-left-bold-circle","codepoint":"F004F","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"E5ED912C-8075-477C-B62B-60184A436F2C","name":"arrow-left-bold-circle-outline","codepoint":"F0050","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5B274371-4B53-4E82-9CE3-42EADBDCCF92","name":"arrow-left-bold-hexagon-outline","codepoint":"F0051","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F88B9364-AE49-4AF6-A891-E20068064832","name":"arrow-left-bold-outline","codepoint":"F09C0","aliases":[],"tags":["Arrow","Automotive"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"67481609-631A-45C8-AB97-679B3D95F9FB","name":"arrow-left-box","codepoint":"F06C1","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.8.36"},{"id":"57F5D624-D5B0-4F19-AFAB-676F822C87DC","name":"arrow-left-circle","codepoint":"F0CDD","aliases":["arrow-back-circle"],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"DEE2CC7E-5349-49CE-9700-6EF0D935A2E6","name":"arrow-left-circle-outline","codepoint":"F0CDE","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"199C908D-09C4-47C6-968A-74582AC4AF26","name":"arrow-left-drop-circle","codepoint":"F0052","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"37B06F58-3BD0-413F-B86D-2EFD008B3D69","name":"arrow-left-drop-circle-outline","codepoint":"F0053","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"D6011A13-DCCB-4DF7-B5A8-335A404C6B71","name":"arrow-left-right","codepoint":"F0E73","aliases":[],"tags":["Arrow"],"author":"ginlime","version":"3.7.94"},{"id":"917B10C1-CFB6-4066-9977-0FA6DD835C0E","name":"arrow-left-right-bold","codepoint":"F0E74","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.7.94"},{"id":"341A3007-7214-4634-924D-1FFEA455AD5E","name":"arrow-left-right-bold-outline","codepoint":"F09C1","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"FA880DCB-AC6F-4C9C-9B6D-6E8236272C31","name":"arrow-left-thick","codepoint":"F004E","aliases":["arrow-left-bold"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B0495FDB-2123-4D72-9D15-F44ED6FBF8CD","name":"arrow-left-thin-circle-outline","codepoint":"F159A","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"05F25B05-A6D6-4863-8B21-6969E10329CF","name":"arrow-right","codepoint":"F0054","aliases":["arrow-forward"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"8C7A25B6-878E-4BDB-A5B7-2927257E1B7D","name":"arrow-right-bold","codepoint":"F0734","aliases":[],"tags":["Arrow","Automotive"],"author":"Austin Andrews","version":"1.9.32"},{"id":"7225998A-DEF1-40C6-A05C-FA4119A643D9","name":"arrow-right-bold-box","codepoint":"F0735","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"1830D607-FDD5-4CC1-8D74-2A92C16B9E51","name":"arrow-right-bold-box-outline","codepoint":"F0736","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"AF178779-F8E7-4F77-A9D1-A4675713C440","name":"arrow-right-bold-circle","codepoint":"F0056","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"8B60DF03-2440-4D73-98DE-A8666666864E","name":"arrow-right-bold-circle-outline","codepoint":"F0057","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1EAE1304-ED67-4607-A5C3-833B9CF7D943","name":"arrow-right-bold-hexagon-outline","codepoint":"F0058","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"86D895A6-8B2C-4757-A2CC-C506B402C2BB","name":"arrow-right-bold-outline","codepoint":"F09C2","aliases":[],"tags":["Arrow","Automotive"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"8BA08E5C-7ED5-49E2-BDDE-1F1425C9FE1A","name":"arrow-right-box","codepoint":"F06C2","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.8.36"},{"id":"DF8E13FB-5C26-4C43-A6DC-F01185A97E42","name":"arrow-right-circle","codepoint":"F0CDF","aliases":["arrow-forward-circle"],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"A0626F15-BC40-422F-B978-EEDFB5543961","name":"arrow-right-circle-outline","codepoint":"F0CE0","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"39AEA4FF-B65C-4368-B582-98108E3F9F06","name":"arrow-right-drop-circle","codepoint":"F0059","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1E7109A9-3178-4B5E-87A9-CD1054B38BE9","name":"arrow-right-drop-circle-outline","codepoint":"F005A","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9F7385FB-733C-4C1F-AC88-684BE98F381B","name":"arrow-right-thick","codepoint":"F0055","aliases":["arrow-right-bold"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5ADB8DD0-2F9D-4F1B-ABC9-093579E960A0","name":"arrow-right-thin-circle-outline","codepoint":"F1598","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"ED7981BC-0B25-4657-BB7C-FB14A3D91D99","name":"arrow-split-horizontal","codepoint":"F093B","aliases":["resize-vertical","resize"],"tags":["Arrow"],"author":"Michael Richins","version":"2.4.85"},{"id":"7234382E-CB5D-4EB3-8BA2-0C50BC2171DB","name":"arrow-split-vertical","codepoint":"F093C","aliases":["resize-horizontal","resize"],"tags":["Arrow"],"author":"Michael Richins","version":"2.4.85"},{"id":"DD1AC44D-81B8-42EF-8714-7E7D29F2BC3F","name":"arrow-top-left","codepoint":"F005B","aliases":["arrow-up-left"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4D43349E-EF13-4BB1-9684-0CEDE55DE9DE","name":"arrow-top-left-bold-outline","codepoint":"F09C3","aliases":["arrow-up-left-bold-outline"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"3F3EFD86-07D4-495B-9E20-66826FF54E1D","name":"arrow-top-left-bottom-right","codepoint":"F0E75","aliases":[],"tags":["Arrow"],"author":"ginlime","version":"3.7.94"},{"id":"D6AFEFE4-0E22-4197-B094-53E9528FFF0A","name":"arrow-top-left-bottom-right-bold","codepoint":"F0E76","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.7.94"},{"id":"D1D2B0DA-2EAD-451B-A9D9-B4C52E16FEDC","name":"arrow-top-left-thick","codepoint":"F09C4","aliases":["arrow-up-left-thick","arrow-top-left-bold","arrow-up-left-bold"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"A3FB09A5-28B7-4A90-AA48-E6D0AA5031EB","name":"arrow-top-left-thin-circle-outline","codepoint":"F1593","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"27AB7B33-64F3-49A5-8082-CA7B465152A9","name":"arrow-top-right","codepoint":"F005C","aliases":["arrow-up-right"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"D6A6FF61-6566-4C1D-BBCC-30E00B0655DD","name":"arrow-top-right-bold-outline","codepoint":"F09C5","aliases":["arrow-up-right-bold-outline"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"6B94201F-4E9F-486E-B3A6-484A6C266E55","name":"arrow-top-right-bottom-left","codepoint":"F0E77","aliases":[],"tags":["Arrow"],"author":"ginlime","version":"3.7.94"},{"id":"815927F0-0D89-4D10-B336-2B918B321994","name":"arrow-top-right-bottom-left-bold","codepoint":"F0E78","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.7.94"},{"id":"37C83BAE-6330-4E45-A976-3E2642997035","name":"arrow-top-right-thick","codepoint":"F09C6","aliases":["arrow-up-right-thick","arrow-top-right-bold","arrow-up-right-bold"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"83068FC2-BF4B-4B99-956D-46EC07F6738F","name":"arrow-top-right-thin-circle-outline","codepoint":"F1594","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"3AF49B97-A909-4961-9FBB-82C60D7CC773","name":"arrow-up","codepoint":"F005D","aliases":["arrow-upward","arrow-top"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"36199A40-CCCB-44B9-A6B0-73F7315E5716","name":"arrow-up-bold","codepoint":"F0737","aliases":["arrow-top-bold"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"062452EE-7669-4C36-85E6-A85BBA735348","name":"arrow-up-bold-box","codepoint":"F0738","aliases":["arrow-top-bold-box"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"5386BD1B-8959-4312-8739-5B08021F319D","name":"arrow-up-bold-box-outline","codepoint":"F0739","aliases":["arrow-top-bold-box-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.9.32"},{"id":"D6719240-C87E-4185-B694-1EA5FFC94F4E","name":"arrow-up-bold-circle","codepoint":"F005F","aliases":["arrow-top-bold-circle"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3337B267-94EC-426B-ABC9-5842F75B13B1","name":"arrow-up-bold-circle-outline","codepoint":"F0060","aliases":["arrow-top-bold-circle-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"7C3BD067-49AB-41C8-9091-FBD2D533045E","name":"arrow-up-bold-hexagon-outline","codepoint":"F0061","aliases":["arrow-top-bold-hexagon-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"664AA4B5-DD9C-40AD-A69E-3CD314025AD3","name":"arrow-up-bold-outline","codepoint":"F09C7","aliases":["arrow-top-bold-outline"],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"82958DF7-5F5F-4470-BFB4-4389937B4D29","name":"arrow-up-box","codepoint":"F06C3","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.8.36"},{"id":"208441AD-DDC5-4EC8-A48D-746DB5AE3CFD","name":"arrow-up-circle","codepoint":"F0CE1","aliases":["arrow-top-circle"],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"D41B6302-5A2E-4B55-93A4-E30E07F761C1","name":"arrow-up-circle-outline","codepoint":"F0CE2","aliases":["arrow-top-circle-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"3.3.92"},{"id":"DF1BCEA6-C202-477E-A3CF-2054D93E5F2A","name":"arrow-up-down","codepoint":"F0E79","aliases":[],"tags":["Arrow"],"author":"ginlime","version":"3.7.94"},{"id":"478A5E36-5EC0-4DC5-B663-AFB1F84C83A9","name":"arrow-up-down-bold","codepoint":"F0E7A","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.7.94"},{"id":"1F1BE05B-E67A-4646-A8B3-08423BD58673","name":"arrow-up-down-bold-outline","codepoint":"F09C8","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"73B211DB-05CF-4025-B035-AD03454C47A6","name":"arrow-up-drop-circle","codepoint":"F0062","aliases":["arrow-top-drop-circle"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"42277E7D-D87A-4DE9-982B-37E6A8AE4E70","name":"arrow-up-drop-circle-outline","codepoint":"F0063","aliases":["arrow-top-drop-circle-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4EDBF232-461F-4F4C-82BB-64A89BA08405","name":"arrow-up-thick","codepoint":"F005E","aliases":["arrow-top-thick","arrow-up-bold","arrow-top-bold"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9733F983-7DD1-4230-B792-413D46E0B422","name":"arrow-up-thin-circle-outline","codepoint":"F1597","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.5.55"},{"id":"8B00DF03-0754-4D7F-B0C9-8CF21D42989F","name":"arrow-vertical-lock","codepoint":"F115C","aliases":["scroll-vertical-lock"],"tags":["Lock","Arrow"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"548CCDA7-0E99-4568-9997-2ECFD33392BB","name":"artstation","codepoint":"F0B5B","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"3.0.39"},{"id":"AE294E7D-3AC0-4C7D-AFAF-8DDA0AB5BF52","name":"aspect-ratio","codepoint":"F0A24","aliases":[],"tags":[],"author":"Google","version":"2.6.95"},{"id":"0C612FE5-D7CC-44F3-945A-4BD15A7E39BA","name":"assistant","codepoint":"F0064","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"E8C373FE-4258-4341-B52A-E33D9A484968","name":"asterisk","codepoint":"F06C4","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"9FC24609-9C8B-4DBA-A473-F5EFAFCC90DF","name":"at","codepoint":"F0065","aliases":["alternate-email"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"25806C84-E41E-43A7-93AF-EA4ABACA982E","name":"atlassian","codepoint":"F0804","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.19"},{"id":"A35ABE08-C956-4177-935C-1E1FB835772D","name":"atm","codepoint":"F0D47","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"C366C8B8-44FB-481E-88F2-AE0C3B1E8C74","name":"atom","codepoint":"F0768","aliases":[],"tags":["Science"],"author":"Roberto Graham","version":"1.9.32"},{"id":"AD030F55-7B31-45F9-94F7-738CC84B2009","name":"atom-variant","codepoint":"F0E7B","aliases":["orbit"],"tags":["Science"],"author":"Austin Andrews","version":"3.7.94"},{"id":"E3C20B38-A6D3-4EF0-817D-863B25E555BA","name":"attachment","codepoint":"F0066","aliases":["paperclip-horizontal"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"79CBF0E5-365C-466B-B162-2EBD1531F182","name":"audio-video","codepoint":"F093D","aliases":["av-receiver"],"tags":["Home Automation"],"author":"Michael Richins","version":"2.4.85"},{"id":"09FB4D77-A411-4CBF-9E88-21807D804CB3","name":"audio-video-off","codepoint":"F11B6","aliases":["av-receiver-off"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"FC29D627-D661-4F31-9BEC-2F4BE355DFE7","name":"augmented-reality","codepoint":"F0850","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.1.99"},{"id":"2EAC4201-2055-4755-84A9-958FDDF7732B","name":"auto-download","codepoint":"F137E","aliases":[],"tags":[],"author":"Michael Richins","version":"4.9.95"},{"id":"FAAFAACC-4E0D-4688-B583-FC88A782A9B6","name":"auto-fix","codepoint":"F0068","aliases":["magic","wand","auto-fix-high"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"3DEAD47C-90B3-485E-943C-CE2D70C85154","name":"auto-upload","codepoint":"F0069","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"00598C19-1255-479D-914A-1AADFDBC4868","name":"autorenew","codepoint":"F006A","aliases":["clockwise-arrows","circular-arrows","circle-arrows","sync"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"A118E3CD-FF18-48FD-B26C-B4A48641E4C5","name":"av-timer","codepoint":"F006B","aliases":[],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"851E2C6C-16AE-4C0F-B99A-AB6BE37C4F55","name":"aws","codepoint":"F0E0F","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"3.6.95"},{"id":"B6119C36-82C4-4C6F-98D5-B339A73C837E","name":"axe","codepoint":"F08C8","aliases":[],"tags":["Hardware \/ Tools"],"author":"Nick","version":"2.3.50"},{"id":"78DCA9F5-C22C-407A-ABC1-15510C2F977A","name":"axis","codepoint":"F0D48","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.4.93"},{"id":"3D0AC996-0A31-4D68-AD38-A8507967B269","name":"axis-arrow","codepoint":"F0D49","aliases":["accelerometer","gyro"],"tags":["Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"FCB87FD8-4522-47AF-AC10-2DF8A59F632D","name":"axis-arrow-info","codepoint":"F140E","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"5.1.45"},{"id":"1EE0C03F-9BCA-4AB4-92C3-209EA92FA54F","name":"axis-arrow-lock","codepoint":"F0D4A","aliases":[],"tags":["Lock","Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"D2BAA555-22F2-447F-89F1-95D11AE09126","name":"axis-lock","codepoint":"F0D4B","aliases":[],"tags":["Lock"],"author":"Austin Andrews","version":"3.4.93"},{"id":"933B83F8-4F97-436F-89E0-574315FF1E2E","name":"axis-x-arrow","codepoint":"F0D4C","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"E113D418-BFDB-44FE-A809-61072FEAEF39","name":"axis-x-arrow-lock","codepoint":"F0D4D","aliases":[],"tags":["Lock","Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"7EE23AE2-F41C-4CDA-9B52-B8A432CA7E20","name":"axis-x-rotate-clockwise","codepoint":"F0D4E","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.4.93"},{"id":"B500E4B0-397A-4BA2-926F-5B8BDF10632F","name":"axis-x-rotate-counterclockwise","codepoint":"F0D4F","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.4.93"},{"id":"6620039A-2405-48BB-9619-143BAF7CF8DD","name":"axis-x-y-arrow-lock","codepoint":"F0D50","aliases":[],"tags":["Lock","Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"F12198D8-62C4-4E6A-A201-5D33DB690736","name":"axis-y-arrow","codepoint":"F0D51","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"4C02BFA9-8AF8-4FC3-AAC7-F4D4AEF9BE06","name":"axis-y-arrow-lock","codepoint":"F0D52","aliases":[],"tags":["Lock","Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"6A8E42CA-4236-496C-9C0A-81FADCDA6506","name":"axis-y-rotate-clockwise","codepoint":"F0D53","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.4.93"},{"id":"70E8F92A-9AAA-44CB-AB76-527463DE2D06","name":"axis-y-rotate-counterclockwise","codepoint":"F0D54","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.4.93"},{"id":"2BAA5FEA-713E-44D6-A44F-B36C92BB7F60","name":"axis-z-arrow","codepoint":"F0D55","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"870F3E6C-6957-498E-AC62-BAE40C9FA7EA","name":"axis-z-arrow-lock","codepoint":"F0D56","aliases":[],"tags":["Lock","Arrow"],"author":"Austin Andrews","version":"3.4.93"},{"id":"D3A59461-2A63-4C62-B528-564252BBAB29","name":"axis-z-rotate-clockwise","codepoint":"F0D57","aliases":["vertical-rotate-clockwise"],"tags":[],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"DB0819A2-5E99-483B-BBC8-AEAD0DE9D196","name":"axis-z-rotate-counterclockwise","codepoint":"F0D58","aliases":["vertical-rotate-counterclockwise"],"tags":[],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"3F7EAFAC-7A39-4051-B58D-2CBA6687110C","name":"babel","codepoint":"F0A25","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.6.95"},{"id":"2CD51EFC-51B6-4323-B1EA-429EB58BFF7F","name":"baby","codepoint":"F006C","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"1.5.54"},{"id":"B3497A75-EE3B-4A8A-8F27-39A458423659","name":"baby-bottle","codepoint":"F0F39","aliases":[],"tags":["People \/ Family"],"author":"Michael Richins","version":"3.9.97"},{"id":"5E06191D-D9AC-412E-B21B-C3AF1F28D76F","name":"baby-bottle-outline","codepoint":"F0F3A","aliases":[],"tags":["People \/ Family"],"author":"Michael Richins","version":"3.9.97"},{"id":"46AF3844-1F3F-43B5-A93B-424EC83BCADB","name":"baby-buggy","codepoint":"F13E0","aliases":["stroller","pram","carriage"],"tags":["People \/ Family"],"author":"Moma Design Studio","version":"5.1.45"},{"id":"FA711E97-6083-45AA-9C92-FCCDABC57D37","name":"baby-carriage","codepoint":"F068F","aliases":["child-friendly","stroller","pram","buggy"],"tags":["People \/ Family"],"author":"Google","version":"1.7.12"},{"id":"D495FD84-4476-4E2E-B099-4E0A07AA9D90","name":"baby-carriage-off","codepoint":"F0FA0","aliases":["child-friendly-off","stroller-off","pram-off","buggy-off"],"tags":["People \/ Family"],"author":"Michael Richins","version":"4.0.96"},{"id":"78A84DE8-3ED5-4F81-991B-8EAE452908D3","name":"baby-face","codepoint":"F0E7C","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"3.7.94"},{"id":"24C6F5BD-6965-4CDB-B3AC-02CA82F24216","name":"baby-face-outline","codepoint":"F0E7D","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"3.7.94"},{"id":"5A5BC824-220B-4998-883A-0E57FB2AB75F","name":"backburger","codepoint":"F006D","aliases":["hamburger-menu-back"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"2AAC06E6-8ABD-418B-B9A4-8554B62D7C04","name":"backspace","codepoint":"F006E","aliases":["erase","clear"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"7CD351DA-560B-42B5-86F3-7F782EA70FEA","name":"backspace-outline","codepoint":"F0B5C","aliases":["erase-outline","clear-outline"],"tags":[],"author":"Google","version":"3.0.39"},{"id":"49AA61F3-2E3D-4EEA-BFB1-32D59C6906F0","name":"backspace-reverse","codepoint":"F0E7E","aliases":["clear-reverse","erase-reverse"],"tags":[],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"287700E2-130D-484B-B56D-0162BE6DEEEE","name":"backspace-reverse-outline","codepoint":"F0E7F","aliases":["clear-reverse-outline","erase-reverse-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"36F8C2B4-C82C-4546-AFFC-601ECA54A603","name":"backup-restore","codepoint":"F006F","aliases":["settings-backup-restore"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"059B29E7-34BA-402E-B06A-B9EBF021FA8B","name":"bacteria","codepoint":"F0ED5","aliases":[],"tags":["Science","Medical \/ Hospital"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"548C05E8-98DD-4D5C-8308-FA997A2C9016","name":"bacteria-outline","codepoint":"F0ED6","aliases":[],"tags":["Science","Medical \/ Hospital"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"AE2E869B-B420-4505-9EE0-EE3751478D64","name":"badge-account","codepoint":"F0DA7","aliases":["user-badge","person-badge"],"tags":["Account \/ User"],"author":"Michael Richins","version":"3.5.94"},{"id":"610A9983-6737-4876-B1E2-09C22D3888D9","name":"badge-account-alert","codepoint":"F0DA8","aliases":["user-badge-alert","person-badge-alert","account-badge-warning","user-badge-warning","person-badge-warning"],"tags":["Account \/ User","Alert \/ Error"],"author":"Michael Richins","version":"3.5.94"},{"id":"3F5E356C-AD32-46E2-835F-ECFC043C73AD","name":"badge-account-alert-outline","codepoint":"F0DA9","aliases":["user-badge-alert-outline","person-badge-alert-outline","account-badge-warning-outline","user-badge-warning-outline","person-badge-warning-outline"],"tags":["Account \/ User","Alert \/ Error"],"author":"Michael Richins","version":"3.5.94"},{"id":"99CC4A89-E39E-460D-B199-227045E4A57D","name":"badge-account-horizontal","codepoint":"F0E0D","aliases":[],"tags":["Account \/ User"],"author":"Google","version":"3.6.95"},{"id":"089F503E-00BF-4103-9475-B0E3955CE09D","name":"badge-account-horizontal-outline","codepoint":"F0E0E","aliases":[],"tags":["Account \/ User"],"author":"Google","version":"3.6.95"},{"id":"37856000-4337-42D9-B273-9C9656E9CFCD","name":"badge-account-outline","codepoint":"F0DAA","aliases":["user-badge-outline","person-badge-outline"],"tags":["Account \/ User"],"author":"Michael Richins","version":"3.5.94"},{"id":"AF478988-12FA-460A-AE5B-01536D6D5B97","name":"badminton","codepoint":"F0851","aliases":["shuttlecock"],"tags":["Sport"],"author":"Nick","version":"2.1.99"},{"id":"0B935A7D-05EB-4687-8E4B-BC075AA2FA85","name":"bag-carry-on","codepoint":"F0F3B","aliases":["carry-on-luggage"],"tags":["Transportation + Flying"],"author":"Google","version":"3.9.97"},{"id":"57DD596E-AFB6-46D2-8415-2DED40839B11","name":"bag-carry-on-check","codepoint":"F0D65","aliases":["carry-on-bag-tick","carry-on-bag-check"],"tags":["Transportation + Flying"],"author":"Google","version":"3.4.93"},{"id":"F11D5411-E08A-483D-B04C-A75B523C717C","name":"bag-carry-on-off","codepoint":"F0F3C","aliases":["carry-on-luggage-off"],"tags":["Transportation + Flying"],"author":"Google","version":"3.9.97"},{"id":"2D40D813-D1C8-4190-8010-012467F9E48F","name":"bag-checked","codepoint":"F0F3D","aliases":["luggage"],"tags":["Transportation + Flying"],"author":"Google","version":"3.9.97"},{"id":"FB55F27F-9D0D-4EA7-ACD7-22C85E799248","name":"bag-personal","codepoint":"F0E10","aliases":["backpack"],"tags":["Transportation + Flying"],"author":"Michael Richins","version":"3.6.95"},{"id":"9B14800C-E104-4A89-9773-B220CA30A403","name":"bag-personal-off","codepoint":"F0E11","aliases":["backpack-off"],"tags":["Transportation + Flying"],"author":"Michael Richins","version":"3.6.95"},{"id":"822DE3FA-6BBB-4DF9-B586-A63CA5162EF1","name":"bag-personal-off-outline","codepoint":"F0E12","aliases":["backpack-off-outline"],"tags":["Transportation + Flying"],"author":"Michael Richins","version":"3.6.95"},{"id":"E95F21EF-993D-462F-BA6E-21F7665BC34C","name":"bag-personal-outline","codepoint":"F0E13","aliases":["backpack-outline"],"tags":["Transportation + Flying"],"author":"Michael Richins","version":"3.6.95"},{"id":"0DBD5DC4-4D5B-48B9-951C-249BB05C3E7E","name":"bag-suitcase","codepoint":"F158B","aliases":[],"tags":["Transportation + Flying"],"author":"Google","version":"5.5.55"},{"id":"44E2AE1A-79ED-43C0-9A29-B18DFCB9B915","name":"bag-suitcase-off","codepoint":"F158D","aliases":[],"tags":["Transportation + Flying"],"author":"Google","version":"5.5.55"},{"id":"E89335F8-3A20-489F-A974-FF591F8A147E","name":"bag-suitcase-off-outline","codepoint":"F158E","aliases":[],"tags":["Transportation + Flying"],"author":"Google","version":"5.5.55"},{"id":"4977C376-1E6B-41F4-92F4-3410E9699F2D","name":"bag-suitcase-outline","codepoint":"F158C","aliases":[],"tags":["Transportation + Flying"],"author":"Google","version":"5.5.55"},{"id":"B6469241-E347-42D8-BF71-8DF29F1CA897","name":"baguette","codepoint":"F0F3E","aliases":["bread","bakery","french-baguette","loaf"],"tags":["Food \/ Drink"],"author":"Nick","version":"3.9.97"},{"id":"31D1D255-3E73-41A8-93E2-12DF16DA0C40","name":"balloon","codepoint":"F0A26","aliases":["party-balloon"],"tags":["Holiday"],"author":"Michael Richins","version":"2.6.95"},{"id":"27AB71F3-1EFD-484F-8E63-C1E4C694E392","name":"ballot","codepoint":"F09C9","aliases":["vote"],"tags":[],"author":"Google","version":"2.5.94"},{"id":"B9CDE0FA-F96A-413C-9BFD-DAB4DBC3DDE3","name":"ballot-outline","codepoint":"F09CA","aliases":["vote-outline"],"tags":[],"author":"Google","version":"2.5.94"},{"id":"D0C76005-3272-4189-A061-E344D9BAB0C6","name":"ballot-recount","codepoint":"F0C39","aliases":["vote-recount"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"0B0AD153-4696-4ED2-9AE1-309926B23287","name":"ballot-recount-outline","codepoint":"F0C3A","aliases":["vote-recount-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"6CDF527A-26C1-4175-A56B-5D65FD5E46E2","name":"bandage","codepoint":"F0DAF","aliases":["band-aid","plaster"],"tags":[],"author":"Google","version":"3.5.94"},{"id":"38278159-AC2C-433A-9335-95B05C1F6F56","name":"bandcamp","codepoint":"F0675","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.7.12"},{"id":"FE08919F-CFFC-4A25-994C-CEDEB299908B","name":"bank","codepoint":"F0070","aliases":["account-balance","museum"],"tags":["Banking","Places"],"author":"Google","version":"1.5.54"},{"id":"1642BE6C-C1B6-49EA-833D-BB5E20BC1C69","name":"bank-check","codepoint":"F1655","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"DAC4946E-1A07-44B4-977F-E51D740DA5FB","name":"bank-minus","codepoint":"F0DB0","aliases":[],"tags":["Banking"],"author":"Austin Andrews","version":"3.5.94"},{"id":"9379EA96-CBC9-4A84-BF1A-18A80E7BDBE2","name":"bank-off","codepoint":"F1656","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"4590ED1A-1E67-42F4-8D4B-E2B39E5EFC63","name":"bank-off-outline","codepoint":"F1657","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"952ADDE3-5EC1-4AB1-80F1-9FA7AA14AD74","name":"bank-outline","codepoint":"F0E80","aliases":["museum-outline"],"tags":["Banking"],"author":"Google","version":"3.7.94"},{"id":"DCB74822-6C93-473B-88B4-1818CFDE2B69","name":"bank-plus","codepoint":"F0DB1","aliases":["bank-add"],"tags":["Banking"],"author":"Contributors","version":"3.5.94"},{"id":"14C747D0-C356-403D-862F-09A2F30276E7","name":"bank-remove","codepoint":"F0DB2","aliases":[],"tags":["Banking"],"author":"Austin Andrews","version":"3.5.94"},{"id":"5692748F-52FC-41F9-97B2-D0F251F4619D","name":"bank-transfer","codepoint":"F0A27","aliases":[],"tags":["Banking"],"author":"SarinManS","version":"2.6.95"},{"id":"F8E6FE4D-8CE9-41A5-A26A-FEC3A572DA3F","name":"bank-transfer-in","codepoint":"F0A28","aliases":[],"tags":["Banking"],"author":"SarinManS","version":"2.6.95"},{"id":"02A1C3B5-91EE-43B9-9BDB-3EF67F540722","name":"bank-transfer-out","codepoint":"F0A29","aliases":[],"tags":["Banking"],"author":"SarinManS","version":"2.6.95"},{"id":"5231CD58-9C30-40A8-993C-A24C6B70F6B8","name":"barcode","codepoint":"F0071","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"AF7144E7-5004-4685-A100-78425F035F51","name":"barcode-off","codepoint":"F1236","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"40365CB0-4664-4648-8C51-2E6E20A0D096","name":"barcode-scan","codepoint":"F0072","aliases":["barcode-scanner"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"5126A5A7-ECBC-49FC-BBC6-1703DCACF5E4","name":"barley","codepoint":"F0073","aliases":["grain","wheat","gluten"],"tags":["Agriculture","Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6627D247-B25C-48F3-925D-BF282D7B4295","name":"barley-off","codepoint":"F0B5D","aliases":["gluten-free","grain-off","wheat-off"],"tags":["Agriculture"],"author":"Simran","version":"3.0.39"},{"id":"678BDE48-30CE-4897-BA06-9991001FA842","name":"barn","codepoint":"F0B5E","aliases":["farm"],"tags":[],"author":"SarinManS","version":"3.0.39"},{"id":"CD3098D2-892F-49F5-9FA7-1A5FDC53A15C","name":"barrel","codepoint":"F0074","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"EDAC5CB7-39B3-4DAD-89ED-38D7EA914211","name":"baseball","codepoint":"F0852","aliases":[],"tags":["Sport"],"author":"Nick","version":"2.1.99"},{"id":"20D31EB1-5C7F-4597-9B42-80E08E0192F8","name":"baseball-bat","codepoint":"F0853","aliases":[],"tags":["Sport"],"author":"Nick","version":"2.1.99"},{"id":"360632A2-1E37-4A89-BC24-166CF4824357","name":"baseball-diamond","codepoint":"F15EC","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"55F744E2-2059-41A4-B909-748029558069","name":"baseball-diamond-outline","codepoint":"F15ED","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"53BA6F8E-FC99-4B2A-8497-EA732C1880E4","name":"bash","codepoint":"F1183","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Richins","version":"4.4.95"},{"id":"4E334FE9-DF93-469A-B7D7-AC88BBF25D84","name":"basket","codepoint":"F0076","aliases":["shopping-basket"],"tags":["Shopping"],"author":"Google","version":"1.5.54"},{"id":"9B7DC550-62F9-4FB0-9B21-0379AA925A19","name":"basket-fill","codepoint":"F0077","aliases":[],"tags":["Shopping"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C41B2071-6BBF-458A-B73A-409D231A9F4D","name":"basket-minus","codepoint":"F1523","aliases":["shopping-basket-minus"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"8F4899A8-07F0-4C00-90EE-1509BE7A0D4C","name":"basket-minus-outline","codepoint":"F1524","aliases":["shopping-basket-minus-outline"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"FC2C74AA-57B1-4E13-A499-AA81CBE6670A","name":"basket-off","codepoint":"F1525","aliases":["shopping-basket-off"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"2D28FB7D-8AEA-4ED6-BB7D-DA76EC3DA4EB","name":"basket-off-outline","codepoint":"F1526","aliases":["shopping-basket-off-outline"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"A9AC5A33-FD7D-49C8-9C5E-C41335F6E833","name":"basket-outline","codepoint":"F1181","aliases":["shopping-basket-outline"],"tags":["Shopping"],"author":"Google","version":"4.4.95"},{"id":"3B02F0C6-F80B-479B-ABA7-CFBDBA843EB4","name":"basket-plus","codepoint":"F1527","aliases":["shopping-basket-plus"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"DC1E93FF-94C4-4B14-9152-ADDE374A44BB","name":"basket-plus-outline","codepoint":"F1528","aliases":["shopping-basket-plus-outline"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"C730C431-5377-4B0E-933B-5307E736B75A","name":"basket-remove","codepoint":"F1529","aliases":["shopping-basket-remove"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"8DB42CB2-5A41-489E-BC04-1DFADF917DE6","name":"basket-remove-outline","codepoint":"F152A","aliases":["shopping-basket-remove-outline"],"tags":["Shopping"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"D46B98B3-4045-4EAD-A26E-659195B5CC65","name":"basket-unfill","codepoint":"F0078","aliases":[],"tags":["Shopping"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FD797202-9EF1-407E-A290-97C014B8F37E","name":"basketball","codepoint":"F0806","aliases":["youtube-sports"],"tags":["Sport"],"author":"Google","version":"2.1.19"},{"id":"7792E2EB-0A99-44CF-AEBE-6683490594B0","name":"basketball-hoop","codepoint":"F0C3B","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"3.2.89"},{"id":"3310ED1D-3E70-48C0-AE7B-14BB42E0CD16","name":"basketball-hoop-outline","codepoint":"F0C3C","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"3.2.89"},{"id":"06925257-791B-4F7F-9A8F-A2D958EE8784","name":"bat","codepoint":"F0B5F","aliases":[],"tags":["Holiday"],"author":"Austin Andrews","version":"3.0.39"},{"id":"C12D919F-7D0D-4355-8109-912BA37154B5","name":"battery","codepoint":"F0079","aliases":["battery-full","battery-std","battery-100"],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"D753B56C-E806-4F17-B2A0-EBC4B4B78D19","name":"battery-10","codepoint":"F007A","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"9C8DAC10-97C6-476E-8122-25D7709F7AF6","name":"battery-10-bluetooth","codepoint":"F093E","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"95AEB324-9D57-4D27-B463-0C8077C04E24","name":"battery-20","codepoint":"F007B","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"9BA1E9FB-BB6A-447E-9F35-615CCC81CD81","name":"battery-20-bluetooth","codepoint":"F093F","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"970E1F42-4594-42CD-BB4E-6F5CBDBF5D21","name":"battery-30","codepoint":"F007C","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"6128BD10-A4CD-440E-BF98-151777783110","name":"battery-30-bluetooth","codepoint":"F0940","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"EE290FAF-A1D6-4A0D-8BBA-8DD2455AFB82","name":"battery-40","codepoint":"F007D","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"058D5094-AB60-4412-8C71-6CF4A56784A6","name":"battery-40-bluetooth","codepoint":"F0941","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"A79598F9-7FDF-46A2-9F8D-1DBD6BAB1A1D","name":"battery-50","codepoint":"F007E","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"313BE145-A7FB-4620-915C-4B2298C70EA1","name":"battery-50-bluetooth","codepoint":"F0942","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"B6EB700B-9288-474C-9A5C-C269680BFC5F","name":"battery-60","codepoint":"F007F","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"B422BB57-AC2D-43C2-B7A0-67160D90519E","name":"battery-60-bluetooth","codepoint":"F0943","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"5DC968CB-1DC2-42B1-96E2-80AC6B23BB9C","name":"battery-70","codepoint":"F0080","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"426481A7-5387-4385-9D2D-BEB1BCF5900D","name":"battery-70-bluetooth","codepoint":"F0944","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"54485D0C-49B3-424D-8283-4CE90E16F88D","name":"battery-80","codepoint":"F0081","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"176EE56B-73A9-44C7-94FF-90C11A48127E","name":"battery-80-bluetooth","codepoint":"F0945","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"58205285-7EAA-400A-A8E5-A9373E7D986A","name":"battery-90","codepoint":"F0082","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"AEB32E6B-7E3D-4C3A-AE1A-96C63868E208","name":"battery-90-bluetooth","codepoint":"F0946","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"ABFAD078-0E10-4293-94AD-16871B75E51F","name":"battery-alert","codepoint":"F0083","aliases":["battery-warning"],"tags":["Battery","Home Automation","Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"7C1C81FB-9E38-4220-B225-460056043383","name":"battery-alert-bluetooth","codepoint":"F0947","aliases":["battery-warning-bluetooth"],"tags":["Alert \/ Error","Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"DD0191F8-8AE0-4D80-A29C-AB7451DAE464","name":"battery-alert-variant","codepoint":"F10CC","aliases":[],"tags":["Battery","Alert \/ Error"],"author":"Austin Andrews","version":"4.3.95"},{"id":"C384D39D-C672-454D-964E-8AEF06C2381F","name":"battery-alert-variant-outline","codepoint":"F10CD","aliases":[],"tags":["Battery","Alert \/ Error"],"author":"Austin Andrews","version":"4.3.95"},{"id":"3DB7EA89-8F0C-40DA-B45A-E5B588F2CC01","name":"battery-bluetooth","codepoint":"F0948","aliases":["battery-bluetooth-100","battery-bluetooth-full"],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"910BCFA6-ED67-48A5-97EB-BA61969629E9","name":"battery-bluetooth-variant","codepoint":"F0949","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"F365ACF3-9453-4516-B592-AECD72AB7433","name":"battery-charging","codepoint":"F0084","aliases":["battery-charging-full"],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"EBDD7C45-CE9F-4503-9CE4-0682E4E8E6BF","name":"battery-charging-10","codepoint":"F089C","aliases":[],"tags":["Automotive","Battery"],"author":"Google","version":"2.2.43"},{"id":"C1379E5C-2335-4C37-9A73-EE54D6747512","name":"battery-charging-100","codepoint":"F0085","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"3E25E8BE-5097-4414-A7E4-9CDF02CD4F84","name":"battery-charging-20","codepoint":"F0086","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"04D00269-7E8F-40D1-BFC4-36A01720260B","name":"battery-charging-30","codepoint":"F0087","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"D40803B3-43CB-4680-A7BD-56CC83ED54B8","name":"battery-charging-40","codepoint":"F0088","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"1681D3BD-4990-4571-87B0-1C846DC8D600","name":"battery-charging-50","codepoint":"F089D","aliases":[],"tags":["Automotive","Battery"],"author":"Google","version":"2.2.43"},{"id":"23E8809B-FB62-4573-83CF-9C33E980FD41","name":"battery-charging-60","codepoint":"F0089","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"C8C75ED1-4B80-42A7-B590-DA3BE7567E86","name":"battery-charging-70","codepoint":"F089E","aliases":[],"tags":["Automotive","Battery"],"author":"Google","version":"2.2.43"},{"id":"20455031-CCDD-40F8-A7A4-5E1F9E55F20E","name":"battery-charging-80","codepoint":"F008A","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"0EC45F7B-7A0A-43AD-ABD3-10E4209659C0","name":"battery-charging-90","codepoint":"F008B","aliases":[],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"2BD37CBE-629C-41E8-8631-CD438C1E7704","name":"battery-charging-high","codepoint":"F12A6","aliases":[],"tags":["Battery"],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"C0158CBD-1F8D-491B-9825-9DB96D901908","name":"battery-charging-low","codepoint":"F12A4","aliases":[],"tags":["Battery"],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"FD7F7486-1E30-44A5-A4B2-C908372835CD","name":"battery-charging-medium","codepoint":"F12A5","aliases":[],"tags":["Battery"],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"A057A8D0-A442-4948-B2BF-63CECE073AF5","name":"battery-charging-outline","codepoint":"F089F","aliases":[],"tags":["Automotive","Battery"],"author":"Google","version":"2.2.43"},{"id":"60EEA5B6-8070-482D-ABE3-54A9D2A80875","name":"battery-charging-wireless","codepoint":"F0807","aliases":["battery-charging-wireless-full","battery-charging-wireless-100"],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"5D2990D5-D3D4-4E8F-AED8-B90CE6164068","name":"battery-charging-wireless-10","codepoint":"F0808","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"5C194C6F-8CFE-4F1A-AFD3-11D7E8CB89B4","name":"battery-charging-wireless-20","codepoint":"F0809","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"567818F9-23C0-41C4-A3BD-2BA37F8BFF29","name":"battery-charging-wireless-30","codepoint":"F080A","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"1ABBC4EA-32D6-4FBA-AA00-E19707123AE5","name":"battery-charging-wireless-40","codepoint":"F080B","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"9BC0DBFF-A3F6-4061-B6E1-685880D6B653","name":"battery-charging-wireless-50","codepoint":"F080C","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"F09D15A6-1E87-488C-9F75-24EC677E72FF","name":"battery-charging-wireless-60","codepoint":"F080D","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"45966E8F-2801-4ED6-970F-12D9FD6C6290","name":"battery-charging-wireless-70","codepoint":"F080E","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"EB5E0801-60FA-4DD3-8709-2A6F0AC9C3ED","name":"battery-charging-wireless-80","codepoint":"F080F","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"E8C0AC60-D7AB-4FA3-9596-CE002E798180","name":"battery-charging-wireless-90","codepoint":"F0810","aliases":[],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"F835E187-444F-43B8-A057-9915F1388A87","name":"battery-charging-wireless-alert","codepoint":"F0811","aliases":["battery-charging-wireless-warning"],"tags":["Battery","Home Automation","Alert \/ Error"],"author":"Michael Richins","version":"2.1.19"},{"id":"4AFDE54E-1A6D-4F7F-BD0D-AB67FB0F12CC","name":"battery-charging-wireless-outline","codepoint":"F0812","aliases":["battery-charging-wireless-empty","battery-charging-wireless-0"],"tags":["Battery","Home Automation"],"author":"Michael Richins","version":"2.1.19"},{"id":"DEE88AFA-DFF3-4100-8475-EB5EB72CCFCB","name":"battery-heart","codepoint":"F120F","aliases":[],"tags":["Battery"],"author":"Michael Richins","version":"4.6.95"},{"id":"0D342AE3-0BE6-40C3-BAF9-D519508C4546","name":"battery-heart-outline","codepoint":"F1210","aliases":[],"tags":["Battery"],"author":"Michael Richins","version":"4.6.95"},{"id":"2DE04585-054B-4E09-AC31-33E28DD80942","name":"battery-heart-variant","codepoint":"F1211","aliases":[],"tags":["Battery"],"author":"Michael Richins","version":"4.6.95"},{"id":"253E4BDF-CE79-459D-B06D-915B34A12227","name":"battery-high","codepoint":"F12A3","aliases":[],"tags":["Battery"],"author":"Austin Andrews","version":"4.7.95"},{"id":"4BDC283A-A6B7-4B2B-A18A-2B25410AF35C","name":"battery-low","codepoint":"F12A1","aliases":[],"tags":["Battery"],"author":"Austin Andrews","version":"4.7.95"},{"id":"59FF99D5-138F-4D6B-90B2-4782A4B3F8EB","name":"battery-medium","codepoint":"F12A2","aliases":[],"tags":["Battery"],"author":"Austin Andrews","version":"4.7.95"},{"id":"15E0E37E-564A-40D5-9D4A-948C932C8E52","name":"battery-minus","codepoint":"F008C","aliases":[],"tags":["Battery","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"447DBB2A-31ED-4856-A7A2-A61BF0780C7B","name":"battery-negative","codepoint":"F008D","aliases":[],"tags":["Battery","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C0939A88-BF53-4323-A12F-E6A92F7BE327","name":"battery-off","codepoint":"F125D","aliases":[],"tags":["Battery"],"author":"Michael Richins","version":"4.7.95"},{"id":"66A0E28A-53F2-4E22-B14A-BADBE10E0CA9","name":"battery-off-outline","codepoint":"F125E","aliases":[],"tags":["Battery"],"author":"Michael Richins","version":"4.7.95"},{"id":"925B02B4-CA05-4545-A4E3-421F8412DA37","name":"battery-outline","codepoint":"F008E","aliases":["battery-0","battery-empty"],"tags":["Battery","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"A4BD7F0D-E95C-413C-B853-435A53854844","name":"battery-plus","codepoint":"F008F","aliases":["battery-saver","battery-add"],"tags":["Battery","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"195F51E4-5B02-4BE3-B407-4B7FC1445F18","name":"battery-positive","codepoint":"F0090","aliases":[],"tags":["Battery","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"80257130-A38B-4BC1-B194-2EB16048D763","name":"battery-unknown","codepoint":"F0091","aliases":[],"tags":["Battery","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"B30963B2-893D-43F8-9EFD-918DCB654B75","name":"battery-unknown-bluetooth","codepoint":"F094A","aliases":[],"tags":["Battery"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"0AA8EAC5-6700-47B6-A38B-0E58CFA0CFE7","name":"battlenet","codepoint":"F0B60","aliases":["battle-net"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"3.0.39"},{"id":"FB1FEB37-FA9B-40BF-A7EC-B4A1690E6B77","name":"beach","codepoint":"F0092","aliases":["parasol"],"tags":["Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AC08F348-ACA6-440E-A28D-FCC9BFC85E27","name":"beaker","codepoint":"F0CEA","aliases":[],"tags":["Science"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"22743DE0-B662-44CD-8707-91ABF624D0E3","name":"beaker-alert","codepoint":"F1229","aliases":[],"tags":["Alert \/ Error","Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"327C0F93-7EBD-4B24-A31C-285F6FC14DF3","name":"beaker-alert-outline","codepoint":"F122A","aliases":[],"tags":["Alert \/ Error","Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"252089E7-6AA1-400C-99DF-B8F2090BE78A","name":"beaker-check","codepoint":"F122B","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"23EFC5EC-7DAE-46FC-8E1C-488CF2EFFEB3","name":"beaker-check-outline","codepoint":"F122C","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"FC008372-099E-45EB-BD51-13D1CA45A9BF","name":"beaker-minus","codepoint":"F122D","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"15C31E14-F9D4-49E7-A9FA-266E3C2C7F1B","name":"beaker-minus-outline","codepoint":"F122E","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"95E06F22-3EA5-448F-B260-E555C1DCD18E","name":"beaker-outline","codepoint":"F0690","aliases":[],"tags":["Science"],"author":"Simran","version":"1.7.12"},{"id":"CDF9CCFD-BDE5-4BBF-94DA-BF61466906A6","name":"beaker-plus","codepoint":"F122F","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"210E9002-74BB-44CB-9D93-7CC8EE95D519","name":"beaker-plus-outline","codepoint":"F1230","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"21A03544-7009-4069-8BF0-17168DF93ED9","name":"beaker-question","codepoint":"F1231","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"3C151400-745C-44BE-A94E-A2F5365C7DD6","name":"beaker-question-outline","codepoint":"F1232","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"0F41805A-67FE-4ADB-A398-B22032BF0C89","name":"beaker-remove","codepoint":"F1233","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"DF5AF4E0-65C2-492A-AEDD-0297AE36BA2B","name":"beaker-remove-outline","codepoint":"F1234","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"EA62EF73-ACC7-4E54-87EF-D5E1683BE58F","name":"bed","codepoint":"F02E3","aliases":["hotel"],"tags":["Home Automation","Holiday"],"author":"Google","version":"1.5.54"},{"id":"76E0CC3D-3FF4-421A-A7F0-0F38C68C92A2","name":"bed-double","codepoint":"F0FD4","aliases":[],"tags":["Home Automation","Holiday"],"author":"Michael Richins","version":"4.2.95"},{"id":"6061EF08-3805-4F30-88A1-0DC3419E6989","name":"bed-double-outline","codepoint":"F0FD3","aliases":[],"tags":["Home Automation","Holiday"],"author":"Google","version":"4.2.95"},{"id":"15DC169E-459C-4EDB-BF8F-3E1D4F34B2BF","name":"bed-empty","codepoint":"F08A0","aliases":[],"tags":["Home Automation","Holiday"],"author":"GreenTurtwig","version":"2.2.43"},{"id":"D6763D57-A47E-4BFA-A493-5F25C164FB2F","name":"bed-king","codepoint":"F0FD2","aliases":[],"tags":["Home Automation","Holiday"],"author":"Google","version":"4.2.95"},{"id":"E84472BF-7730-4700-B468-E5096FD65531","name":"bed-king-outline","codepoint":"F0FD1","aliases":[],"tags":["Home Automation","Holiday"],"author":"Michael Richins","version":"4.2.95"},{"id":"860292B0-C722-4829-9E30-AACF00D09C8C","name":"bed-outline","codepoint":"F0099","aliases":["hotel-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"0DB69F3A-8C9B-48D0-8D37-5A1CF6B03B68","name":"bed-queen","codepoint":"F0FD0","aliases":[],"tags":["Home Automation","Holiday"],"author":"Michael Richins","version":"4.2.95"},{"id":"DC8A5BF4-BEA0-4D7D-B364-4765854CD4CE","name":"bed-queen-outline","codepoint":"F0FDB","aliases":[],"tags":["Home Automation","Holiday"],"author":"Michael Richins","version":"4.2.95"},{"id":"A9C924A7-EAA8-42FC-963A-C74E36448A1B","name":"bed-single","codepoint":"F106D","aliases":[],"tags":["Home Automation","Holiday"],"author":"Simran","version":"4.2.95"},{"id":"C9FEB434-571C-41C6-A0E5-1FA68368ACC3","name":"bed-single-outline","codepoint":"F106E","aliases":[],"tags":["Home Automation","Holiday"],"author":"Simran","version":"4.2.95"},{"id":"8B580447-CD93-41E8-BDB0-F37DAE420D3A","name":"bee","codepoint":"F0FA1","aliases":["fly","insect"],"tags":["Nature","Agriculture","Animal"],"author":"Google","version":"4.0.96"},{"id":"ED379BAE-ED56-474D-87C3-8B43D5207766","name":"bee-flower","codepoint":"F0FA2","aliases":["fly-flower","nature"],"tags":["Nature","Agriculture"],"author":"Google","version":"4.0.96"},{"id":"47006F8F-3A47-4D8A-9224-CF1F823E1B35","name":"beehive-off-outline","codepoint":"F13ED","aliases":[],"tags":["Nature","Agriculture"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"667E2F2C-B896-48EF-B5F9-EF9436A8BE4B","name":"beehive-outline","codepoint":"F10CE","aliases":["honey-outline"],"tags":["Nature","Agriculture"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"520FBDF0-4EB1-4413-89F9-AB4E3518FA38","name":"beekeeper","codepoint":"F14E2","aliases":["apiarists","apiculturists","honey-farmer"],"tags":["Nature","Agriculture"],"author":"Contributors","version":"5.4.55"},{"id":"9D9A73D2-0780-4141-95A3-CDFE21E6D4D6","name":"beer","codepoint":"F0098","aliases":["pint","pub","bar","drink","cup-full"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"524E1789-7B3A-4BAD-9D04-2E8FD838DCFB","name":"beer-outline","codepoint":"F130C","aliases":["drink-outline","cup-full-outline","pint-outline","pub-outline","bar-outline"],"tags":["Food \/ Drink"],"author":"Simran","version":"4.8.95"},{"id":"45fea174-07db-11e4-bf19-842b2b6cfe1b","name":"bell","codepoint":"F009A","aliases":["notifications"],"tags":["Notification","Home Automation","Music"],"author":"Google","version":"1.5.54"},{"id":"376D7457-2DC3-463A-B4D9-4F170E0B19FB","name":"bell-alert","codepoint":"F0D59","aliases":["bell-warning"],"tags":["Alert \/ Error","Notification"],"author":"Simran","version":"3.4.93"},{"id":"2E15CEB7-FC9C-4822-94CF-D84F99824F3C","name":"bell-alert-outline","codepoint":"F0E81","aliases":[],"tags":["Alert \/ Error","Notification"],"author":"Simran","version":"3.7.94"},{"id":"61CFFDEC-BE16-404E-8ECA-F911F8105C7C","name":"bell-cancel","codepoint":"F13E7","aliases":[],"tags":["Notification"],"author":"Simran","version":"5.1.45"},{"id":"5CA70271-00B4-4412-B082-FED05EFF165A","name":"bell-cancel-outline","codepoint":"F13E8","aliases":[],"tags":["Notification"],"author":"Simran","version":"5.1.45"},{"id":"A00A7DBE-44BB-4843-B740-FAAB76357B03","name":"bell-check","codepoint":"F11E5","aliases":[],"tags":["Notification"],"author":"Contributors","version":"4.5.95"},{"id":"510AFFA1-DEEE-4A0B-B596-611969C5934D","name":"bell-check-outline","codepoint":"F11E6","aliases":[],"tags":["Notification"],"author":"Contributors","version":"4.5.95"},{"id":"D811F01E-BDFB-496F-866C-70533A343B57","name":"bell-circle","codepoint":"F0D5A","aliases":[],"tags":["Notification"],"author":"Google","version":"3.4.93"},{"id":"204DDC9C-1546-44DF-829D-2EA5AA299804","name":"bell-circle-outline","codepoint":"F0D5B","aliases":[],"tags":["Notification"],"author":"Google","version":"3.4.93"},{"id":"C25507E4-8865-47BF-A6AB-D97978AB4397","name":"bell-minus","codepoint":"F13E9","aliases":[],"tags":["Notification"],"author":"Simran","version":"5.1.45"},{"id":"7344702F-0680-4095-BF7E-D9AFDE650703","name":"bell-minus-outline","codepoint":"F13EA","aliases":[],"tags":["Notification"],"author":"Simran","version":"5.1.45"},{"id":"69686D8F-75FE-4091-9061-88DB64D95C01","name":"bell-off","codepoint":"F009B","aliases":["notifications-off"],"tags":["Notification"],"author":"Google","version":"1.5.54"},{"id":"6C0FD819-5174-4CCA-8A63-2CEE9F6EE71E","name":"bell-off-outline","codepoint":"F0A91","aliases":[],"tags":["Notification"],"author":"Google","version":"2.7.94"},{"id":"70A190E9-6F1D-40DB-81D4-C9516949DF0B","name":"bell-outline","codepoint":"F009C","aliases":["notifications-none"],"tags":["Notification","Music"],"author":"Google","version":"1.5.54"},{"id":"FC07FF46-2FD1-4E4E-8D35-BADDEEB5F531","name":"bell-plus","codepoint":"F009D","aliases":["add-alert","bell-add"],"tags":["Notification"],"author":"Simran","version":"1.5.54"},{"id":"45FB036D-61D0-4390-9F15-480121F2CE3B","name":"bell-plus-outline","codepoint":"F0A92","aliases":["bell-add-outline","add-alert-outline"],"tags":["Notification"],"author":"Simran","version":"2.7.94"},{"id":"16A7DF47-4674-4439-9E33-ADE491DFC806","name":"bell-remove","codepoint":"F13EB","aliases":[],"tags":["Notification"],"author":"Simran","version":"5.1.45"},{"id":"BFCC1A57-A94F-4104-BCBF-980E9D8B2B6C","name":"bell-remove-outline","codepoint":"F13EC","aliases":[],"tags":["Notification"],"author":"Simran","version":"5.1.45"},{"id":"CD75C484-B1AD-492B-8CAA-9F002398C3CA","name":"bell-ring","codepoint":"F009E","aliases":["notifications-active"],"tags":["Notification"],"author":"Google","version":"1.5.54"},{"id":"EE7DADC1-CF66-4922-B0C9-9B8F753514F9","name":"bell-ring-outline","codepoint":"F009F","aliases":[],"tags":["Notification"],"author":"Google","version":"1.5.54"},{"id":"43BD9E91-2044-4B80-AF87-2FC810C42A1B","name":"bell-sleep","codepoint":"F00A0","aliases":["notifications-paused"],"tags":["Notification"],"author":"Google","version":"1.5.54"},{"id":"91193FC6-AF35-46FD-A05E-6AA99D6EA99F","name":"bell-sleep-outline","codepoint":"F0A93","aliases":[],"tags":["Notification"],"author":"Google","version":"2.7.94"},{"id":"4F83A19F-BAB5-4894-AC5A-B288AFD592DC","name":"beta","codepoint":"F00A1","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5FA9C13A-087C-452E-966F-4C2FCE336C68","name":"betamax","codepoint":"F09CB","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"7E88D677-5560-4DF1-A3D0-FC2814BF6612","name":"biathlon","codepoint":"F0E14","aliases":[],"tags":["Sport"],"author":"Google","version":"3.6.95"},{"id":"90DDBB60-0BBB-4DFA-9626-32D4D1FB34C5","name":"bicycle","codepoint":"F109C","aliases":["bike","cycling"],"tags":["Transportation + Other"],"author":"Fran\u00e7ois Risoud","version":"4.2.95"},{"id":"CF4876E1-DEBA-4C41-B5B7-4C90C3EF68F4","name":"bicycle-basket","codepoint":"F1235","aliases":["bike-basket"],"tags":["Transportation + Other"],"author":"Fran\u00e7ois Risoud","version":"4.6.95"},{"id":"3923C397-5A00-472A-8FDC-FBBAAF3FA323","name":"bicycle-electric","codepoint":"F15B4","aliases":["bike-electric"],"tags":["Transportation + Other"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"A7A362D7-385E-4026-A43F-BBF13E8D4B37","name":"bicycle-penny-farthing","codepoint":"F15E9","aliases":["bicycle-high-wheel","bicycle-antique"],"tags":["Transportation + Other"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"627C7FF1-BCAD-4741-966E-7CED73B35DC2","name":"bike","codepoint":"F00A3","aliases":["bicycle","cycling","directions-bike"],"tags":["Transportation + Other","Sport"],"author":"Google","version":"1.5.54"},{"id":"2C312B6E-73D4-4A98-A701-D49E31F95E7B","name":"bike-fast","codepoint":"F111F","aliases":[],"tags":["Transportation + Other"],"author":"GreenTurtwig","version":"4.3.95"},{"id":"645C4EDB-9339-4784-8AE9-BD60F8460CAE","name":"billboard","codepoint":"F1010","aliases":[],"tags":[],"author":"Michael Richins","version":"4.1.95"},{"id":"6FFE2C93-4350-4706-9694-1674F96855EA","name":"billiards","codepoint":"F0B61","aliases":["pool","eight-ball"],"tags":["Sport"],"author":"Michael Richins","version":"3.0.39"},{"id":"2ED0EE4C-D928-41C6-8D5D-3AA3A2DF7AF6","name":"billiards-rack","codepoint":"F0B62","aliases":["pool-table","pool-rack","snooker-rack","pool-triangle","billiards-triangle","snooker-triangle"],"tags":["Sport"],"author":"Michael Richins","version":"3.0.39"},{"id":"75806AA4-294B-4A0A-8BDB-FC4CABCA1768","name":"binoculars","codepoint":"F00A5","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"F5D76655-0F6E-4FF2-AC74-CC3A235B7FC6","name":"bio","codepoint":"F00A6","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"96BDE572-9D10-47D0-919F-68EB6CD3DFA9","name":"biohazard","codepoint":"F00A7","aliases":[],"tags":["Science"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"18622D72-42B2-4919-BDB5-DCC77310045B","name":"bird","codepoint":"F15C6","aliases":[],"tags":["Animal"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"B48BB714-F66F-4D86-9864-051DB90AE197","name":"bitbucket","codepoint":"F00A8","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"9C8A35A5-86B5-4B10-BEE9-93CDFAF15B9C","name":"bitcoin","codepoint":"F0813","aliases":[],"tags":["Brand \/ Logo","Banking","Currency"],"author":"Contributors","version":"2.1.19"},{"id":"1F233821-5ED4-4CB3-8933-9A16C05D7AC9","name":"black-mesa","codepoint":"F00A9","aliases":[],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.5.54"},{"id":"AC980D29-7F19-4356-970E-A147CFEB64E3","name":"blender","codepoint":"F0CEB","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"F365BC90-C8EC-4A5C-99FB-C2ED27B5593A","name":"blender-software","codepoint":"F00AB","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"926ACBEB-C5F6-4EF4-829E-E0B05501DDD6","name":"blinds","codepoint":"F00AC","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5DCCF3FA-F418-4052-9B93-6FA85C2659F5","name":"blinds-open","codepoint":"F1011","aliases":[],"tags":["Home Automation"],"author":"idevo89","version":"4.1.95"},{"id":"5832B598-DAAA-4497-B995-CF940A1C7F20","name":"block-helper","codepoint":"F00AD","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"AAF23976-7C9D-4AFA-BE25-CCD225A95EEA","name":"blogger","codepoint":"F00AE","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"FA540210-0F58-4D2A-86BA-E202B520C8DA","name":"blood-bag","codepoint":"F0CEC","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"7CBB03E7-EAC6-44C2-8C28-A78728F8BB7B","name":"bluetooth","codepoint":"F00AF","aliases":[],"tags":[],"author":"Contributors","version":"1.5.54"},{"id":"6639774A-9027-4D20-AE57-24C78EF41141","name":"bluetooth-audio","codepoint":"F00B0","aliases":["bluetooth-searching"],"tags":["Audio"],"author":"Google","version":"1.5.54"},{"id":"1E123F41-EA93-4085-8446-88F50C501A6F","name":"bluetooth-connect","codepoint":"F00B1","aliases":["bluetooth-connected"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"CEB015C9-455E-4551-A898-7A992658CF72","name":"bluetooth-off","codepoint":"F00B2","aliases":["bluetooth-disabled"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"E5DEA4AB-58E1-45CF-81EF-1A98594C5884","name":"bluetooth-settings","codepoint":"F00B3","aliases":["settings-bluetooth"],"tags":["Settings"],"author":"Google","version":"1.5.54"},{"id":"A0D9FDB0-B6D8-43F9-A418-01B78336C84C","name":"bluetooth-transfer","codepoint":"F00B4","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"FAFCB184-2AAD-4E83-924F-1C37F1EDF956","name":"blur","codepoint":"F00B5","aliases":["blur-on"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B23B281D-C753-468E-A0D1-79C2963346C8","name":"blur-linear","codepoint":"F00B6","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4F541CC2-7659-4230-A307-6E5D515C529B","name":"blur-off","codepoint":"F00B7","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"29F42A3B-BCD5-45BA-9B87-35F97FE9438D","name":"blur-radial","codepoint":"F00B8","aliases":["blur-circular"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"00B9DE12-462A-483B-90D3-8FA89B3D9FD5","name":"bolnisi-cross","codepoint":"F0CED","aliases":[],"tags":["Religion"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"4371183D-0D2B-4512-8069-93834BC85DE7","name":"bolt","codepoint":"F0DB3","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"7DC40C3F-3733-48AF-94C7-5454FB849A49","name":"bomb","codepoint":"F0691","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.7.12"},{"id":"DEC98F6C-E85D-400C-87CD-6AE692583838","name":"bomb-off","codepoint":"F06C5","aliases":[],"tags":[],"author":"Roberto Graham","version":"1.8.36"},{"id":"7FCD9594-B235-45D5-8504-A41F251FD50E","name":"bone","codepoint":"F00B9","aliases":[],"tags":["Animal"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FFF82791-D12F-4643-8128-71CF5FE38C9B","name":"book","codepoint":"F00BA","aliases":["git-repository"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D4247A9D-BD96-40AC-8C4E-A9A255DF5160","name":"book-account","codepoint":"F13AD","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"5.0.45"},{"id":"C9126B03-23E9-457D-9249-ADB88EA6F0E4","name":"book-account-outline","codepoint":"F13AE","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"5.0.45"},{"id":"08CE9E71-4426-4186-8573-7B2EDFE28F7D","name":"book-alert","codepoint":"F167C","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"6DDFDD69-EBA5-4BFB-A44F-6B84A7B3A4BC","name":"book-alert-outline","codepoint":"F167D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"250BF541-072A-4773-8BC2-B1943DF1EDBB","name":"book-alphabet","codepoint":"F061D","aliases":["dictionary"],"tags":[],"author":"Christopher Schreiner","version":"1.6.50"},{"id":"7B6400CF-D8CF-418B-A400-CDCA1D58E813","name":"book-arrow-down","codepoint":"F167E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"7B9920BE-2895-4D38-A981-5E416D76403A","name":"book-arrow-down-outline","codepoint":"F167F","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"5D776E4B-7F6C-4385-A892-964B3F800F30","name":"book-arrow-left","codepoint":"F1680","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"1730A6B3-D405-4F4B-A12D-0957B5B268D7","name":"book-arrow-left-outline","codepoint":"F1681","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"2780AAEC-BE71-4C4A-8C02-7BCDBE521D74","name":"book-arrow-right","codepoint":"F1682","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"CCBCE4D7-2799-433B-AF47-A5105E45779A","name":"book-arrow-right-outline","codepoint":"F1683","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"E724EA9A-002E-4A3E-9275-690258105F1D","name":"book-arrow-up","codepoint":"F1684","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"D3DE3980-8DF9-4FED-B08D-F04B5610B84D","name":"book-arrow-up-outline","codepoint":"F1685","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"8D3C8531-8EAD-43FC-9139-B1A9D2BEB63D","name":"book-cancel","codepoint":"F1686","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"FA64FF4E-C720-4635-90EF-D4A913168329","name":"book-cancel-outline","codepoint":"F1687","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"ADF6BB0F-12F3-498F-B31A-07F6BFFFDF9D","name":"book-check","codepoint":"F14F3","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.4.55"},{"id":"32A94643-61F6-4F21-BB4D-68932CB98FB4","name":"book-check-outline","codepoint":"F14F4","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.4.55"},{"id":"97CCD006-4DE0-4AEE-BB95-D9EBCCDE8012","name":"book-clock","codepoint":"F1688","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"EFEC2FA7-18B1-4753-88C4-E2531FA96DD5","name":"book-clock-outline","codepoint":"F1689","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"36C20B8A-AA61-49D5-9500-16917BBDF388","name":"book-cog","codepoint":"F168A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"B63BFA22-6A8E-48FD-8BDB-E82BB550411D","name":"book-cog-outline","codepoint":"F168B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"CC30F9D0-3076-4189-A00D-F570D5B0C5D1","name":"book-cross","codepoint":"F00A2","aliases":["bible"],"tags":["Religion"],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"CF11FAB5-CEE6-4F8D-9E64-67285419FF62","name":"book-edit","codepoint":"F168C","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"615E9F0E-F80A-4806-8023-F3B5E47A0F07","name":"book-edit-outline","codepoint":"F168D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"B115D616-1428-4D6B-84D7-643900FBEF77","name":"book-education","codepoint":"F16C9","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"2C5308E6-760F-4CD8-A2CF-DD3B5434B0A0","name":"book-education-outline","codepoint":"F16CA","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"4A6A20D1-3F8E-440A-BFB1-38CFB3FB3EC6","name":"book-information-variant","codepoint":"F106F","aliases":["encyclopedia"],"tags":[],"author":"Terren","version":"4.2.95"},{"id":"121AF367-3AE5-48D1-9868-8DC60342D4A0","name":"book-lock","codepoint":"F079A","aliases":["book-secure"],"tags":["Lock"],"author":"Michael Richins","version":"2.0.46"},{"id":"90B49606-B4FF-4D4B-AE05-4769659094CE","name":"book-lock-open","codepoint":"F079B","aliases":["book-unsecure"],"tags":["Lock"],"author":"Michael Richins","version":"2.0.46"},{"id":"F4804DDA-AD18-4DAF-A916-F0F6DC23F0A5","name":"book-lock-open-outline","codepoint":"F168E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"2E088838-572B-45AC-B250-1C86900B787E","name":"book-lock-outline","codepoint":"F168F","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"D5DCE615-BCFA-4922-8F95-5CEA756FD378","name":"book-marker","codepoint":"F1690","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"69EBC2C1-A3D3-42E6-9868-3E97DD6DD301","name":"book-marker-outline","codepoint":"F1691","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"7367B5F0-8155-4F3D-9C7E-BFDF677442D8","name":"book-minus","codepoint":"F05D9","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"6B536CF6-98D8-44A5-9094-43C1BE41EC91","name":"book-minus-multiple","codepoint":"F0A94","aliases":["books-minus"],"tags":[],"author":"Perth Totty","version":"2.7.94"},{"id":"2AF5ACED-6980-4A66-B010-629C3E371315","name":"book-minus-multiple-outline","codepoint":"F090B","aliases":[],"tags":[],"author":"Michael Richins","version":"2.3.50"},{"id":"402AE77A-79CC-42EF-9FB7-7D11D2C949DA","name":"book-minus-outline","codepoint":"F1692","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"637C4988-5432-4F5E-ADD5-EBDC397D0622","name":"book-multiple","codepoint":"F00BB","aliases":["books"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B58005AE-8DFA-4C34-AC4D-C14DEF3D35C2","name":"book-multiple-outline","codepoint":"F0436","aliases":[],"tags":[],"author":"Michael Richins","version":"1.5.54"},{"id":"10BCB9E5-2E1F-4CD0-871F-B36FA0595004","name":"book-music","codepoint":"F0067","aliases":["audio-book"],"tags":["Audio"],"author":"Austin Andrews","version":"1.5.54"},{"id":"22B56C5C-000D-49DB-9D8A-DDD312662DFB","name":"book-music-outline","codepoint":"F1693","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"52463F43-10D2-41DC-B4EB-45DDE9A4E655","name":"book-off","codepoint":"F1694","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"C9B4D51E-AA3F-49D4-9603-CC5CA33EB28A","name":"book-off-outline","codepoint":"F1695","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"7EFAD89C-D84E-41F0-A8A4-F72AC8DB470C","name":"book-open","codepoint":"F00BD","aliases":["chrome-reader-mode"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"08C8BAF9-6B91-458D-BE03-F6A7AABEA2AB","name":"book-open-blank-variant","codepoint":"F00BE","aliases":["import-contacts"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BA5E15E3-923B-464B-ACEA-F2958F6782F7","name":"book-open-outline","codepoint":"F0B63","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"113421A1-241F-4479-B22B-5F56EFD63D4C","name":"book-open-page-variant","codepoint":"F05DA","aliases":["auto-stories"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"3653D788-AC33-42D4-ADE4-F91A1C373973","name":"book-open-page-variant-outline","codepoint":"F15D6","aliases":[],"tags":[],"author":"Google","version":"5.6.55"},{"id":"E5928511-4156-4086-B58D-A2B235A3F824","name":"book-open-variant","codepoint":"F14F7","aliases":[],"tags":[],"author":"Google","version":"5.4.55"},{"id":"D1558D49-BCE0-4539-9560-DB05153356AF","name":"book-outline","codepoint":"F0B64","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"89E22D2B-FF72-4242-BEE1-7865F974CF51","name":"book-play","codepoint":"F0E82","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.7.94"},{"id":"8A87B5DD-D8DF-43A8-BFDD-D127E6F48792","name":"book-play-outline","codepoint":"F0E83","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.7.94"},{"id":"3C49BDB2-C3A3-4E0C-9314-19FE66414A5B","name":"book-plus","codepoint":"F05DB","aliases":["book-add"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"9A754066-7A7A-4362-9530-C8500B178DED","name":"book-plus-multiple","codepoint":"F0A95","aliases":["books-plus","book-multiple-add","books-add"],"tags":[],"author":"Perth Totty","version":"2.7.94"},{"id":"129A1ABB-F616-4750-8814-018A12FE9D88","name":"book-plus-multiple-outline","codepoint":"F0ADE","aliases":[],"tags":[],"author":"Michael Richins","version":"2.7.94"},{"id":"58B6134A-73CF-4E0E-AB85-DCBFB6B6766B","name":"book-plus-outline","codepoint":"F1696","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"CFAA64B9-8047-4713-AD53-574A398F187F","name":"book-refresh","codepoint":"F1697","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"7F62E9BE-F358-4CF8-B3DB-938805F83089","name":"book-refresh-outline","codepoint":"F1698","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"DAB52460-1820-4BD0-9695-67EBF9E84167","name":"book-remove","codepoint":"F0A97","aliases":[],"tags":[],"author":"Perth Totty","version":"2.7.94"},{"id":"414C568C-94B4-4EC3-9D81-22F747B9D0FC","name":"book-remove-multiple","codepoint":"F0A96","aliases":["books-remove"],"tags":[],"author":"Perth Totty","version":"2.7.94"},{"id":"32DEB304-15CC-4B30-832E-A1377A57EC47","name":"book-remove-multiple-outline","codepoint":"F04CA","aliases":[],"tags":[],"author":"Michael Richins","version":"1.5.54"},{"id":"CDCF29D7-CED3-45DB-BBC8-ACEA8262738C","name":"book-remove-outline","codepoint":"F1699","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"AE0D918C-8BC9-4D85-B445-62039AD16FB2","name":"book-search","codepoint":"F0E84","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.7.94"},{"id":"62AB37D9-3483-4F21-BD4C-44214B668599","name":"book-search-outline","codepoint":"F0E85","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.7.94"},{"id":"E48C6D20-C8BC-43A0-9F90-A9FBADAB3454","name":"book-settings","codepoint":"F169A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"E090B509-20FE-405D-9811-221E533F79F3","name":"book-settings-outline","codepoint":"F169B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"ACB38262-FB32-456E-AE84-6BCE160F56C4","name":"book-sync","codepoint":"F169C","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"8C2A47E9-6B8B-4504-A1C7-37EDFD9DC979","name":"book-sync-outline","codepoint":"F16C8","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"1B9F45CE-CA39-4ACF-8961-4B4B56D6F94A","name":"book-variant","codepoint":"F00BF","aliases":["class"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"6B7FCAFD-C14A-49FC-A959-A2B6C7C2C5BC","name":"book-variant-multiple","codepoint":"F00BC","aliases":["books-variant"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"690787DD-F7B0-4D32-A668-32657D3A3AE8","name":"bookmark","codepoint":"F00C0","aliases":["turned-in"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"65F155F1-7A9F-49AF-B570-FD6D24553CE5","name":"bookmark-check","codepoint":"F00C1","aliases":["bookmark-tick"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"EFBBDF1F-1497-4BA3-AE93-614B2BB496F7","name":"bookmark-check-outline","codepoint":"F137B","aliases":[],"tags":[],"author":"Simran","version":"4.9.95"},{"id":"AB2B19C4-5114-4D8A-A2EB-4E112B43F383","name":"bookmark-minus","codepoint":"F09CC","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"491E1C5C-650E-41BB-9D44-8F8F2474B657","name":"bookmark-minus-outline","codepoint":"F09CD","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"28FFD085-27EC-47A7-88A7-989BECA3DDE0","name":"bookmark-multiple","codepoint":"F0E15","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"4C37E778-2438-4F54-8D08-5B25A7659FB7","name":"bookmark-multiple-outline","codepoint":"F0E16","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"DF4ECEB8-EF5C-4ACC-BC7D-B4FEEE75D17D","name":"bookmark-music","codepoint":"F00C2","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"140B0E5A-4F75-4C53-A9D5-867E4DC020E7","name":"bookmark-music-outline","codepoint":"F1379","aliases":[],"tags":[],"author":"Simran","version":"4.9.95"},{"id":"CE74B9A9-5962-4127-ACBE-A1AD4F130A2F","name":"bookmark-off","codepoint":"F09CE","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"998B6488-F375-4297-9941-6D8ADC4E7F3C","name":"bookmark-off-outline","codepoint":"F09CF","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"0EB6BB85-4BE2-4608-BABF-2EF135D420A7","name":"bookmark-outline","codepoint":"F00C3","aliases":["bookmark-border","turned-in-not"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"596822BD-8373-402C-9D27-C341405F55F9","name":"bookmark-plus","codepoint":"F00C5","aliases":["bookmark-add"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"DB2B7624-66CB-4E7E-A65F-4CEE8870C6CC","name":"bookmark-plus-outline","codepoint":"F00C4","aliases":["bookmark-add-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"89594C9C-18ED-45EA-A3AC-A91B570D1541","name":"bookmark-remove","codepoint":"F00C6","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0634B479-2104-4AF4-B442-2E5C407EBEE1","name":"bookmark-remove-outline","codepoint":"F137A","aliases":[],"tags":[],"author":"Simran","version":"4.9.95"},{"id":"562F5DDE-E65C-4ACC-98B7-54C0D5406AED","name":"bookshelf","codepoint":"F125F","aliases":[],"tags":[],"author":"Thomas de Saint-Exup\u00e9ry","version":"4.7.95"},{"id":"D24517D5-27A6-4BE4-B9C8-C575A1431310","name":"boom-gate","codepoint":"F0E86","aliases":["boom-arm","boom-barrier","arm-barrier","barrier","automatic-gate"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"2C3B8F49-7A38-49EE-8288-FDA6AC188727","name":"boom-gate-alert","codepoint":"F0E87","aliases":["boom-arm-alert","boom-barrier-alert","arm-barrier-alert","barrier-alert","automatic-gate-alert"],"tags":["Alert \/ Error","Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"B138EF8B-B8ED-4792-9967-D4FB4C8E8A98","name":"boom-gate-alert-outline","codepoint":"F0E88","aliases":["boom-arm-alert-outline","boom-barrier-alert-outline","arm-barrier-alert-outline","barrier-alert-outline","automatic-gate-alert-outline"],"tags":["Alert \/ Error","Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"D9BD19B7-12DD-4557-9DDA-998688CA3CB5","name":"boom-gate-down","codepoint":"F0E89","aliases":["boom-arm-down","boom-barrier-down","arm-barrier-down","barrier-down","automatic-gate-down"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"F0ED697E-DAA8-4530-8403-C614C8EBCE3B","name":"boom-gate-down-outline","codepoint":"F0E8A","aliases":["boom-arm-down-outline","boom-barrier-down-outline","arm-barrier-down-outline","barrier-down-outline","automatic-gate-down-outline"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"EF1F53B3-DA99-4410-9A20-E12C42FC2461","name":"boom-gate-outline","codepoint":"F0E8B","aliases":["boom-arm-outline","boom-barrier-outline","arm-barrier-outline","barrier-outline","automatic-gate-outline"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"F9ADF5B2-435F-4820-8790-EAA72D6D5C75","name":"boom-gate-up","codepoint":"F0E8C","aliases":["boom-arm-up","boom-barrier-up","arm-barrier-up","barrier-up","automatic-gate-up"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"24E7CECC-7FAC-4FE4-8EAE-B727489040E8","name":"boom-gate-up-outline","codepoint":"F0E8D","aliases":["boom-arm-up-outline","boom-barrier-up-outline","arm-barrier-up-outline","barrier-up-outline","automatic-gate-up-outline"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"3.7.94"},{"id":"DAA06443-AE25-4881-BC62-8033C4420B8E","name":"boombox","codepoint":"F05DC","aliases":[],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"090EBF34-3104-4D3C-B3C8-819C332A43E1","name":"boomerang","codepoint":"F10CF","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"9DAC7258-AB2D-49E4-98A9-E84A5E3E474B","name":"bootstrap","codepoint":"F06C6","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"1.8.36"},{"id":"A3D0E8B6-96B3-4281-B31C-0DDFD729903B","name":"border-all","codepoint":"F00C7","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"AD3DDFBC-21FE-4D6E-AE09-E9EB7D289459","name":"border-all-variant","codepoint":"F08A1","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.2.43"},{"id":"9441B8BD-25C8-4F46-AFD4-6B2DA0C4A599","name":"border-bottom","codepoint":"F00C8","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"29792687-63C3-41A6-8182-CF829969BD48","name":"border-bottom-variant","codepoint":"F08A2","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.2.43"},{"id":"CCD99C36-5D88-4696-8193-56F11C4B20A7","name":"border-color","codepoint":"F00C9","aliases":["border-colour"],"tags":["Color","Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"0F804E73-90EF-4175-984D-603698F0AF09","name":"border-horizontal","codepoint":"F00CA","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"F7471447-8501-40A6-9FFB-AB353B55AA89","name":"border-inside","codepoint":"F00CB","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"6B8A1379-9497-4B1B-A8CF-51CB1AD67757","name":"border-left","codepoint":"F00CC","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"063FAD96-7055-4D1E-8E50-B9288BB9D0B0","name":"border-left-variant","codepoint":"F08A3","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.2.43"},{"id":"F6333BD9-AC00-428D-B8A8-FA3B9187487F","name":"border-none","codepoint":"F00CD","aliases":["border-clear"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"C8EC415C-81DE-4399-AEAB-FE102959F619","name":"border-none-variant","codepoint":"F08A4","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.2.43"},{"id":"F8EA9B00-82F1-4DE8-B8B5-0A71B934C44D","name":"border-outside","codepoint":"F00CE","aliases":["border-outer"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"BC67506B-CAE4-4EDA-B0C8-614436AFDCBF","name":"border-right","codepoint":"F00CF","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"6284DA6C-DB95-4747-BB40-DE69D5970C5B","name":"border-right-variant","codepoint":"F08A5","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.2.43"},{"id":"5A750E96-F9A0-4C38-B601-8BA770E89E01","name":"border-style","codepoint":"F00D0","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"AE703F65-F8D5-43B9-9B6B-B5966260E799","name":"border-top","codepoint":"F00D1","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"E9426CB0-FC83-40AA-B429-F55AD3F72E47","name":"border-top-variant","codepoint":"F08A6","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.2.43"},{"id":"540E7940-BA85-4EED-BEAB-C50CEF348D50","name":"border-vertical","codepoint":"F00D2","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"D938FAC2-CC48-431D-8019-FA41677470DD","name":"bottle-soda","codepoint":"F1070","aliases":["bottle-coke","bottle-pop"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"4.2.95"},{"id":"E62A084A-2136-4FD3-8803-A72DE26D60CB","name":"bottle-soda-classic","codepoint":"F1071","aliases":["bottle-coke-classic","bottle-pop-classic"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"4.2.95"},{"id":"7682F8D6-3FFD-4591-BFC5-44BF9166FB49","name":"bottle-soda-classic-outline","codepoint":"F1363","aliases":[],"tags":[],"author":"Simran","version":"4.9.95"},{"id":"54C4C95B-E05C-4992-8365-96586E864FF9","name":"bottle-soda-outline","codepoint":"F1072","aliases":["bottle-coke-outline","bottle-pop-outline"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"4.2.95"},{"id":"4FEF379F-2EBC-49EA-87B8-068B695A67B6","name":"bottle-tonic","codepoint":"F112E","aliases":["flask"],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"44193E2D-1EAB-4BA1-9D32-C7E149F53E89","name":"bottle-tonic-outline","codepoint":"F112F","aliases":["flask-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"9524D285-4F39-4FEA-9EC1-9F4B6ACB6615","name":"bottle-tonic-plus","codepoint":"F1130","aliases":["health-potion"],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"8508B85B-4238-4FC5-90F8-3C7E5612174B","name":"bottle-tonic-plus-outline","codepoint":"F1131","aliases":["health-potion-outline"],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"CE430764-D7C8-4DC8-97F4-DF1473B2C52C","name":"bottle-tonic-skull","codepoint":"F1132","aliases":["poison","moonshine"],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"24EF4783-9CDC-402E-9F8D-28CCDB50F216","name":"bottle-tonic-skull-outline","codepoint":"F1133","aliases":["poison-outline","moonshine-outline"],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"E27EBD86-D80B-473B-BEAB-A22005475F38","name":"bottle-wine","codepoint":"F0854","aliases":[],"tags":["Food \/ Drink"],"author":"James Coyle","version":"2.1.99"},{"id":"B04C5F90-A3FB-4A60-B773-25AE19D293C7","name":"bottle-wine-outline","codepoint":"F1310","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"4.8.95"},{"id":"741B300C-06EF-459D-BB3E-95DB8E21194E","name":"bow-tie","codepoint":"F0678","aliases":[],"tags":["Clothing"],"author":"Thomas Hunsaker","version":"1.7.12"},{"id":"84EB4644-EC38-431B-B55B-12363EB63765","name":"bowl","codepoint":"F028E","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"95E70948-C85D-41AC-887C-62752FBA7B6B","name":"bowl-mix","codepoint":"F0617","aliases":["mixing-bowl"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.6.50"},{"id":"3C547C40-FF5E-4BB6-B45E-2B26AD990B20","name":"bowl-mix-outline","codepoint":"F02E4","aliases":["mixing-bowl-outline"],"tags":["Food \/ Drink"],"author":"Simran","version":"1.5.54"},{"id":"D0021FC3-865F-45B4-8542-4937DC2952E2","name":"bowl-outline","codepoint":"F02A9","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"0CAB5DF9-E4A7-418D-B317-E792FF2DF8D1","name":"bowling","codepoint":"F00D3","aliases":[],"tags":["Sport"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1E6B8A9E-921F-4695-B1CA-0A87AC157E88","name":"box","codepoint":"F00D4","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"A4C51C21-DEB0-4247-AEA3-B5F454641BDC","name":"box-cutter","codepoint":"F00D5","aliases":["stanley-knife"],"tags":["Hardware \/ Tools"],"author":"Simran","version":"1.5.54"},{"id":"0E77ABEB-007D-4458-BEB9-F2C4607ECFC7","name":"box-cutter-off","codepoint":"F0B4A","aliases":[],"tags":[],"author":"nilsfast","version":"2.8.94"},{"id":"9DBE04CB-C425-4556-9046-15CBD88C866B","name":"box-shadow","codepoint":"F0637","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"C36FCD4A-D073-4BCA-96D1-90CD81E4C080","name":"boxing-glove","codepoint":"F0B65","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"3B62C43D-F1BC-45AB-AB68-B1B854009FD8","name":"braille","codepoint":"F09D0","aliases":[],"tags":[],"author":"Michael Richins","version":"2.5.94"},{"id":"8EC09BCA-7C35-4FAB-9000-4A7795CC0930","name":"brain","codepoint":"F09D1","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Richins","version":"2.5.94"},{"id":"ED0E86DB-C4A5-477B-82BF-FC5849EE0B9C","name":"bread-slice","codepoint":"F0CEE","aliases":[],"tags":["Food \/ Drink"],"author":"Nick","version":"3.3.92"},{"id":"FAC52832-EA67-4ABF-9841-7D3DD07C6EFF","name":"bread-slice-outline","codepoint":"F0CEF","aliases":[],"tags":["Food \/ Drink"],"author":"Nick","version":"3.3.92"},{"id":"9FD9D8F0-D777-4B33-9CF7-E32FD8C25655","name":"bridge","codepoint":"F0618","aliases":[],"tags":["Places"],"author":"Austin Andrews","version":"1.6.50"},{"id":"15A9F4A5-3EB6-443C-8283-547A077CB0C4","name":"briefcase","codepoint":"F00D6","aliases":["work"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B0F37881-7339-4CBC-9DB5-833EDCB6B049","name":"briefcase-account","codepoint":"F0CF0","aliases":["briefcase-person","briefcase-user"],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"F92EB0E4-257F-4200-A18E-0F0C02C8DB51","name":"briefcase-account-outline","codepoint":"F0CF1","aliases":["briefcase-person-outline","briefcase-user-outline"],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"4182182E-F79B-4153-B652-2A4B4AC231E1","name":"briefcase-check","codepoint":"F00D7","aliases":["briefcase-tick"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"3889AEB1-7257-4D20-ACD4-78CB27879639","name":"briefcase-check-outline","codepoint":"F131E","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"1BC68384-3EB0-4296-A3B2-9F348DD7AF1E","name":"briefcase-clock","codepoint":"F10D0","aliases":[],"tags":["Date \/ Time"],"author":"Michael Richins","version":"4.3.95"},{"id":"EBE7A5FD-4D46-4A78-BA72-816546ABB880","name":"briefcase-clock-outline","codepoint":"F10D1","aliases":[],"tags":["Date \/ Time"],"author":"Michael Richins","version":"4.3.95"},{"id":"D4705E48-0920-451E-BFF3-2DA1BBA5C21D","name":"briefcase-download","codepoint":"F00D8","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DD87CBA1-4687-45A7-B470-EC75EC4C0D32","name":"briefcase-download-outline","codepoint":"F0C3D","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"485F9428-A4BF-422D-A624-61AB07D37890","name":"briefcase-edit","codepoint":"F0A98","aliases":[],"tags":["Edit \/ Modify"],"author":"Contributors","version":"2.7.94"},{"id":"EE4B8481-FF0C-44BC-9D23-64DFDF499F73","name":"briefcase-edit-outline","codepoint":"F0C3E","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"5999899F-7FE5-44EF-87F4-DD1E2F9556B3","name":"briefcase-minus","codepoint":"F0A2A","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"C185E5E9-F652-41C2-9FBA-6673FE7CEB10","name":"briefcase-minus-outline","codepoint":"F0C3F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"2059EB01-3552-45CF-A2A1-64DA37F124D0","name":"briefcase-off","codepoint":"F1658","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"EE25B28C-2F16-4BE0-95BB-8328DF0F0CA2","name":"briefcase-off-outline","codepoint":"F1659","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"1E7F3689-287C-40DC-B0DD-CF65987E9B53","name":"briefcase-outline","codepoint":"F0814","aliases":["work-outline"],"tags":[],"author":"Google","version":"2.1.19"},{"id":"C08C7899-5B7E-4E6F-9861-C319CFABA7DC","name":"briefcase-plus","codepoint":"F0A2B","aliases":["briefcase-add"],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"CA6D7ED5-38E6-4B63-915A-431CDDA27062","name":"briefcase-plus-outline","codepoint":"F0C40","aliases":["briefcase-add-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"9B02F5A1-D171-49A4-91DB-5F47E03D7B65","name":"briefcase-remove","codepoint":"F0A2C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"1754B039-7D56-4722-BEE1-8A8BA735FCD5","name":"briefcase-remove-outline","codepoint":"F0C41","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"E6071C37-85E7-45F7-868D-A12234D0B979","name":"briefcase-search","codepoint":"F0A2D","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.6.95"},{"id":"62511811-5FA9-4E69-8513-62828BE493DF","name":"briefcase-search-outline","codepoint":"F0C42","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"3D48B9FF-A060-47DA-809E-32D5ED68CA64","name":"briefcase-upload","codepoint":"F00D9","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"AE06D41B-19EB-4E10-92DE-2A285163F034","name":"briefcase-upload-outline","codepoint":"F0C43","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"1BB4FAD5-B3AE-47FD-95C4-B1713FE05FF2","name":"briefcase-variant","codepoint":"F1494","aliases":[],"tags":[],"author":"Google","version":"5.3.45"},{"id":"2C5F52C7-AC1B-417F-8035-DB25264DA0A4","name":"briefcase-variant-off","codepoint":"F165A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"E89FB55E-396B-4E43-BC41-512B597CF474","name":"briefcase-variant-off-outline","codepoint":"F165B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"5280D1B7-9418-4673-BB9E-6AB3BD640C92","name":"briefcase-variant-outline","codepoint":"F1495","aliases":[],"tags":[],"author":"Google","version":"5.3.45"},{"id":"B3FF12D1-1C76-4E1D-BAD0-468E424BADA7","name":"brightness-1","codepoint":"F00DA","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"FAEBEE4C-295C-475F-AE7D-11CFA4688017","name":"brightness-2","codepoint":"F00DB","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"825E1BB2-1E01-4E6E-9CF0-04412FDECDA6","name":"brightness-3","codepoint":"F00DC","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"10EC7F50-BDC1-45C4-A6D2-2CB5FB4DE902","name":"brightness-4","codepoint":"F00DD","aliases":["theme-light-dark"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"17314413-99ED-480C-B739-8572B6AE5477","name":"brightness-5","codepoint":"F00DE","aliases":["brightness-low"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"34818392-81EE-4210-8F86-9C448596C912","name":"brightness-6","codepoint":"F00DF","aliases":["brightness-medium","theme-light-dark"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"014CCAA3-4B30-4C3D-921C-078A078A5198","name":"brightness-7","codepoint":"F00E0","aliases":["brightness-high"],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"6E47CC3B-6D95-4311-A8DD-7B50AC24781C","name":"brightness-auto","codepoint":"F00E1","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"CBC38577-44FC-45B5-9454-3D04AA9CEAE3","name":"brightness-percent","codepoint":"F0CF2","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"F5E24182-366C-4D23-BA0E-8D2E25B88230","name":"broadcast","codepoint":"F1720","aliases":["signal"],"tags":["Weather"],"author":"Google","version":"5.9.55"},{"id":"E1851914-B294-4FC0-A94B-C5C8D0F52DCB","name":"broadcast-off","codepoint":"F1721","aliases":["signal-off"],"tags":["Weather"],"author":"Google","version":"5.9.55"},{"id":"8159ED8F-4D1C-4845-8297-0FE41260D199","name":"broom","codepoint":"F00E2","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B5C72984-BCCF-4729-A7D3-2A07D5794014","name":"brush","codepoint":"F00E3","aliases":["paintbrush"],"tags":["Drawing \/ Art"],"author":"Google","version":"1.5.54"},{"id":"1024F530-CFE4-4869-BAA4-062593D42DC9","name":"bucket","codepoint":"F1415","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"1A620C83-4D7F-4175-998B-E3460C77510D","name":"bucket-outline","codepoint":"F1416","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"18A94F7F-1BC5-48EC-9CAF-6D2D663287DC","name":"buddhism","codepoint":"F094B","aliases":["dharmachakra","dharma-wheel","religion-buddhist"],"tags":["Religion"],"author":"Nick","version":"2.4.85"},{"id":"FBD11E2A-7F1F-4CE2-B17D-B3623D4FEA43","name":"buffer","codepoint":"F0619","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.6.50"},{"id":"B68F24D9-0E45-4729-9DB9-46E0D73589F2","name":"buffet","codepoint":"F0578","aliases":[],"tags":[],"author":"nilsfast","version":"1.5.54"},{"id":"09A131FB-EE06-49B8-80C3-49B294BCA612","name":"bug","codepoint":"F00E4","aliases":["bug-report"],"tags":["Nature"],"author":"Google","version":"1.5.54"},{"id":"3EDC1018-2B2B-4B3A-AE65-3C74678C807B","name":"bug-check","codepoint":"F0A2E","aliases":["bug-tick"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"1DF96664-B3AE-4028-BB22-C9DE9273A641","name":"bug-check-outline","codepoint":"F0A2F","aliases":["bug-tick-outline"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"CDBE2126-E455-498B-B5CC-945A42F78B0D","name":"bug-outline","codepoint":"F0A30","aliases":[],"tags":["Nature"],"author":"Google","version":"2.6.95"},{"id":"CBC37A12-44AA-4CA8-976A-F26ED26849D4","name":"bugle","codepoint":"F0DB4","aliases":["car-horn"],"tags":["Automotive","Music"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"76D6F847-8DC7-41CB-B88C-9407CC2B18AA","name":"bulldozer","codepoint":"F0B22","aliases":[],"tags":["Hardware \/ Tools"],"author":"Louistwee","version":"2.8.94"},{"id":"AED3CA58-6CAA-45AF-9791-F61AC32DAFBA","name":"bullet","codepoint":"F0CF3","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"094C9BF2-9EEE-434C-9CA9-8280FBDFBEF7","name":"bulletin-board","codepoint":"F00E5","aliases":["notice-board"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"A5D2E199-03A1-4C23-9C63-954D63DEBEB4","name":"bullhorn","codepoint":"F00E6","aliases":["announcement","megaphone"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B48B1E77-750E-4A16-9154-12D25E572A9D","name":"bullhorn-outline","codepoint":"F0B23","aliases":["announcement-outline","megaphone-outline"],"tags":[],"author":"Google","version":"2.8.94"},{"id":"ED26BD4D-ACDB-45DC-A0DA-18ECA3B2008E","name":"bullseye","codepoint":"F05DD","aliases":["target"],"tags":["Sport"],"author":"Simran","version":"1.5.54"},{"id":"FAC8D1F3-C466-41F3-B3BF-A08519BBC909","name":"bullseye-arrow","codepoint":"F08C9","aliases":["target-arrow"],"tags":["Sport"],"author":"Simran","version":"2.3.50"},{"id":"103BB26D-356A-4F6D-9F98-787CEC908FAD","name":"bulma","codepoint":"F12E7","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.8.95"},{"id":"8428337D-0DED-4E4D-8F89-326FCAD97884","name":"bunk-bed","codepoint":"F1302","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"4.8.95"},{"id":"D3DFF539-E101-40B2-BA6D-B62327AFE6AC","name":"bunk-bed-outline","codepoint":"F0097","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"F6516F38-B29E-4CC9-A7E2-706817121D45","name":"bus","codepoint":"F00E7","aliases":["directions-bus"],"tags":["Navigation","Transportation + Road"],"author":"Google","version":"1.5.54"},{"id":"85DD64A3-9215-41F0-9C94-92C180D7BA05","name":"bus-alert","codepoint":"F0A99","aliases":["bus-warning"],"tags":["Alert \/ Error","Transportation + Road"],"author":"Google","version":"2.7.94"},{"id":"44D15383-D6D2-46CC-A977-7921DA98C7E8","name":"bus-articulated-end","codepoint":"F079C","aliases":[],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"5C34E429-3B80-46CD-8DC8-44D5D9769682","name":"bus-articulated-front","codepoint":"F079D","aliases":[],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"B37694EA-F48B-4F48-ACF1-0E48FB334473","name":"bus-clock","codepoint":"F08CA","aliases":["departure-board"],"tags":["Date \/ Time","Transportation + Road"],"author":"Google","version":"2.3.50"},{"id":"1F4327A8-1E93-4490-B992-C9D04DFFB144","name":"bus-double-decker","codepoint":"F079E","aliases":[],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"42DCF950-C2F2-4989-8E0B-ACF16326A6A7","name":"bus-marker","codepoint":"F1212","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"E007EC1E-915B-4A12-89A0-8F7249AEF9FC","name":"bus-multiple","codepoint":"F0F3F","aliases":["fleet"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"3.9.97"},{"id":"774EC563-DF29-498C-8270-ABB051396687","name":"bus-school","codepoint":"F079F","aliases":["education"],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"D944705B-8F7B-441F-8753-6E51E4378D7D","name":"bus-side","codepoint":"F07A0","aliases":[],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"79F04208-0844-4987-9CFA-8870EBB6CD1D","name":"bus-stop","codepoint":"F1012","aliases":[],"tags":["Transportation + Road","Navigation"],"author":"Michael Richins","version":"4.1.95"},{"id":"E299AA19-1C5F-4D7F-B101-0FBFC05A7130","name":"bus-stop-covered","codepoint":"F1013","aliases":[],"tags":["Transportation + Road","Navigation"],"author":"Michael Richins","version":"4.1.95"},{"id":"E1CA2856-1C0E-4487-BAF3-C64A4EA94C45","name":"bus-stop-uncovered","codepoint":"F1014","aliases":[],"tags":["Transportation + Road","Navigation"],"author":"Michael Richins","version":"4.1.95"},{"id":"CC37A3EE-B084-4CD4-AF41-1E5C6D83D839","name":"butterfly","codepoint":"F1589","aliases":[],"tags":["Nature","Animal"],"author":"Nicolas Gres","version":"5.5.55"},{"id":"6BD6BDCD-0C73-40DF-9A9B-127C1DDFF467","name":"butterfly-outline","codepoint":"F158A","aliases":[],"tags":["Nature","Animal"],"author":"Nicolas Gres","version":"5.5.55"},{"id":"1D18C000-0A31-4A28-BA96-B47103D727DD","name":"cable-data","codepoint":"F1394","aliases":[],"tags":[],"author":"GreenTurtwig","version":"5.0.45"},{"id":"7DFE345F-A336-43BC-89BE-18FE3C902BFC","name":"cached","codepoint":"F00E8","aliases":["counterclockwise-arrows","circular-arrows","circle-arrows","sync"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"C7CDAEB3-FE9D-4A53-937B-F778CEA157E0","name":"cactus","codepoint":"F0DB5","aliases":[],"tags":["Nature"],"author":"Andrew Nenakhov","version":"3.5.94"},{"id":"E5BFDCE4-1033-4062-9677-94B95E028B6E","name":"cake","codepoint":"F00E9","aliases":["birthday-cake"],"tags":["Holiday","Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"934C9B6C-0DA5-4D71-9283-C960ED537D02","name":"cake-layered","codepoint":"F00EA","aliases":["birthday-cake"],"tags":["Holiday","Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"2F9E87A6-B7DB-48B1-9528-C8A941FBC3AF","name":"cake-variant","codepoint":"F00EB","aliases":["birthday-cake"],"tags":["Holiday","Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"3E9895C8-BCCB-464C-ACF1-CCA86113DA37","name":"calculator","codepoint":"F00EC","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FB05A4AF-E47A-4F82-BFFE-7C1F587839B6","name":"calculator-variant","codepoint":"F0A9A","aliases":[],"tags":["Math"],"author":"Google","version":"2.7.94"},{"id":"87123F5D-C9AC-43B3-9E97-10EE3F9C1158","name":"calculator-variant-outline","codepoint":"F15A6","aliases":[],"tags":["Math"],"author":"Google","version":"5.5.55"},{"id":"23C8742A-612C-4C55-B184-2A0ABB387746","name":"calendar","codepoint":"F00ED","aliases":["event","insert-invitation"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"CD7D41D2-4BD2-4482-85C2-314A283EB57F","name":"calendar-account","codepoint":"F0ED7","aliases":[],"tags":["Date \/ Time","Account \/ User"],"author":"Michael Richins","version":"3.8.95"},{"id":"B852A287-2C5E-4468-9A83-6B5E0ABD1219","name":"calendar-account-outline","codepoint":"F0ED8","aliases":[],"tags":["Date \/ Time","Account \/ User"],"author":"Michael Richins","version":"3.8.95"},{"id":"38F5B0F1-FAC2-4389-9CE0-BDDEBEC868F4","name":"calendar-alert","codepoint":"F0A31","aliases":["event-alert","calendar-warning"],"tags":["Date \/ Time","Alert \/ Error"],"author":"Simran","version":"2.6.95"},{"id":"9FB11BA5-47F5-40B8-9BD2-259FEA4E0A6E","name":"calendar-arrow-left","codepoint":"F1134","aliases":["reschedule"],"tags":["Date \/ Time"],"author":"Terren","version":"4.4.95"},{"id":"571CF297-7E85-4808-A76A-72952F1A4976","name":"calendar-arrow-right","codepoint":"F1135","aliases":["reschedule"],"tags":["Date \/ Time"],"author":"Terren","version":"4.4.95"},{"id":"57984F1A-6CA5-4928-B221-466C0CC11562","name":"calendar-blank","codepoint":"F00EE","aliases":["calendar-today"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BD09D9F0-FF38-4D14-8798-2CB5091CABE1","name":"calendar-blank-multiple","codepoint":"F1073","aliases":[],"tags":["Date \/ Time"],"author":"James Coyle","version":"4.2.95"},{"id":"9A461143-6DF3-49CB-A238-24CFE7181183","name":"calendar-blank-outline","codepoint":"F0B66","aliases":["event-blank-outline"],"tags":["Date \/ Time"],"author":"Google","version":"3.0.39"},{"id":"62008F88-6B17-4277-9155-B596476629A1","name":"calendar-check","codepoint":"F00EF","aliases":["event-available","calendar-task","calendar-tick","event-tick","event-check"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"62AD0407-3DB5-48B0-8A26-3C5A07C78582","name":"calendar-check-outline","codepoint":"F0C44","aliases":["event-available-outline","event-check-outline","event-tick-outline","calendar-task-outline","calendar-tick-outline"],"tags":["Date \/ Time"],"author":"Google","version":"3.2.89"},{"id":"921F6084-24E6-4D62-8BF9-9258D8FADE8E","name":"calendar-clock","codepoint":"F00F0","aliases":["event-clock","event-time","calendar-time"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9101C5D4-90CA-4C18-B66E-611B3B0A3877","name":"calendar-clock-outline","codepoint":"F16E1","aliases":[],"tags":[],"author":"GreenTurtwig","version":"5.9.55"},{"id":"A5F0BBFB-DA5E-4068-B2D5-3C0F3EB26B14","name":"calendar-cursor","codepoint":"F157B","aliases":[],"tags":["Date \/ Time"],"author":"Google","version":"5.5.55"},{"id":"2976EA1B-60A3-46FB-97E2-95BB74B0DD22","name":"calendar-edit","codepoint":"F08A7","aliases":["event-edit"],"tags":["Date \/ Time","Edit \/ Modify"],"author":"Michael Richins","version":"2.2.43"},{"id":"5837A731-F9AE-433E-AB31-12EE3D2D13D1","name":"calendar-end","codepoint":"F166C","aliases":[],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"5.7.55"},{"id":"14692438-9215-4003-AF95-04AA7C27DA48","name":"calendar-export","codepoint":"F0B24","aliases":[],"tags":["Date \/ Time"],"author":"Michael Richins","version":"2.8.94"},{"id":"EF6AC5FE-7E6E-47AC-B5D8-E802CBB94E3B","name":"calendar-heart","codepoint":"F09D2","aliases":["event-heart"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"2.5.94"},{"id":"04EEB2AA-AB71-4124-8AC4-FA65985AF37E","name":"calendar-import","codepoint":"F0B25","aliases":[],"tags":["Date \/ Time"],"author":"Michael Richins","version":"2.8.94"},{"id":"8189159C-0869-4B40-809C-ECE7C33A2EC0","name":"calendar-lock","codepoint":"F1641","aliases":[],"tags":["Date \/ Time"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"38B4A077-A3EA-4AF2-8553-9888BA25589F","name":"calendar-lock-outline","codepoint":"F1642","aliases":[],"tags":["Date \/ Time"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"12439778-1F4B-4498-8716-5BE128D194E1","name":"calendar-minus","codepoint":"F0D5C","aliases":["event-minus"],"tags":["Date \/ Time"],"author":"Contributors","version":"3.4.93"},{"id":"73BD287F-15E4-46D3-997F-0F2A9E641EE9","name":"calendar-month","codepoint":"F0E17","aliases":[],"tags":["Date \/ Time"],"author":"Terren","version":"3.6.95"},{"id":"80D8D5AB-B9A9-4A26-8E9A-A2D4DBDD77AC","name":"calendar-month-outline","codepoint":"F0E18","aliases":[],"tags":["Date \/ Time"],"author":"Terren","version":"3.6.95"},{"id":"F4851A5B-6F19-4C18-9A13-4BF2617FF0E0","name":"calendar-multiple","codepoint":"F00F1","aliases":["event-multiple","calendars","events"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"7329D294-805D-4843-AB03-B87C661C296A","name":"calendar-multiple-check","codepoint":"F00F2","aliases":["event-multiple-check","calendar-multiple-tick","calendars-check","calendars-tick","event-multiple-tick","events-check","events-tick"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"EFABC8FA-93A2-43FB-A9C3-B03F1324B2E2","name":"calendar-multiselect","codepoint":"F0A32","aliases":[],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"2.6.95"},{"id":"3703C79F-7F34-41D6-A12F-6247144FEB02","name":"calendar-outline","codepoint":"F0B67","aliases":["event-outline"],"tags":["Date \/ Time"],"author":"Google","version":"3.0.39"},{"id":"34AFE807-D724-4A5A-A3FE-910928179BE8","name":"calendar-plus","codepoint":"F00F3","aliases":["event-plus","calendar-add","event-add"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1A7293FC-E6E7-4C86-8919-32D0C5F60B08","name":"calendar-question","codepoint":"F0692","aliases":["calendar-rsvp","event-question"],"tags":["Date \/ Time"],"author":"Simran","version":"1.7.12"},{"id":"740D7A91-7492-4922-96C7-A719E2BCD62A","name":"calendar-range","codepoint":"F0679","aliases":["date-range","calendar-week","event-range"],"tags":["Date \/ Time"],"author":"Google","version":"1.7.12"},{"id":"CD7FA7FC-1BB0-4DB6-82C6-DF13E5A55EB2","name":"calendar-range-outline","codepoint":"F0B68","aliases":["event-range-outline"],"tags":["Date \/ Time"],"author":"Google","version":"3.0.39"},{"id":"4147C0BC-E3AE-4324-AA38-D2EC7A7AAD5E","name":"calendar-refresh","codepoint":"F01E1","aliases":["calendar-repeat"],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"BC0BD74D-06D4-458A-B0CE-90B96A2ADCBF","name":"calendar-refresh-outline","codepoint":"F0203","aliases":["calendar-repeat-outline"],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"2FAF3098-4BD1-4C70-94A8-F75E1EA54F49","name":"calendar-remove","codepoint":"F00F4","aliases":["event-busy","event-remove"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"10475FB2-142C-48FF-AB95-B93CF2680208","name":"calendar-remove-outline","codepoint":"F0C45","aliases":["event-busy-outline","event-remove-outline"],"tags":["Date \/ Time"],"author":"Google","version":"3.2.89"},{"id":"1C61A1FD-56B6-41F1-B677-84D32425225A","name":"calendar-search","codepoint":"F094C","aliases":["event-search"],"tags":["Date \/ Time"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"96505BCC-D522-45A6-A642-85F1B4248FAA","name":"calendar-star","codepoint":"F09D3","aliases":["event-star"],"tags":["Date \/ Time"],"author":"Michael Richins","version":"2.5.94"},{"id":"D88F139B-9D00-462D-8AA5-C23A5A02FCC6","name":"calendar-start","codepoint":"F166D","aliases":[],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"5.7.55"},{"id":"7343C074-F974-4083-89C5-3C2BABF4E3C9","name":"calendar-sync","codepoint":"F0E8E","aliases":["calendar-repeat"],"tags":["Date \/ Time"],"author":"Michael Richins","version":"3.7.94"},{"id":"24C0F48E-A354-4835-A2D4-B1E348ACF5D5","name":"calendar-sync-outline","codepoint":"F0E8F","aliases":["calendar-repeat-outline"],"tags":["Date \/ Time"],"author":"Michael Richins","version":"3.7.94"},{"id":"1A873476-B82D-4E23-BF19-897F0A0C0B93","name":"calendar-text","codepoint":"F00F5","aliases":["event-note","event-text"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"F49AE0DB-5AAF-4574-BF4C-121E99A95BEF","name":"calendar-text-outline","codepoint":"F0C46","aliases":["event-text-outline","event-note-outline"],"tags":["Date \/ Time"],"author":"Google","version":"3.2.89"},{"id":"A566BA98-D35A-443F-AD31-0D31EF0B85EC","name":"calendar-today","codepoint":"F00F6","aliases":["calendar-day"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"F2D23B1E-EA12-4EF5-9365-E698D1CD1319","name":"calendar-week","codepoint":"F0A33","aliases":["event-week"],"tags":["Date \/ Time"],"author":"Simran","version":"2.6.95"},{"id":"7C244D7F-9332-4C73-AF3D-1DE3F6E365ED","name":"calendar-week-begin","codepoint":"F0A34","aliases":["event-week-begin"],"tags":["Date \/ Time"],"author":"Simran","version":"2.6.95"},{"id":"E873A542-F4E7-44F4-B7CD-19474188D5BC","name":"calendar-weekend","codepoint":"F0ED9","aliases":[],"tags":["Date \/ Time"],"author":"Crissov","version":"3.8.95"},{"id":"3E8B49C8-08CA-4D96-BC1B-EB21909E0311","name":"calendar-weekend-outline","codepoint":"F0EDA","aliases":[],"tags":["Date \/ Time"],"author":"Crissov","version":"3.8.95"},{"id":"B5ACE913-DBF1-4E73-BFE5-BB86F0EBF76E","name":"call-made","codepoint":"F00F7","aliases":[],"tags":["Cellphone \/ Phone","Arrow"],"author":"Google","version":"1.5.54"},{"id":"8BEE5A5E-EC0A-4FC5-96BE-7F8C2A2EE52F","name":"call-merge","codepoint":"F00F8","aliases":["merge-type"],"tags":["Cellphone \/ Phone","Arrow"],"author":"Google","version":"1.5.54"},{"id":"CA2546B9-70B0-4E1A-B646-17163B0C76E4","name":"call-missed","codepoint":"F00F9","aliases":[],"tags":["Cellphone \/ Phone","Arrow"],"author":"Google","version":"1.5.54"},{"id":"008CD0E5-C47B-44FB-AF43-A1221C527056","name":"call-received","codepoint":"F00FA","aliases":[],"tags":["Cellphone \/ Phone","Arrow"],"author":"Google","version":"1.5.54"},{"id":"790BCBB6-8B08-4AEC-A322-99F584BB394B","name":"call-split","codepoint":"F00FB","aliases":[],"tags":["Cellphone \/ Phone","Arrow"],"author":"Google","version":"1.5.54"},{"id":"89EE8EAB-CA5B-40C5-B114-1EC5248634BF","name":"camcorder","codepoint":"F00FC","aliases":[],"tags":["Video \/ Movie"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BE1C767B-C032-487C-AB85-E2E960C9A89D","name":"camcorder-off","codepoint":"F00FF","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"236D9E8E-E38C-4EA9-9539-0E8B1447003A","name":"camera","codepoint":"F0100","aliases":["photography","camera-alt","local-see","photo-camera"],"tags":["Photography","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"E6F67D5D-0EED-450C-B39F-75D37E9B63CA","name":"camera-account","codepoint":"F08CB","aliases":["camera-user"],"tags":["Account \/ User","Photography"],"author":"Google","version":"2.3.50"},{"id":"4FCD7DBE-6B4C-41DB-BDD8-40ED820EC7F1","name":"camera-burst","codepoint":"F0693","aliases":["burst-mode"],"tags":["Photography"],"author":"Google","version":"1.7.12"},{"id":"28AACAD9-8E72-41FA-B736-55A4AFDAD6FF","name":"camera-control","codepoint":"F0B69","aliases":[],"tags":["Photography"],"author":"Google","version":"3.0.39"},{"id":"45456446-14D9-49F2-8842-93BAF8233F47","name":"camera-enhance","codepoint":"F0101","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"5D466962-4E59-4103-8556-25032439677A","name":"camera-enhance-outline","codepoint":"F0B6A","aliases":[],"tags":["Photography"],"author":"Google","version":"3.0.39"},{"id":"D4175840-8B51-4C1E-AFF2-A8142F5CCF2E","name":"camera-flip","codepoint":"F15D9","aliases":["camera-sync","camera-refresh"],"tags":["Photography"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"A40CFB47-3650-42BF-874C-C5BF09641708","name":"camera-flip-outline","codepoint":"F15DA","aliases":["camera-sync-outline","camera-refresh-outline"],"tags":["Photography"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"574F4B2D-70FE-41E3-AFB4-EC1E2AB897AB","name":"camera-front","codepoint":"F0102","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"2C6477B5-AA9E-4EDD-A73A-79F2ED5E5F2A","name":"camera-front-variant","codepoint":"F0103","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"B4EDBFFC-CF00-45F3-93A7-6ADD45108FEE","name":"camera-gopro","codepoint":"F07A1","aliases":[],"tags":["Photography","Device \/ Tech"],"author":"Michael Richins","version":"2.0.46"},{"id":"3399CF92-5E35-4C1A-A796-FB641666AB63","name":"camera-image","codepoint":"F08CC","aliases":[],"tags":["Photography"],"author":"Google","version":"2.3.50"},{"id":"E011977B-432E-470C-A4F6-9C7A4F8BB519","name":"camera-iris","codepoint":"F0104","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"D178034B-0B93-40F5-BBF1-D28B25A86647","name":"camera-metering-center","codepoint":"F07A2","aliases":["camera-metering-centre"],"tags":["Photography"],"author":"Andy Martinez","version":"2.0.46"},{"id":"700D143A-8347-4A79-9EF8-844E1B436524","name":"camera-metering-matrix","codepoint":"F07A3","aliases":[],"tags":["Photography"],"author":"Andy Martinez","version":"2.0.46"},{"id":"EA33D5EE-5E13-4D82-A552-C3B16772926F","name":"camera-metering-partial","codepoint":"F07A4","aliases":[],"tags":["Photography"],"author":"Andy Martinez","version":"2.0.46"},{"id":"C1313085-6C7F-4D60-A278-A39361B57DA9","name":"camera-metering-spot","codepoint":"F07A5","aliases":[],"tags":["Photography"],"author":"Andy Martinez","version":"2.0.46"},{"id":"461A25B1-59F6-49F1-A917-BED92315AA63","name":"camera-off","codepoint":"F05DF","aliases":[],"tags":["Photography"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5ABA45CF-038B-4665-BC3B-7D34CEF3882E","name":"camera-outline","codepoint":"F0D5D","aliases":[],"tags":["Photography"],"author":"Google","version":"3.4.93"},{"id":"B58A0D5C-B137-42DD-A43B-8DD296D7684A","name":"camera-party-mode","codepoint":"F0105","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"262BE971-8B8E-4DAC-8897-A841E5EBEB27","name":"camera-plus","codepoint":"F0EDB","aliases":[],"tags":["Photography"],"author":"Google","version":"3.8.95"},{"id":"AD12EDBC-2323-410D-B0F2-F84ED6AEC170","name":"camera-plus-outline","codepoint":"F0EDC","aliases":[],"tags":["Photography"],"author":"Google","version":"3.8.95"},{"id":"B4CA0FB9-D119-426C-9043-16D90F5086B8","name":"camera-rear","codepoint":"F0106","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"B7DB5F20-5D64-4096-959F-60BB040B320F","name":"camera-rear-variant","codepoint":"F0107","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"CA03F06D-AD3C-4D69-B6A4-721668AB111C","name":"camera-retake","codepoint":"F0E19","aliases":[],"tags":["Photography"],"author":"Michael Richins","version":"3.6.95"},{"id":"0C602606-75CC-4D76-B79B-6550127ED464","name":"camera-retake-outline","codepoint":"F0E1A","aliases":[],"tags":["Photography"],"author":"Michael Richins","version":"3.6.95"},{"id":"68BB6884-5CEA-4B2A-8F22-46B6A98CDA75","name":"camera-switch","codepoint":"F0108","aliases":["switch-camera"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"CABA2832-65F9-4196-9681-51C5E2C1CFB2","name":"camera-switch-outline","codepoint":"F084A","aliases":[],"tags":["Photography"],"author":"Google","version":"2.1.99"},{"id":"6A8FC2AF-724C-46A2-9F04-C34E7D658679","name":"camera-timer","codepoint":"F0109","aliases":[],"tags":["Date \/ Time","Photography"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5125EF68-0BAB-4C17-BA18-022EAAAE36D5","name":"camera-wireless","codepoint":"F0DB6","aliases":[],"tags":["Photography"],"author":"Google","version":"3.5.94"},{"id":"A8BB090E-25FC-4517-A1C9-B2AA1ABD8AFA","name":"camera-wireless-outline","codepoint":"F0DB7","aliases":[],"tags":["Photography"],"author":"Google","version":"3.5.94"},{"id":"E5958680-B397-40E1-BDB0-49B05339C973","name":"campfire","codepoint":"F0EDD","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"02F70DD2-E16E-43FD-9C2A-267C965E3919","name":"cancel","codepoint":"F073A","aliases":["prohibited","ban","do-not-disturb-alt","denied","block","forbid","no","clear"],"tags":[],"author":"Google","version":"1.9.32"},{"id":"4FB0AA38-406A-4877-8B0C-15C7ED95F22C","name":"candle","codepoint":"F05E2","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8CAC723B-0FF5-493B-A3A2-5772FDE46A0F","name":"candycane","codepoint":"F010A","aliases":[],"tags":["Holiday","Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4C2DC909-0C3F-431F-A37B-5B66C9F33E37","name":"cannabis","codepoint":"F07A6","aliases":["weed","pot","marijuana"],"tags":["Nature","Medical \/ Hospital"],"author":"Austin Andrews","version":"2.0.46"},{"id":"1DA6A01B-2804-4C68-A60E-20DBBB6938E5","name":"cannabis-off","codepoint":"F166E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"74D4E706-53B2-4349-95B2-026B3057D9B2","name":"caps-lock","codepoint":"F0A9B","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"FCF4FF57-4547-4C11-A20A-3D26252780EC","name":"car","codepoint":"F010B","aliases":["directions-car","drive-eta","time-to-leave"],"tags":["Transportation + Road","Navigation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"02A38C46-7F26-4A95-9025-33181E528B1C","name":"car-2-plus","codepoint":"F1015","aliases":["hov-lane","high-occupancy-vehicle-lane","carpool-lane"],"tags":["Transportation + Road","Automotive"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"9E971816-54E0-4C43-A6BB-AD821E17DC30","name":"car-3-plus","codepoint":"F1016","aliases":["hov-lane","high-occupancy-vehicle-lane","carpool-lane"],"tags":["Transportation + Road","Automotive"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"F647E77D-3416-4DFD-8E9C-0BB1A1FDA6A8","name":"car-arrow-left","codepoint":"F13B2","aliases":[],"tags":["Automotive","Transportation + Road"],"author":"Michael Irigoyen","version":"5.0.45"},{"id":"04AA17AE-F0E4-4B44-9440-812E1F875884","name":"car-arrow-right","codepoint":"F13B3","aliases":[],"tags":["Automotive","Transportation + Road"],"author":"Michael Irigoyen","version":"5.0.45"},{"id":"E41B22B2-CAC1-4D56-877B-2DC4E5E4BEC2","name":"car-back","codepoint":"F0E1B","aliases":[],"tags":["Automotive","Transportation + Road"],"author":"Michael Richins","version":"3.6.95"},{"id":"4AF128D8-1E70-4396-BB5A-F96A7D0F9BCB","name":"car-battery","codepoint":"F010C","aliases":[],"tags":["Battery","Automotive"],"author":"Simran","version":"1.5.54"},{"id":"170D1972-AFA7-417C-BCC4-B07689D8B6F4","name":"car-brake-abs","codepoint":"F0C47","aliases":["anti-lock-brake-system","anti-lock-braking-system"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"843DC5E8-723D-44A1-A959-A49C662712D1","name":"car-brake-alert","codepoint":"F0C48","aliases":["car-parking-brake","car-handbrake","car-hand-brake","car-emergency-brake","car-brake-warning"],"tags":["Automotive","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"4F3D37E3-F34C-4720-BC92-1173A85F88FC","name":"car-brake-hold","codepoint":"F0D5E","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"CBCA05E4-718D-4727-8A1B-EDA815D00AE1","name":"car-brake-parking","codepoint":"F0D5F","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"8627DD5D-1BE6-4FBB-81A6-7D40ED3C1E69","name":"car-brake-retarder","codepoint":"F1017","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"6A83FE13-CCAF-473E-B660-F2AD8EE561AD","name":"car-child-seat","codepoint":"F0FA3","aliases":[],"tags":["Automotive","People \/ Family"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"862F1CFE-643B-44BB-9B46-33BF1C75CEE2","name":"car-clutch","codepoint":"F1018","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"B854CD8C-6731-4C70-917F-9033015E94F4","name":"car-cog","codepoint":"F13CC","aliases":["car-settings"],"tags":["Automotive","Settings","Transportation + Road"],"author":"Simran","version":"5.1.45"},{"id":"8C8468C7-8A41-42A1-8C33-4AAE55FF9E2A","name":"car-connected","codepoint":"F010D","aliases":[],"tags":["Transportation + Road","Automotive"],"author":"Simran","version":"1.5.54"},{"id":"D7E88B5B-B6F3-4C55-AE93-39A78593B351","name":"car-convertible","codepoint":"F07A7","aliases":[],"tags":["Transportation + Road","Automotive"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"1DA47513-FB2A-4A20-926F-3D2E90D40F26","name":"car-coolant-level","codepoint":"F1019","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"7FCD959A-B0AA-43AD-B448-5B51A1A2C023","name":"car-cruise-control","codepoint":"F0D60","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"1B289520-CE81-4385-88B3-923CB0FD6233","name":"car-defrost-front","codepoint":"F0D61","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"8B6938C0-6C97-41A4-A22F-83D6A9F1AC3F","name":"car-defrost-rear","codepoint":"F0D62","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"AA43B04E-7C56-4DFB-83FC-081E3A4A3F48","name":"car-door","codepoint":"F0B6B","aliases":[],"tags":["Automotive"],"author":"Austin Andrews","version":"3.0.39"},{"id":"76A1EC75-D6D2-465E-89F7-EBE2AF145C4C","name":"car-door-lock","codepoint":"F109D","aliases":[],"tags":["Automotive","Lock"],"author":"Michael Richins","version":"4.2.95"},{"id":"48583637-1477-451A-8E75-765EC4EB0585","name":"car-electric","codepoint":"F0B6C","aliases":[],"tags":["Transportation + Road","Automotive"],"author":"Google","version":"3.0.39"},{"id":"D97919E2-BB44-4ABE-86AB-68CD49AC4BE7","name":"car-electric-outline","codepoint":"F15B5","aliases":[],"tags":["Transportation + Road"],"author":"Google","version":"5.6.55"},{"id":"355D6842-8858-4C79-B684-0E0F5E03801D","name":"car-emergency","codepoint":"F160F","aliases":["car-police"],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"5.6.55"},{"id":"5BF118F1-1115-4928-8755-34AF926CF13D","name":"car-esp","codepoint":"F0C49","aliases":["electronic-stability-program"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"90BBBADD-0FCD-4147-9D6E-5DAFCACF2B0B","name":"car-estate","codepoint":"F07A8","aliases":["car-suv","car-sports-utility-vehicle"],"tags":["Transportation + Road","Automotive"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"21A2527E-9AC0-4FFA-84CB-246608BEB91D","name":"car-hatchback","codepoint":"F07A9","aliases":[],"tags":["Transportation + Road","Automotive"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"6C179C94-30C5-4DD8-B80E-9FFF69ABE0E1","name":"car-info","codepoint":"F11BE","aliases":[],"tags":["Automotive"],"author":"Michael Richins","version":"4.5.95"},{"id":"3B659932-957C-4DD8-81CF-7ECABC572BFC","name":"car-key","codepoint":"F0B6D","aliases":["car-rental","rent-a-car"],"tags":["Transportation + Road","Automotive"],"author":"GreenTurtwig","version":"3.0.39"},{"id":"10F38BAD-F9E1-4715-9BE9-3784C788D59A","name":"car-lifted-pickup","codepoint":"F152D","aliases":[],"tags":["Automotive"],"author":"Austin Andrews","version":"5.4.55"},{"id":"DA708BEF-4826-49CF-8872-C42996C9616F","name":"car-light-dimmed","codepoint":"F0C4A","aliases":["head-light-dimmed","low-beam"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"3DAC6713-744B-485F-A985-7E2A16F14D6A","name":"car-light-fog","codepoint":"F0C4B","aliases":["head-light-fog"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"7EF72FB8-3767-495E-9F80-888F6924B856","name":"car-light-high","codepoint":"F0C4C","aliases":["head-light-high","high-beam"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"43758944-946B-4883-A77C-F6F28F175920","name":"car-limousine","codepoint":"F08CD","aliases":[],"tags":["Transportation + Road","Automotive"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"B31CB4B0-9987-4F99-8409-FA4601E34064","name":"car-multiple","codepoint":"F0B6E","aliases":[],"tags":["Transportation + Road","Automotive"],"author":"Michael Richins","version":"3.0.39"},{"id":"5426595C-DCD3-4CFE-990E-775C80BDCDC6","name":"car-off","codepoint":"F0E1C","aliases":[],"tags":["Automotive"],"author":"Michael Richins","version":"3.6.95"},{"id":"8EDBF463-60A3-4F49-9198-B52F8E6FB68B","name":"car-outline","codepoint":"F14ED","aliases":[],"tags":["Automotive"],"author":"Google","version":"5.4.55"},{"id":"03116932-7E19-45C7-9E34-02308FCDD7F4","name":"car-parking-lights","codepoint":"F0D63","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"76BB371D-335C-4F53-A439-2A681778C6BC","name":"car-pickup","codepoint":"F07AA","aliases":[],"tags":["Transportation + Road","Automotive"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"F0D6A2CA-711D-440E-B4A2-586C071E1192","name":"car-seat","codepoint":"F0FA4","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"3B08983F-F281-48F5-8A34-383591971006","name":"car-seat-cooler","codepoint":"F0FA5","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"300D30D3-28E2-4D45-A31D-9FF1E92AC5BE","name":"car-seat-heater","codepoint":"F0FA6","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"4ED4D6FD-9E30-4D99-9FD0-11B316BACB96","name":"car-settings","codepoint":"F13CD","aliases":[],"tags":["Automotive","Settings"],"author":"Simran","version":"5.1.45"},{"id":"DF11B72C-D029-49BB-9657-6A267CC1DEA4","name":"car-shift-pattern","codepoint":"F0F40","aliases":["car-transmission","car-manual-transmission"],"tags":["Automotive"],"author":"Colton Wiscombe","version":"3.9.97"},{"id":"CB49A868-3317-4445-BFED-13CB6533000E","name":"car-side","codepoint":"F07AB","aliases":["car-saloon"],"tags":["Transportation + Road","Automotive"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"97F5ED58-F2AB-40AC-A882-4A90DB5D2018","name":"car-sports","codepoint":"F07AC","aliases":[],"tags":["Transportation + Road","Sport","Automotive"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"93700192-0A90-4FC4-944C-894F29BB478F","name":"car-tire-alert","codepoint":"F0C4D","aliases":["car-tyre-alert","car-tyre-warning","car-tire-warning"],"tags":["Automotive","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"D9DC5111-14E6-4585-A79B-489FC04C1CE3","name":"car-traction-control","codepoint":"F0D64","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"1D1E80DE-A3A0-4487-9A94-7C9C3F5E0A59","name":"car-turbocharger","codepoint":"F101A","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"95E617D7-9A48-458E-96C5-A8CBBEF3A852","name":"car-wash","codepoint":"F010E","aliases":["local-car-wash"],"tags":["Transportation + Road","Places","Automotive"],"author":"Google","version":"1.5.54"},{"id":"6E8AA995-39A0-44C4-A0FF-3BC1CA7787DE","name":"car-windshield","codepoint":"F101B","aliases":["car-front-glass"],"tags":["Automotive"],"author":"Michael Richins","version":"4.1.95"},{"id":"55F7CDA2-F41C-42C4-8154-1F8B1C603F25","name":"car-windshield-outline","codepoint":"F101C","aliases":["car-front-glass-outline"],"tags":["Automotive"],"author":"Michael Richins","version":"4.1.95"},{"id":"077EABE1-1DBC-4AC9-AA0E-B45386391968","name":"carabiner","codepoint":"F14C0","aliases":["karabiner","rock-climbing"],"tags":["Sport"],"author":"Google","version":"5.3.45"},{"id":"2E5B9249-0FFB-48D0-8A61-2019FD9ED32F","name":"caravan","codepoint":"F07AD","aliases":[],"tags":["Transportation + Road","Home Automation","Automotive"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"AB226798-9B8A-4929-8880-6665C1114776","name":"card","codepoint":"F0B6F","aliases":["button"],"tags":["Form"],"author":"Rynco Li","version":"3.0.39"},{"id":"4ACD18FB-87D4-46F1-9231-8BD0A91867A9","name":"card-account-details","codepoint":"F05D2","aliases":["identification-card","user-card-details","id-card","person-card-details","drivers-license","business-card"],"tags":["Account \/ User"],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"6BD2BC65-C99A-42FB-A37E-85F5E8C91D32","name":"card-account-details-outline","codepoint":"F0DAB","aliases":["identification-card-outline","user-card-details-outline","id-card-outline","person-card-details-outline","drivers-license-outline","business-card-outline"],"tags":["Account \/ User"],"author":"Michael Richins","version":"3.5.94"},{"id":"951C68F1-876F-440E-A4D9-B724BB6D6181","name":"card-account-details-star","codepoint":"F02A3","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"1.5.54"},{"id":"97C9CAC2-9F94-40EA-9A08-1A9BDD208743","name":"card-account-details-star-outline","codepoint":"F06DB","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"1.8.36"},{"id":"81840940-8672-42C0-B657-15E94B3638D6","name":"card-account-mail","codepoint":"F018E","aliases":["contact-mail"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"F43579AB-0098-44B4-910C-3B24193C3B79","name":"card-account-mail-outline","codepoint":"F0E98","aliases":["contact-mail-outline"],"tags":["Account \/ User"],"author":"Google","version":"3.7.94"},{"id":"D992EB08-7BDB-4D44-B3C1-A123F80C17FA","name":"card-account-phone","codepoint":"F0E99","aliases":["contact-phone"],"tags":["Account \/ User"],"author":"Google","version":"3.7.94"},{"id":"ABC0498A-9F66-489B-A78E-91B3415EE3E4","name":"card-account-phone-outline","codepoint":"F0E9A","aliases":["contact-phone-outline"],"tags":["Account \/ User"],"author":"Google","version":"3.7.94"},{"id":"BFFB5C41-DA26-4980-8B25-1DCB21B4673E","name":"card-bulleted","codepoint":"F0B70","aliases":[],"tags":[],"author":"Rynco Li","version":"3.0.39"},{"id":"487C3E75-13DF-4C18-98E4-55CB048367EA","name":"card-bulleted-off","codepoint":"F0B71","aliases":[],"tags":[],"author":"Rynco Li","version":"3.0.39"},{"id":"A6845501-AB5C-4511-863D-25E6E0F4F74C","name":"card-bulleted-off-outline","codepoint":"F0B72","aliases":[],"tags":[],"author":"Rynco Li","version":"3.0.39"},{"id":"5A5D5F82-1BBA-4661-A4B7-6AC29484EBB3","name":"card-bulleted-outline","codepoint":"F0B73","aliases":[],"tags":[],"author":"Rynco Li","version":"3.0.39"},{"id":"A8645D1A-6D02-401F-82F6-2564C6EC20D8","name":"card-bulleted-settings","codepoint":"F0B74","aliases":[],"tags":["Settings"],"author":"Rynco Li","version":"3.0.39"},{"id":"5C008C35-201B-4DDB-A37B-6E513C9304F2","name":"card-bulleted-settings-outline","codepoint":"F0B75","aliases":[],"tags":["Settings"],"author":"Rynco Li","version":"3.0.39"},{"id":"7538FC94-FD58-41FD-9585-1F6B6A0AA784","name":"card-minus","codepoint":"F1600","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"DBAC0B3F-A11E-4BFF-B5A5-802C28802CFC","name":"card-minus-outline","codepoint":"F1601","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"B426A851-795C-4627-9F65-EF585020DE63","name":"card-off","codepoint":"F1602","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"DD1C1DF5-C30E-421A-9FA7-AC8F0D021B95","name":"card-off-outline","codepoint":"F1603","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"EB9242D1-9D25-4141-A1A0-06636EC84541","name":"card-outline","codepoint":"F0B76","aliases":["button-outline"],"tags":["Form"],"author":"Rynco Li","version":"3.0.39"},{"id":"3B4FC4CD-DB60-407A-B230-C6CA593977DD","name":"card-plus","codepoint":"F11FF","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"DD8BE7C3-7AE2-420C-8DA2-B3AA4EEC5614","name":"card-plus-outline","codepoint":"F1200","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"6902F560-9012-4F0B-8E93-6B0B7641C019","name":"card-remove","codepoint":"F1604","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"84C0BF2A-B9FB-4E01-9961-A4146CB9BCC3","name":"card-remove-outline","codepoint":"F1605","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"2A09F869-B221-4ABC-B803-16560B7BA900","name":"card-search","codepoint":"F1074","aliases":["pageview"],"tags":[],"author":"Google","version":"4.2.95"},{"id":"3EE58157-57AF-420D-9F5B-C545BCE7D395","name":"card-search-outline","codepoint":"F1075","aliases":["pageview-outline"],"tags":[],"author":"Google","version":"4.2.95"},{"id":"EF0C4465-ACEB-44FA-BA7F-A0422E4481F6","name":"card-text","codepoint":"F0B77","aliases":[],"tags":[],"author":"Rynco Li","version":"3.0.39"},{"id":"45A9D669-8244-476D-A148-21EAB63F819B","name":"card-text-outline","codepoint":"F0B78","aliases":[],"tags":[],"author":"Rynco Li","version":"3.0.39"},{"id":"7E04A92C-1DC5-4A5F-84B0-57A50545EBE4","name":"cards","codepoint":"F0638","aliases":[],"tags":["Gaming \/ RPG"],"author":"Simran","version":"1.6.50"},{"id":"FD5114FD-37CB-4346-BC73-58E1EED49CF3","name":"cards-club","codepoint":"F08CE","aliases":["suit-clubs","poker-club"],"tags":["Gaming \/ RPG"],"author":"Nick","version":"2.3.50"},{"id":"0934FB0D-8585-4064-989F-054E52D16FDB","name":"cards-diamond","codepoint":"F08CF","aliases":["suit-diamonds","hov-lane","high-occupancy-vehicle-lane","carpool-lane","poker-diamond"],"tags":["Gaming \/ RPG","Transportation + Road"],"author":"Nick","version":"2.3.50"},{"id":"529FA74E-39AF-4AF4-BAD3-637FDFBD53AE","name":"cards-diamond-outline","codepoint":"F101D","aliases":["hov-lane-outline","high-occupancy-vehicle-lane-outline","carpool-lane-outline","poker-diamond-outline"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"4.1.95"},{"id":"152E7662-6FDD-478C-A945-68F6B04CB073","name":"cards-heart","codepoint":"F08D0","aliases":["suit-hearts","poker-heart"],"tags":["Gaming \/ RPG"],"author":"Nick","version":"2.3.50"},{"id":"BB07EFB4-5078-47BA-B441-93D4957AF7F9","name":"cards-outline","codepoint":"F0639","aliases":[],"tags":["Gaming \/ RPG"],"author":"Simran","version":"1.6.50"},{"id":"C388C342-49AA-4577-A968-12BD804E5A8E","name":"cards-playing-outline","codepoint":"F063A","aliases":[],"tags":["Gaming \/ RPG"],"author":"Simran","version":"1.6.50"},{"id":"B2DEB97A-B08E-4E10-8E24-A4AF2CF98C74","name":"cards-spade","codepoint":"F08D1","aliases":["suit-spades","poker-spade"],"tags":["Gaming \/ RPG"],"author":"Nick","version":"2.3.50"},{"id":"A000BD20-147F-43FB-AD99-08AE6BA2E80B","name":"cards-variant","codepoint":"F06C7","aliases":[],"tags":["Gaming \/ RPG"],"author":"Case Sandberg","version":"1.8.36"},{"id":"6BD10A61-9A45-4A5A-ABEF-404135975917","name":"carrot","codepoint":"F010F","aliases":[],"tags":["Agriculture","Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"97563623-CF1C-43AE-87D8-DF54802D442B","name":"cart","codepoint":"F0110","aliases":["trolley","local-grocery-store","shopping-cart"],"tags":["Shopping"],"author":"Google","version":"1.5.54"},{"id":"0DCB3032-271E-4522-ABEE-386F49E6B4ED","name":"cart-arrow-down","codepoint":"F0D66","aliases":["shopping-cart-arrow-down","trolley-arrow-down"],"tags":["Shopping"],"author":"Simran","version":"3.4.93"},{"id":"31173BE4-3D5E-45EB-BD45-3D19E86AF6B2","name":"cart-arrow-right","codepoint":"F0C4E","aliases":["trolley-arrow-right","shopping-cart-arrow-right"],"tags":["Shopping"],"author":"Michael Richins","version":"3.2.89"},{"id":"8ED82219-BC37-41C0-9012-E316AB7BD809","name":"cart-arrow-up","codepoint":"F0D67","aliases":["shopping-cart-arrow-up","trolley-arrow-up"],"tags":["Shopping"],"author":"Simran","version":"3.4.93"},{"id":"549C956B-9A3A-489B-BBC3-F9FF7AF0EB14","name":"cart-check","codepoint":"F15EA","aliases":[],"tags":["Shopping"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"D4AF47D5-214B-4856-8450-0ED7C524991D","name":"cart-minus","codepoint":"F0D68","aliases":["shopping-cart-minus","trolley-minus"],"tags":["Shopping"],"author":"Simran","version":"3.4.93"},{"id":"05455801-C523-420A-A961-868ABA3DF636","name":"cart-off","codepoint":"F066B","aliases":["trolley-off","remove-shopping-cart","shopping-cart-off"],"tags":["Shopping"],"author":"Google","version":"1.6.50"},{"id":"F290ABB0-4CD2-4C45-B543-E3AEBA1FE358","name":"cart-outline","codepoint":"F0111","aliases":["trolley-outline","shopping-cart-outline"],"tags":["Shopping"],"author":"Google","version":"1.5.54"},{"id":"2BF13245-A7BF-49EC-8EB0-CA10F7AF11B2","name":"cart-plus","codepoint":"F0112","aliases":["trolley-plus","add-shopping-cart","shopping-cart-plus","cart-add","trolley-add","shopping-cart-add"],"tags":["Shopping"],"author":"Google","version":"1.5.54"},{"id":"DCB745AA-0ECB-4584-88DA-52CC447555A0","name":"cart-remove","codepoint":"F0D69","aliases":["trolley-remove","shopping-cart-remove"],"tags":["Shopping"],"author":"Simran","version":"3.4.93"},{"id":"E7E79B59-68A1-4629-9353-A2E64A4A18B4","name":"cart-variant","codepoint":"F15EB","aliases":[],"tags":["Shopping"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"250BE86F-4D41-4F22-AECD-DD8A2533DA62","name":"case-sensitive-alt","codepoint":"F0113","aliases":[],"tags":[],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"59956D81-BF6B-4DCA-ABAD-A890412F22F1","name":"cash","codepoint":"F0114","aliases":["money"],"tags":["Currency","Banking","Shopping"],"author":"Austin Andrews","version":"1.5.54"},{"id":"18E513D3-5D34-4A4B-B600-D7173CB30DDA","name":"cash-100","codepoint":"F0115","aliases":["money-100"],"tags":["Currency","Banking"],"author":"Google","version":"1.5.54"},{"id":"4AF1798E-6400-40B9-8DAB-4482C07C62E9","name":"cash-check","codepoint":"F14EE","aliases":[],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"03BA1D57-6374-41F7-A781-C0615B91178B","name":"cash-lock","codepoint":"F14EA","aliases":[],"tags":["Lock"],"author":"Austin Andrews","version":"5.4.55"},{"id":"C9CB2DC9-3F57-4D99-81D8-154F348746E5","name":"cash-lock-open","codepoint":"F14EB","aliases":[],"tags":["Lock"],"author":"Austin Andrews","version":"5.4.55"},{"id":"080E0DBC-A7E4-40C0-A126-9CE83BDE2FDF","name":"cash-marker","codepoint":"F0DB8","aliases":["cod","cash-on-delivery"],"tags":["Banking"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"20240E77-778A-4B82-9975-585C647AE81C","name":"cash-minus","codepoint":"F1260","aliases":[],"tags":[],"author":"Contributors","version":"4.7.95"},{"id":"80D4170E-FDA3-40D0-9B05-1020D5FCA817","name":"cash-multiple","codepoint":"F0116","aliases":["money"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C2E340E3-EA0A-4726-B595-6149C8C662B8","name":"cash-plus","codepoint":"F1261","aliases":[],"tags":[],"author":"Contributors","version":"4.7.95"},{"id":"EADBBD96-B2BD-4C31-969E-BFBA6DF519B1","name":"cash-refund","codepoint":"F0A9C","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"2.7.94"},{"id":"6B63F864-415A-4679-9126-363E5254B175","name":"cash-register","codepoint":"F0CF4","aliases":["till"],"tags":["Shopping"],"author":"Contributors","version":"3.3.92"},{"id":"C4DA23E6-9BE6-490B-83FB-B39A3E22E9E1","name":"cash-remove","codepoint":"F1262","aliases":[],"tags":[],"author":"Contributors","version":"4.7.95"},{"id":"22ECB099-6A57-4DA8-9E42-0E3D8000C003","name":"cash-usd","codepoint":"F1176","aliases":["local-atm","money-usd"],"tags":["Currency","Banking"],"author":"Michael Irigoyen","version":"4.4.95","deprecated":true},{"id":"219B8956-E48B-4D11-9257-422E563955DB","name":"cash-usd-outline","codepoint":"F0117","aliases":["local-atm","money-usd"],"tags":["Currency","Banking"],"author":"Google","version":"1.5.54","deprecated":true},{"id":"EF35081A-EABF-4C6B-B858-7F2177B60F95","name":"cassette","codepoint":"F09D4","aliases":["tape"],"tags":["Music"],"author":"GreenTurtwig","version":"2.5.94"},{"id":"996A1644-29FB-4221-9225-FD5CF8AAD5CE","name":"cast","codepoint":"F0118","aliases":[],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"E464AD1F-6036-43F9-9D9F-22390B2CBECB","name":"cast-audio","codepoint":"F101E","aliases":["cast-speaker"],"tags":["Audio"],"author":"Contributors","version":"4.1.95"},{"id":"80EC7FF6-03C0-4D61-8858-D2D94426D2DE","name":"cast-connected","codepoint":"F0119","aliases":[],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"31B2064A-79C9-44A7-8C5E-0490162A7864","name":"cast-education","codepoint":"F0E1D","aliases":["cast-school","school-online","cast-tutorial"],"tags":[],"author":"Google","version":"3.6.95"},{"id":"F6AC6C9C-C82B-48C0-84AB-BEE76FC7BB5B","name":"cast-off","codepoint":"F078A","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.9.32"},{"id":"53FF9F06-A3F7-4B04-9D54-207FE8B56B8E","name":"castle","codepoint":"F011A","aliases":[],"tags":["Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5D3A753E-1FA9-42F4-8A71-E686A36D1CB6","name":"cat","codepoint":"F011B","aliases":[],"tags":["Animal"],"author":"Austin Andrews","version":"1.5.54"},{"id":"04FF8A0D-0B5F-426B-ABAF-001EAC16559F","name":"cctv","codepoint":"F07AE","aliases":["closed-circuit-television","security-camera"],"tags":["Home Automation"],"author":"Roberto Graham","version":"2.0.46"},{"id":"C45A21A3-671C-4B1A-B405-D625ECA93C11","name":"ceiling-light","codepoint":"F0769","aliases":["ceiling-lamp"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"1.9.32"},{"id":"8898488F-1BE6-40A0-84B7-1C0832AA4754","name":"cellphone","codepoint":"F011C","aliases":["mobile-phone","smartphone","stay-current-portrait","stay-primary-portrait"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"C633DDA7-FB93-4041-98C2-92117B970114","name":"cellphone-android","codepoint":"F011D","aliases":["mobile-phone-android","smartphone-android"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"1.5.54","deprecated":true},{"id":"04D5C9C6-6CE4-4D2E-A759-07933F9B7932","name":"cellphone-arrow-down","codepoint":"F09D5","aliases":["cellphone-system-update","mobile-phone-arrow-down","smartphone-arrow-down"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.5.94"},{"id":"E22A55C0-983F-499E-8B43-4A66DB278B4E","name":"cellphone-basic","codepoint":"F011E","aliases":["mobile-phone-basic"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Simran","version":"1.5.54"},{"id":"FE245F0F-24CE-497E-BA73-19936BD14716","name":"cellphone-charging","codepoint":"F1397","aliases":[],"tags":[],"author":"Moma Design Studio","version":"5.0.45"},{"id":"134C82D3-528D-46FA-9107-7F3D5AD8FBC3","name":"cellphone-cog","codepoint":"F0951","aliases":["phonelink-setup","mobile-phone-settings-variant","smartphone-settings-variant"],"tags":["Settings","Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"4FBBF196-CF97-436B-A3E6-A08D695E6986","name":"cellphone-dock","codepoint":"F011F","aliases":["mobile-phone-dock","smartphone-dock"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"EC642A5A-34A2-4E29-85F1-60ACAA546FB1","name":"cellphone-erase","codepoint":"F094D","aliases":["phonelink-erase","mobile-phone-erase","smartphone-erase"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"5B692392-DA8F-40F2-948F-D81832ABA465","name":"cellphone-information","codepoint":"F0F41","aliases":["mobile-phone-information","smartphone-information"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"3.9.97"},{"id":"8B1B6ED1-8AA5-4888-8477-B122FB236E1D","name":"cellphone-iphone","codepoint":"F0120","aliases":["mobile-phone-iphone","smartphone-iphone"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"1.5.54","deprecated":true},{"id":"29BA2DA3-CED6-4D52-92EF-D9152F63B7AB","name":"cellphone-key","codepoint":"F094E","aliases":["mobile-phone-key","smartphone-key"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"E29A590D-51B8-471B-B23B-E0A41046EDA6","name":"cellphone-link","codepoint":"F0121","aliases":["mobile-phone-link","smartphone-link","devices"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"7E4265ED-151D-45CE-BDD2-08B6028B6006","name":"cellphone-link-off","codepoint":"F0122","aliases":["mobile-phone-link-off","smartphone-link-off","phonelink-off"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"2261E999-4B3A-4540-BB30-B4C130137916","name":"cellphone-lock","codepoint":"F094F","aliases":["phonelink-lock","mobile-phone-lock","smartphone-lock"],"tags":["Cellphone \/ Phone","Lock","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"4C511E7E-D658-493D-B34B-B73A4DEE8FF9","name":"cellphone-message","codepoint":"F08D3","aliases":["mobile-phone-message","smartphone-message"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Austin Andrews","version":"2.3.50"},{"id":"039B41EB-85E3-458B-9C51-AADE4C4071FE","name":"cellphone-message-off","codepoint":"F10D2","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Terren","version":"4.3.95"},{"id":"A4EFE1A4-034F-473F-9076-D8DFF6167067","name":"cellphone-nfc","codepoint":"F0E90","aliases":[],"tags":["Automotive","Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"3.7.94"},{"id":"E036E842-B41C-410B-BF8A-85B10A7E26D0","name":"cellphone-nfc-off","codepoint":"F12D8","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"2AD1736A-2142-4E3D-BA70-9CF8584C366D","name":"cellphone-off","codepoint":"F0950","aliases":["mobile-phone-off","smartphone-off","mobile-off"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"B89607FB-8199-48B0-AF59-E048CAEB210B","name":"cellphone-play","codepoint":"F101F","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.1.95"},{"id":"84F994FA-DF0C-4A5A-88F6-8A2AD1DC1189","name":"cellphone-screenshot","codepoint":"F0A35","aliases":[],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.6.95"},{"id":"E7458A8C-66F2-41D7-81AE-4B2B961DFE1A","name":"cellphone-settings","codepoint":"F0123","aliases":["mobile-phone-settings","smartphone-settings","settings-cell"],"tags":["Cellphone \/ Phone","Settings","Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"F5D685BD-7BA8-4F4C-8701-06F1B1E57064","name":"cellphone-sound","codepoint":"F0952","aliases":["phonelink-ring","mobile-phone-sound","smartphone-sound"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"D89FFCD9-0592-4760-98C9-5EDDA77826F5","name":"cellphone-text","codepoint":"F08D2","aliases":["mobile-phone-text","smartphone-text"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Austin Andrews","version":"2.3.50"},{"id":"071CA76A-0ED5-42CD-9BE9-46AFA9D5459E","name":"cellphone-wireless","codepoint":"F0815","aliases":["mobile-phone-wireless","smartphone-wireless"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Contributors","version":"2.1.19"},{"id":"63D4C7DD-5BEF-41F2-921F-48EB987F0ED3","name":"celtic-cross","codepoint":"F0CF5","aliases":[],"tags":["Religion"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"BAC7F15C-844C-4FEB-A4C0-2CDF80738979","name":"centos","codepoint":"F111A","aliases":[],"tags":[],"author":"Contributors","version":"4.3.95"},{"id":"2DBEB397-D80B-445D-A11E-7B8362CFBEF4","name":"certificate","codepoint":"F0124","aliases":["diploma","seal"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"6F755EB5-B2E1-413A-A919-3F0DCE69E48A","name":"certificate-outline","codepoint":"F1188","aliases":["diploma-outline","seal-outline"],"tags":[],"author":"Michael Richins","version":"4.4.95"},{"id":"822CF3D7-FEB4-4988-A037-0866756D4ADE","name":"chair-rolling","codepoint":"F0F48","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"47FCC651-522C-4786-B518-91A03A721A90","name":"chair-school","codepoint":"F0125","aliases":["desk","education","learn"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B5589411-20E7-4552-BEC5-A394068B23A7","name":"charity","codepoint":"F0C4F","aliases":["super-chat-for-good"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"98939E5B-1528-4A2F-B35A-C37C60C75D93","name":"chart-arc","codepoint":"F0126","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"00654F5E-1B8B-4BD7-933B-0BD65B2C9BAC","name":"chart-areaspline","codepoint":"F0127","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C55BFF6F-469B-4D28-835B-537BED8DE99D","name":"chart-areaspline-variant","codepoint":"F0E91","aliases":[],"tags":["Math"],"author":"Michael Richins","version":"3.7.94"},{"id":"85D4DC49-5359-4867-A5D1-52C44699387F","name":"chart-bar","codepoint":"F0128","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FAA40519-5517-44DF-AF2E-30D07874BEB7","name":"chart-bar-stacked","codepoint":"F076A","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.9.32"},{"id":"35760CC7-EBA2-4445-B88B-7E8224535BB7","name":"chart-bell-curve","codepoint":"F0C50","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"D4E38BC9-5A85-4890-B3DD-92F3D263E26E","name":"chart-bell-curve-cumulative","codepoint":"F0FA7","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"381420B2-B2EE-4E9F-9DEA-EA0C1F92A226","name":"chart-box","codepoint":"F154D","aliases":[],"tags":["Math"],"author":"Google","version":"5.4.55"},{"id":"4115E465-01E5-4F3F-929A-81C239289B21","name":"chart-box-outline","codepoint":"F154E","aliases":[],"tags":["Math"],"author":"Google","version":"5.4.55"},{"id":"2F2AA4D1-DB33-4B54-8052-2A2EFCE59168","name":"chart-box-plus-outline","codepoint":"F154F","aliases":[],"tags":["Math"],"author":"Google","version":"5.4.55"},{"id":"9D79A433-CF5A-45A2-971F-4FBF72DB9821","name":"chart-bubble","codepoint":"F05E3","aliases":["bubble-chart"],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"C7BED6AB-8D91-42EC-A22F-D4B922B0EB14","name":"chart-donut","codepoint":"F07AF","aliases":["chart-doughnut","data-usage"],"tags":["Math"],"author":"Google","version":"2.0.46"},{"id":"FE9CBE2A-4D6F-4A1F-B817-26607BB9561B","name":"chart-donut-variant","codepoint":"F07B0","aliases":["chart-doughnut-variant"],"tags":["Math"],"author":"Austin Andrews","version":"2.0.46"},{"id":"A2839B3A-760A-4061-80CA-41B3FA5817E0","name":"chart-gantt","codepoint":"F066C","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.6.50"},{"id":"8DCC14D7-057F-4DA4-89B2-B26D6B6F0C00","name":"chart-histogram","codepoint":"F0129","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"D996574D-5B42-47C5-91D6-F86555C2FBC5","name":"chart-line","codepoint":"F012A","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B53C0CF7-F923-409F-91C3-420513E44231","name":"chart-line-stacked","codepoint":"F076B","aliases":[],"tags":["Math"],"author":"Haley Halcyon","version":"1.9.32"},{"id":"2FAF8E0B-5AB4-4914-A0A1-CECFFAF85427","name":"chart-line-variant","codepoint":"F07B1","aliases":["show-chart"],"tags":["Math"],"author":"Google","version":"2.0.46"},{"id":"746FB7AE-B8AC-4356-8B79-D95F54B410D7","name":"chart-multiline","codepoint":"F08D4","aliases":[],"tags":["Math"],"author":"Google","version":"2.3.50"},{"id":"42E3BF4B-FFE9-449F-AFEE-66F565602A9B","name":"chart-multiple","codepoint":"F1213","aliases":[],"tags":["Math"],"author":"Michael Richins","version":"4.6.95"},{"id":"9C6B53C5-698B-4428-9738-A6700BF8698C","name":"chart-pie","codepoint":"F012B","aliases":[],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"42A6B073-CC7E-4539-9313-E60FAE81BC70","name":"chart-ppf","codepoint":"F1380","aliases":["chart-production-possibility-frontier"],"tags":["Math"],"author":"Simran","version":"4.9.95"},{"id":"D0F312B5-8B3B-4E68-BF0B-691D4F129749","name":"chart-sankey","codepoint":"F11DF","aliases":["chart-snakey"],"tags":["Math"],"author":"Michael Richins","version":"4.5.95"},{"id":"5FA4943E-5956-4668-ADDD-984914DD745C","name":"chart-sankey-variant","codepoint":"F11E0","aliases":["chart-snakey-variant"],"tags":["Math"],"author":"Michael Richins","version":"4.5.95"},{"id":"C268C5A5-0D35-4963-9151-61D2C442015B","name":"chart-scatter-plot","codepoint":"F0E92","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"852E3EF2-942E-42C5-87BB-E1193EBD3E0C","name":"chart-scatter-plot-hexbin","codepoint":"F066D","aliases":["chart-scatterplot-hexbin"],"tags":["Math"],"author":"Austin Andrews","version":"1.6.50"},{"id":"922A0C03-C46D-45E7-8B44-9D53F1292360","name":"chart-timeline","codepoint":"F066E","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.6.50"},{"id":"F41D980A-439A-4F1B-A3B7-850EB1A70416","name":"chart-timeline-variant","codepoint":"F0E93","aliases":[],"tags":["Math"],"author":"Google","version":"3.7.94"},{"id":"F2256261-8218-48B2-BACA-9E23E42EEC15","name":"chart-timeline-variant-shimmer","codepoint":"F15B6","aliases":[],"tags":[],"author":"Google","version":"5.6.55"},{"id":"B7E7AEAC-4A67-4C0F-8A4C-C0955AE5F655","name":"chart-tree","codepoint":"F0E94","aliases":[],"tags":["Math"],"author":"Google","version":"3.7.94"},{"id":"7FF15164-E575-4024-ABAC-A183179F0217","name":"chat","codepoint":"F0B79","aliases":[],"tags":[],"author":"Contributors","version":"3.0.39"},{"id":"7E35E8CF-E958-43D7-9B28-072E3161618A","name":"chat-alert","codepoint":"F0B7A","aliases":["chat-warning"],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"3.0.39"},{"id":"C0C2065A-8B0C-4DE2-AD4E-D909080FFB42","name":"chat-alert-outline","codepoint":"F12C9","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"45A636B1-89B7-45B8-B68A-65DB813B7927","name":"chat-minus","codepoint":"F1410","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"69E4B1D9-C479-47CB-8354-A61FCCC51A0B","name":"chat-minus-outline","codepoint":"F1413","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"E6394813-3C45-4D08-A207-9008A2E5CECB","name":"chat-outline","codepoint":"F0EDE","aliases":[],"tags":[],"author":"Michael Richins","version":"3.8.95"},{"id":"25FEEB21-3351-4743-994B-1DA08DEAB2B7","name":"chat-plus","codepoint":"F140F","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"F9BDF971-6385-4B8F-98AD-B3FE8D376855","name":"chat-plus-outline","codepoint":"F1412","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"95003FC4-C655-4687-AF82-660A49B95978","name":"chat-processing","codepoint":"F0B7B","aliases":["chat-typing"],"tags":[],"author":"Austin Andrews","version":"3.0.39"},{"id":"F753E08E-F7C9-4BAF-8647-9328D56D1837","name":"chat-processing-outline","codepoint":"F12CA","aliases":["chat-typing-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"8B7833C6-EB36-4F0C-A554-AF7189A7AB34","name":"chat-question","codepoint":"F1738","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"7EC5A46D-1E6A-475C-A76F-19F9F4B9CD90","name":"chat-question-outline","codepoint":"F1739","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"3C021F95-3463-45CD-9908-A0D84B2793FB","name":"chat-remove","codepoint":"F1411","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"4D147E9B-52BB-446B-8355-0CEA377C0631","name":"chat-remove-outline","codepoint":"F1414","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"4B555315-27A3-4DD2-8A85-0F05260CDA33","name":"chat-sleep","codepoint":"F12D1","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"ABE1573F-24A9-4AC1-9ADB-6A9A32FB10AA","name":"chat-sleep-outline","codepoint":"F12D2","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"F789CE44-7EA3-4E97-88FB-BEC22EB2030C","name":"check","codepoint":"F012C","aliases":["tick","done"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"48BA3B7B-1EF7-4160-A0BB-54EBCF999A13","name":"check-all","codepoint":"F012D","aliases":["tick-all","done-all","check-multiple","checks","ticks"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"2070D6C6-EC09-4507-BE0A-07BFFFAF6DFB","name":"check-bold","codepoint":"F0E1E","aliases":["check-thick"],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"E0A0FF12-A5AD-40E3-B286-8958154F0537","name":"check-box-multiple-outline","codepoint":"F0C51","aliases":["check-boxes-outline","tick-box-multiple-outline"],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"EA5B8CC8-FFD6-4128-AC25-DEDCF1097A34","name":"check-box-outline","codepoint":"F0C52","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"93D7B6DC-17D2-4A2B-B787-79E2E8BEF304","name":"check-circle","codepoint":"F05E0","aliases":["tick-circle"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"F609EE7E-AAB4-4CE7-A002-D0F7ECF89609","name":"check-circle-outline","codepoint":"F05E1","aliases":["tick-circle-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"64E327CF-3FCB-4742-AB82-789B2C27D31B","name":"check-decagram","codepoint":"F0791","aliases":["verified","decagram-check","approve","approval","tick-decagram"],"tags":[],"author":"Michael Richins","version":"2.0.46"},{"id":"1CAE9177-18C6-497A-B6B9-900C00A14D0E","name":"check-decagram-outline","codepoint":"F1740","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.9.55"},{"id":"F1CE2683-FE3F-4AA1-89A2-A935D6FD403C","name":"check-network","codepoint":"F0C53","aliases":["tick-network"],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"98A3D662-2D11-40DB-8557-E1DD0E877091","name":"check-network-outline","codepoint":"F0C54","aliases":["tick-network-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"38BFE155-0352-4907-A578-B5D0D7F5B78D","name":"check-outline","codepoint":"F0855","aliases":["done-outline","tick-outline"],"tags":[],"author":"Google","version":"2.1.99"},{"id":"862B14E6-BA7A-4736-8047-1C836B2F4EC1","name":"check-underline","codepoint":"F0E1F","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.6.95"},{"id":"4B7477D9-418A-40E7-811A-50DFFEA14A03","name":"check-underline-circle","codepoint":"F0E20","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"8C448942-B521-4C50-B8AD-0233EF30B12C","name":"check-underline-circle-outline","codepoint":"F0E21","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"F35E17AA-A0E8-4AEE-9504-6DC07F3ACEAD","name":"checkbook","codepoint":"F0A9D","aliases":["chequebook","cheque-book"],"tags":[],"author":"Google","version":"2.7.94"},{"id":"2B75FE22-5209-4DF8-B16A-B6F74272337B","name":"checkbox-blank","codepoint":"F012E","aliases":[],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"F031DE59-CC30-47BF-B689-BC993893B03A","name":"checkbox-blank-circle","codepoint":"F012F","aliases":[],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"7C094780-770D-44B6-981C-C701784192D6","name":"checkbox-blank-circle-outline","codepoint":"F0130","aliases":[],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"8F505717-7778-4909-81E9-0714F01B44AF","name":"checkbox-blank-off","codepoint":"F12EC","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"06F6526C-6D2A-45F5-A5DF-46860DE27EAC","name":"checkbox-blank-off-outline","codepoint":"F12ED","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"C7D0E43D-6393-429B-BDCE-B522419B7B3D","name":"checkbox-blank-outline","codepoint":"F0131","aliases":["check-box-outline-blank"],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"EFD12742-D508-4531-A9A4-EDCF3148C748","name":"checkbox-intermediate","codepoint":"F0856","aliases":[],"tags":["Form"],"author":"Michael Richins","version":"2.1.99"},{"id":"C3E50D88-07AB-491F-B21E-9AA11A1E5886","name":"checkbox-marked","codepoint":"F0132","aliases":["check-box"],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"4336ADDD-7A8E-46E7-A886-3873CCCFD3DA","name":"checkbox-marked-circle","codepoint":"F0133","aliases":[],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"7DC53566-5640-4124-A2C2-5070D7FBA591","name":"checkbox-marked-circle-outline","codepoint":"F0134","aliases":[],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"AB384DA7-C0DA-4A68-96EA-FC54BF0EDED1","name":"checkbox-marked-outline","codepoint":"F0135","aliases":[],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"2B01AE9D-AFA4-4CDA-82BD-21076D27C006","name":"checkbox-multiple-blank","codepoint":"F0136","aliases":["checkboxes-blank"],"tags":["Form"],"author":"Austin Andrews","version":"1.5.54"},{"id":"0AE5C836-2A43-4706-81C5-5053A73B9CAA","name":"checkbox-multiple-blank-circle","codepoint":"F063B","aliases":["checkboxes-blank-circle"],"tags":["Form"],"author":"Simran","version":"1.6.50"},{"id":"CCBAD6F8-5D3D-420A-94AF-CC85AA12397E","name":"checkbox-multiple-blank-circle-outline","codepoint":"F063C","aliases":["checkboxes-blank-circle-outline"],"tags":["Form"],"author":"Simran","version":"1.6.50"},{"id":"CA74F33C-3AEE-4EA9-93B4-643099DFD92D","name":"checkbox-multiple-blank-outline","codepoint":"F0137","aliases":["checkboxes-blank-outline"],"tags":["Form"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4F160BFE-433B-49D1-B2DC-E7F71AF7070B","name":"checkbox-multiple-marked","codepoint":"F0138","aliases":["checkboxes-marked"],"tags":["Form"],"author":"Austin Andrews","version":"1.5.54"},{"id":"85C35F15-1AC0-407B-BCBF-AD79B6E6DDEA","name":"checkbox-multiple-marked-circle","codepoint":"F063D","aliases":["checkboxes-marked-circle"],"tags":["Form"],"author":"Simran","version":"1.6.50"},{"id":"5158D0E3-0E77-4CC3-A9A4-727825812D00","name":"checkbox-multiple-marked-circle-outline","codepoint":"F063E","aliases":["checkboxes-marked-circle-outline"],"tags":["Form"],"author":"Simran","version":"1.6.50"},{"id":"16BECBE7-BD8E-4301-B5CB-5EE534FBDAD3","name":"checkbox-multiple-marked-outline","codepoint":"F0139","aliases":["checkboxes-marked-outline"],"tags":["Form"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A5F7D4AF-C7A3-4F38-B21B-B9F3E68770DE","name":"checkerboard","codepoint":"F013A","aliases":["raster"],"tags":["Gaming \/ RPG","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"925C7A7F-E7D0-4260-B131-D96FF2F7B8DB","name":"checkerboard-minus","codepoint":"F1202","aliases":["raster-minus"],"tags":["Geographic Information System"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"020A5F88-EE7B-4FE7-ADC7-999A0ADB16EE","name":"checkerboard-plus","codepoint":"F1201","aliases":["raster-plus"],"tags":["Geographic Information System"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"CDCAA6DE-0885-474F-992F-6A7F46563A15","name":"checkerboard-remove","codepoint":"F1203","aliases":["raster-remove"],"tags":["Geographic Information System"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"618E3DC0-F776-4CFF-BE9F-D6A23D580F5B","name":"cheese","codepoint":"F12B9","aliases":["swiss-cheese"],"tags":["Food \/ Drink"],"author":"Thomas de Saint-Exup\u00e9ry","version":"4.7.95"},{"id":"7EF3B22A-CA40-400B-AA25-00B9A6777651","name":"cheese-off","codepoint":"F13EE","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"E22BD22B-9748-4CA8-A748-B5598B08A7DE","name":"chef-hat","codepoint":"F0B7C","aliases":["toque","cook"],"tags":["Clothing"],"author":"Simran","version":"3.0.39"},{"id":"7916D1CB-2F73-4C27-8A6B-B14D593F8F59","name":"chemical-weapon","codepoint":"F013B","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"3B0E25CE-ADB0-4601-BFBD-87C7B6D63E7F","name":"chess-bishop","codepoint":"F085C","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.99"},{"id":"073FDF74-5305-45AB-8AC3-42A0FE6BBF9C","name":"chess-king","codepoint":"F0857","aliases":["crown","royalty"],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.99"},{"id":"99D5E230-2040-4811-BEF1-17B867DA5F75","name":"chess-knight","codepoint":"F0858","aliases":["chess-horse"],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.99"},{"id":"EDF049A9-1170-411B-923E-D19BD5EADB92","name":"chess-pawn","codepoint":"F0859","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.99"},{"id":"0B9D0593-D546-4DDD-AEB1-289943FB12AE","name":"chess-queen","codepoint":"F085A","aliases":["crown","royalty"],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.99"},{"id":"D1FA251F-4332-4BA9-8742-F194C0B0BF28","name":"chess-rook","codepoint":"F085B","aliases":["chess-castle","chess-tower"],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.99"},{"id":"74ACC301-AA62-492B-92C1-8021BDD89A02","name":"chevron-double-down","codepoint":"F013C","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"76350FC3-7629-4247-9D09-8AB9AF9BC6CF","name":"chevron-double-left","codepoint":"F013D","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"E4B5D36C-A663-4D53-BE18-09393497556F","name":"chevron-double-right","codepoint":"F013E","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"53D302C9-3A0D-4104-967E-21D174E3C0B2","name":"chevron-double-up","codepoint":"F013F","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"84FE90C1-076D-4EA1-B56F-4C2582A39AC3","name":"chevron-down","codepoint":"F0140","aliases":["expand-more","keyboard-arrow-down"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"E2EFD734-594F-40ED-A263-3DFBB8E1B381","name":"chevron-down-box","codepoint":"F09D6","aliases":[],"tags":["Form","Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"D299D24D-E65D-4A1F-953B-0AC936D25C58","name":"chevron-down-box-outline","codepoint":"F09D7","aliases":[],"tags":["Form","Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"F312962F-0720-4145-89EA-6E3E9D60131D","name":"chevron-down-circle","codepoint":"F0B26","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"3968656C-5ADA-44B4-AFAD-9437B1363C5D","name":"chevron-down-circle-outline","codepoint":"F0B27","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"CF5607F2-4106-4D47-8FE6-B8F5A16E6D98","name":"chevron-left","codepoint":"F0141","aliases":["keyboard-arrow-left","navigate-before"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"7DC0F3E7-2E3F-49BD-874D-B17250FBA187","name":"chevron-left-box","codepoint":"F09D8","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"22B3AE2E-C625-4325-8FBE-A98AC004CEE6","name":"chevron-left-box-outline","codepoint":"F09D9","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"842FCAE6-0FE2-495D-980C-1ABA85257C77","name":"chevron-left-circle","codepoint":"F0B28","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"DDBD357B-6E94-483F-9A09-0E2131FA8533","name":"chevron-left-circle-outline","codepoint":"F0B29","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"A6D25AD4-462B-4185-B739-FBFCD3ACF3C3","name":"chevron-right","codepoint":"F0142","aliases":["keyboard-arrow-right","navigate-next"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"D9C230F8-C44C-4CE7-8DEF-891A531A1619","name":"chevron-right-box","codepoint":"F09DA","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"E96D0BE5-31CA-4C47-B91A-B8FB9FCB5D15","name":"chevron-right-box-outline","codepoint":"F09DB","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"A0F96469-2C19-48B6-A054-3F48656CE24F","name":"chevron-right-circle","codepoint":"F0B2A","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"9AA7CA11-776D-413A-A08F-9E21AF0F963B","name":"chevron-right-circle-outline","codepoint":"F0B2B","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"D922FD44-139A-4DEE-92A6-1BFCA39C8461","name":"chevron-triple-down","codepoint":"F0DB9","aliases":[],"tags":[],"author":"Google","version":"3.5.94"},{"id":"09E1A31D-448C-42D3-A220-2ACBD0D8B211","name":"chevron-triple-left","codepoint":"F0DBA","aliases":[],"tags":[],"author":"Google","version":"3.5.94"},{"id":"F80C6B02-D422-44FE-9199-B9E12EF523C8","name":"chevron-triple-right","codepoint":"F0DBB","aliases":[],"tags":[],"author":"Google","version":"3.5.94"},{"id":"C04D4C82-E95C-45E1-8582-89A24536026F","name":"chevron-triple-up","codepoint":"F0DBC","aliases":["rank"],"tags":[],"author":"Google","version":"3.5.94"},{"id":"AECCC94F-C38A-4A97-879E-ACD09F89169A","name":"chevron-up","codepoint":"F0143","aliases":["expand-less","keyboard-arrow-up","caret"],"tags":["Arrow","Math"],"author":"Google","version":"1.5.54"},{"id":"C721C684-43CC-4B3B-B91A-A574D5215FF3","name":"chevron-up-box","codepoint":"F09DC","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"7660602A-34FB-4A1A-818B-A086CA1783BD","name":"chevron-up-box-outline","codepoint":"F09DD","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"981C36F0-6F33-4A92-B20E-66E70BF474FA","name":"chevron-up-circle","codepoint":"F0B2C","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"625319CF-2277-486A-9FB6-902F3F3FE212","name":"chevron-up-circle-outline","codepoint":"F0B2D","aliases":[],"tags":["Arrow"],"author":"SarinManS","version":"2.8.94"},{"id":"E868226C-7BE8-4A22-8A9A-8E040004016A","name":"chili-hot","codepoint":"F07B2","aliases":["chilli-hot","pepper","spicy"],"tags":["Food \/ Drink"],"author":"Andy Martinez","version":"2.0.46"},{"id":"C9DA0BF5-09DD-46A9-AE62-1612B26F0BB1","name":"chili-medium","codepoint":"F07B3","aliases":["chilli-medium","pepper","spicy"],"tags":["Food \/ Drink"],"author":"Andy Martinez","version":"2.0.46"},{"id":"3CE5B420-F103-47EA-800C-A4D145B89508","name":"chili-mild","codepoint":"F07B4","aliases":["chilli-mild","pepper","spicy"],"tags":["Food \/ Drink"],"author":"Andy Martinez","version":"2.0.46"},{"id":"F92E010E-F45D-44CE-8F13-F6419010B0D2","name":"chili-off","codepoint":"F1467","aliases":["chilli-off","pepper-off","spicy-off"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"A535271B-1114-44AD-9D9D-1984905026FF","name":"chip","codepoint":"F061A","aliases":["integrated-circuit"],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"5644CD16-FA4D-4F68-8DAC-996169C778E1","name":"christianity","codepoint":"F0953","aliases":["religion-christian","cross"],"tags":["Religion"],"author":"Nick","version":"2.4.85"},{"id":"E7B0A94D-5F09-4E77-A1E0-3DA131398A26","name":"christianity-outline","codepoint":"F0CF6","aliases":["religion-christian-outline","cross-outline"],"tags":["Religion"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"82E4FDFE-C9C8-4087-ABCC-DF51F760379A","name":"church","codepoint":"F0144","aliases":[],"tags":["Religion","Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4E50E8E9-4283-4B08-9AB2-6283088898BB","name":"cigar","codepoint":"F1189","aliases":[],"tags":[],"author":"Michael Richins","version":"4.4.95"},{"id":"BC451ECE-B21F-43F6-AE1C-D9E3614E4406","name":"cigar-off","codepoint":"F141B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"59803983-F6CE-4D40-B83C-36D42C9464A9","name":"circle","codepoint":"F0765","aliases":["lens"],"tags":["Shape"],"author":"Austin Andrews","version":"1.9.32"},{"id":"3E57AA64-D7C2-4C4E-BE87-58A6D775BC21","name":"circle-box","codepoint":"F15DC","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"4A709F16-7813-44DA-AB19-EBEBB4A6718A","name":"circle-box-outline","codepoint":"F15DD","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"02A447DB-D9DB-4568-B839-841F1401FD31","name":"circle-double","codepoint":"F0E95","aliases":[],"tags":["Shape"],"author":"ginlime","version":"3.7.94"},{"id":"7C0E615F-A0DC-4689-A094-4E59D27675B3","name":"circle-edit-outline","codepoint":"F08D5","aliases":[],"tags":["Edit \/ Modify"],"author":"Google","version":"2.3.50"},{"id":"6262A121-B53E-4429-8E8E-F05A6820EDC7","name":"circle-expand","codepoint":"F0E96","aliases":[],"tags":[],"author":"Google","version":"3.7.94"},{"id":"901AA3C4-B9A4-4764-ABA4-FD51FA6D68ED","name":"circle-half","codepoint":"F1395","aliases":[],"tags":[],"author":"Simran","version":"5.0.45"},{"id":"D066B111-84BC-4682-864B-CAFEE4A93F66","name":"circle-half-full","codepoint":"F1396","aliases":[],"tags":[],"author":"Simran","version":"5.0.45"},{"id":"AB8D0574-712C-4403-A5A5-51E16C081605","name":"circle-medium","codepoint":"F09DE","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"C05A4C2F-8128-474F-B204-D782A332CB73","name":"circle-multiple","codepoint":"F0B38","aliases":["coins"],"tags":["Currency","Banking"],"author":"Michael Richins","version":"2.8.94"},{"id":"BAD0A147-6CA0-4BCF-88DF-8E8A4C247B0E","name":"circle-multiple-outline","codepoint":"F0695","aliases":["toll","coins-outline"],"tags":["Currency","Banking"],"author":"Google","version":"1.7.12"},{"id":"5DC46127-B07A-4E2B-B3BA-A98C0D2942F4","name":"circle-off-outline","codepoint":"F10D3","aliases":["null-off"],"tags":[],"author":"Simran","version":"4.3.95"},{"id":"00E1BEF8-DD84-4DCE-BE3C-8AA411DCE5FD","name":"circle-outline","codepoint":"F0766","aliases":["null"],"tags":["Shape"],"author":"Austin Andrews","version":"1.9.32"},{"id":"40F6544B-8BBE-44AD-85A2-FDFA1AD8091E","name":"circle-slice-1","codepoint":"F0A9E","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"520A592A-21BB-4D8C-835F-BEF1EF0B73D0","name":"circle-slice-2","codepoint":"F0A9F","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"FE0AA2ED-07F6-4BC4-876E-1FA6BA283130","name":"circle-slice-3","codepoint":"F0AA0","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"12C46927-0235-4A3A-965B-287879A4C2E3","name":"circle-slice-4","codepoint":"F0AA1","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"4AA85ADE-6180-453B-A62E-2819E92E779A","name":"circle-slice-5","codepoint":"F0AA2","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"658050F8-5C9A-4C5C-BE99-8EB492524586","name":"circle-slice-6","codepoint":"F0AA3","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"A051B0B2-A0CB-4E51-87F8-242EA4A4777F","name":"circle-slice-7","codepoint":"F0AA4","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"CB0FC186-2B53-4802-A9DB-98CF07B78CF1","name":"circle-slice-8","codepoint":"F0AA5","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"0EA34D8C-1A02-4A92-8293-991702ABD065","name":"circle-small","codepoint":"F09DF","aliases":["bullet","multiplication"],"tags":["Math"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"4CC37629-C3B9-4F3B-BA36-4B93A3CDE297","name":"circular-saw","codepoint":"F0E22","aliases":[],"tags":["Hardware \/ Tools"],"author":"Augustin Ursu","version":"3.6.95"},{"id":"5A5AC571-1818-45D0-8259-A9177DBED615","name":"city","codepoint":"F0146","aliases":["location-city"],"tags":["Places"],"author":"Google","version":"1.5.54"},{"id":"2F6976DF-1008-496D-802D-917F6EA5F7DB","name":"city-variant","codepoint":"F0A36","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"1DECCCEC-93F2-4BD8-BEFD-370D5020DCDB","name":"city-variant-outline","codepoint":"F0A37","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"423D4239-D8DC-4D8B-9365-9D51E2A0FDF7","name":"clipboard","codepoint":"F0147","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"C45D118E-4FFA-42E5-A18B-B8A7B58BF42F","name":"clipboard-account","codepoint":"F0148","aliases":["clipboard-user","assignment-ind","clipboard-person"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"80D8F0AA-0B3A-47ED-B342-8681E0DD7450","name":"clipboard-account-outline","codepoint":"F0C55","aliases":["clipboard-user-outline","clipboard-person-outline","assignment-ind-outline"],"tags":["Account \/ User"],"author":"James Coyle","version":"3.2.89"},{"id":"57AC4C5E-B2AB-42B5-9826-BCFEACCB2E7C","name":"clipboard-alert","codepoint":"F0149","aliases":["clipboard-warning","assignment-late"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"321F2AC5-C710-4AD5-A493-279435DF0074","name":"clipboard-alert-outline","codepoint":"F0CF7","aliases":["clipboard-warning-outline"],"tags":["Alert \/ Error"],"author":"James Coyle","version":"3.3.92"},{"id":"863E0318-495E-437A-B22B-3C1274D108E6","name":"clipboard-arrow-down","codepoint":"F014A","aliases":["assignment-returned","clipboard-arrow-bottom"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"0FB11B14-8890-432D-A4B0-7D359DE681D8","name":"clipboard-arrow-down-outline","codepoint":"F0C56","aliases":["assignment-returned-outline","clipboard-arrow-bottom-outline"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"1D6DD9E5-61EA-40E6-A19A-EF4BA71B0FC0","name":"clipboard-arrow-left","codepoint":"F014B","aliases":["assignment-return"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"38CF4CD8-7203-4E66-BAD3-A3A7B4900BD4","name":"clipboard-arrow-left-outline","codepoint":"F0CF8","aliases":[],"tags":[],"author":"James Coyle","version":"3.3.92"},{"id":"4BD76170-F83F-4145-982F-3F1EBAD22D59","name":"clipboard-arrow-right","codepoint":"F0CF9","aliases":[],"tags":[],"author":"James Coyle","version":"3.3.92"},{"id":"7DB95067-893D-4472-8D74-79E521AE0DD1","name":"clipboard-arrow-right-outline","codepoint":"F0CFA","aliases":[],"tags":[],"author":"James Coyle","version":"3.3.92"},{"id":"5F084570-4F64-4A94-A762-602350ACEDAA","name":"clipboard-arrow-up","codepoint":"F0C57","aliases":["clipboard-arrow-top"],"tags":[],"author":"James Coyle","version":"3.2.89"},{"id":"15ED4DA3-08C5-4913-9FEB-A88CEED7DDE9","name":"clipboard-arrow-up-outline","codepoint":"F0C58","aliases":["clipboard-arrow-top-outline"],"tags":[],"author":"James Coyle","version":"3.2.89"},{"id":"2FA574EF-C285-465F-A254-868506FA4273","name":"clipboard-check","codepoint":"F014E","aliases":["assignment-turned-in","clipboard-tick"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"6DBE3F30-C444-443C-A515-75657C468338","name":"clipboard-check-multiple","codepoint":"F1263","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"2FB7020B-64CC-4CA8-A46E-0D3E5B65A697","name":"clipboard-check-multiple-outline","codepoint":"F1264","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"6A0DFB73-2DBF-4D3C-8C6B-2B4758B11782","name":"clipboard-check-outline","codepoint":"F08A8","aliases":["clipboard-tick-outline"],"tags":[],"author":"James Coyle","version":"2.2.43"},{"id":"E276DDBC-9E61-4CE3-8168-6E896E6ADD98","name":"clipboard-clock","codepoint":"F16E2","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"D9132053-ADBE-417D-A00B-207B8F1C85A7","name":"clipboard-clock-outline","codepoint":"F16E3","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"BA08B631-B169-4C0F-A99B-BBECC9F18CAA","name":"clipboard-edit","codepoint":"F14E5","aliases":[],"tags":["Edit \/ Modify"],"author":"Contributors","version":"5.4.55"},{"id":"E316EB8B-FF99-4B85-AE09-C7E5A9656738","name":"clipboard-edit-outline","codepoint":"F14E6","aliases":[],"tags":["Edit \/ Modify"],"author":"Contributors","version":"5.4.55"},{"id":"CE6923D5-218F-4817-B904-E03A842CE696","name":"clipboard-file","codepoint":"F1265","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"B9BE1636-2925-4AA2-B21A-1EE197FA7774","name":"clipboard-file-outline","codepoint":"F1266","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"5A450EF8-D2F0-4F32-8D10-A606DD847E19","name":"clipboard-flow","codepoint":"F06C8","aliases":[],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"5EA9A77D-401F-48C8-B804-EE8B9A7CB229","name":"clipboard-flow-outline","codepoint":"F1117","aliases":[],"tags":[],"author":"Contributors","version":"4.3.95"},{"id":"754100C6-667F-49AD-A5C5-0FF2AD94C6DF","name":"clipboard-list","codepoint":"F10D4","aliases":[],"tags":[],"author":"Contributors","version":"4.3.95"},{"id":"9169E4CD-137E-4743-96A7-80B5764630FF","name":"clipboard-list-outline","codepoint":"F10D5","aliases":[],"tags":[],"author":"Contributors","version":"4.3.95"},{"id":"7C5309A2-5DA1-4393-8846-0CF5CB43BF88","name":"clipboard-minus","codepoint":"F1618","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"F83888C2-F7CF-423E-9101-2D9A49A6597B","name":"clipboard-minus-outline","codepoint":"F1619","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"8CD0EB09-AC6D-43C7-8DD6-4F2FD9A1DBC5","name":"clipboard-multiple","codepoint":"F1267","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"81D9B376-8054-4DB5-BA79-274E4B3EF79D","name":"clipboard-multiple-outline","codepoint":"F1268","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"376FB5C9-DF1A-455B-9824-5D0A3CE61481","name":"clipboard-off","codepoint":"F161A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"86166B5D-05DD-423B-B10E-E67010AEBE58","name":"clipboard-off-outline","codepoint":"F161B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"54F34575-7348-4032-B072-EC8F9A6C843D","name":"clipboard-outline","codepoint":"F014C","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"F0E26160-95CF-4270-8FD2-134391B88CA8","name":"clipboard-play","codepoint":"F0C59","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"E78AF95D-A3B1-483C-9F46-B503AEF6B4C0","name":"clipboard-play-multiple","codepoint":"F1269","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"2FCD745F-4980-4CAA-A51D-94574CAB1DA4","name":"clipboard-play-multiple-outline","codepoint":"F126A","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"B2D48D43-940B-4758-A9E1-00E13202B239","name":"clipboard-play-outline","codepoint":"F0C5A","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"A5AA9DEA-AAAE-4C79-965F-6828F823E2CD","name":"clipboard-plus","codepoint":"F0751","aliases":["clipboard-add"],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"4662F629-FEF3-4F7A-A901-56FF827CF051","name":"clipboard-plus-outline","codepoint":"F131F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"8E3D93CC-DE0A-4828-AC9A-9A6CFD932978","name":"clipboard-pulse","codepoint":"F085D","aliases":["clipboard-vitals"],"tags":["Medical \/ Hospital"],"author":"Simran","version":"2.1.99"},{"id":"8D6CA1DD-35D6-4E8E-BDA0-6192728A24C4","name":"clipboard-pulse-outline","codepoint":"F085E","aliases":["clipboard-vitals-outline"],"tags":["Medical \/ Hospital"],"author":"Simran","version":"2.1.99"},{"id":"474C3746-90C6-456C-9B18-6101FFC8075B","name":"clipboard-remove","codepoint":"F161C","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"57C00F9A-7204-402F-9AF9-908A02C23681","name":"clipboard-remove-outline","codepoint":"F161D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"785666E6-8CB0-4875-A289-1A9329614E69","name":"clipboard-search","codepoint":"F161E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"9D8E08D1-6F72-4729-AF64-ED099D109B7D","name":"clipboard-search-outline","codepoint":"F161F","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"81453216-6EC0-4751-82A4-BFFF63B922FC","name":"clipboard-text","codepoint":"F014D","aliases":["assignment"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"37090A31-A50D-43AB-92C4-BFB2C17273E6","name":"clipboard-text-multiple","codepoint":"F126B","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"4FF17874-C828-4EA8-9F4D-BEAEB614D69F","name":"clipboard-text-multiple-outline","codepoint":"F126C","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"237A2797-5013-4A50-9CB9-59FFEEC5BE4E","name":"clipboard-text-off","codepoint":"F1620","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"A5B09C9E-6430-4F6E-BA1C-D855ED6AB74C","name":"clipboard-text-off-outline","codepoint":"F1621","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"9C5136D5-E614-4DBD-AB36-EBB044178B6D","name":"clipboard-text-outline","codepoint":"F0A38","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"15B53AD7-FB72-4D70-8F70-B2259281EA2B","name":"clipboard-text-play","codepoint":"F0C5B","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"A1587F0D-C189-4886-9CB0-FBA5E3FA70E6","name":"clipboard-text-play-outline","codepoint":"F0C5C","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"347494DF-0250-4F0E-9E64-23CB8F35B8C2","name":"clipboard-text-search","codepoint":"F1622","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"1E23BABF-F9E8-42C6-9199-0B3B6C43C290","name":"clipboard-text-search-outline","codepoint":"F1623","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"6B346FB6-F563-4AC4-B769-06A143B42152","name":"clippy","codepoint":"F014F","aliases":[],"tags":[],"author":"Contributors","version":"1.5.54"},{"id":"90E7BBD9-12C3-4339-94DE-99A049C8D4B1","name":"clock","codepoint":"F0954","aliases":["watch-later"],"tags":["Date \/ Time"],"author":"Google","version":"2.4.85"},{"id":"A4250284-2784-405C-A62F-E6C546D66777","name":"clock-alert","codepoint":"F0955","aliases":["clock-warning"],"tags":["Date \/ Time","Alert \/ Error"],"author":"Simran","version":"2.4.85"},{"id":"CB400FB2-95E5-4420-B579-80DCA5C0F8B0","name":"clock-alert-outline","codepoint":"F05CE","aliases":["clock-warning"],"tags":["Date \/ Time","Alert \/ Error"],"author":"Simran","version":"1.5.54"},{"id":"46C840CA-A3F7-4293-8ABC-28C285723A8A","name":"clock-check","codepoint":"F0FA8","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"DC1289EA-B14C-403D-9A76-4C28CB042FAA","name":"clock-check-outline","codepoint":"F0FA9","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"EFE4304F-7BAB-4DB6-846C-31B368CA3BDC","name":"clock-digital","codepoint":"F0E97","aliases":[],"tags":["Date \/ Time"],"author":"GreenTurtwig","version":"3.7.94"},{"id":"F7F5CA75-E8B5-45E1-B0BA-040F225D877D","name":"clock-end","codepoint":"F0151","aliases":[],"tags":["Date \/ Time"],"author":"Simran","version":"1.5.54"},{"id":"111210EB-0EF4-4DCB-ABBD-6A75F15EEB44","name":"clock-fast","codepoint":"F0152","aliases":[],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6483D8DB-4170-4104-8A69-40D28401EF4C","name":"clock-in","codepoint":"F0153","aliases":[],"tags":["Date \/ Time"],"author":"Simran","version":"1.5.54"},{"id":"7C3F10AF-CB56-4A35-B22A-C833D5C823A3","name":"clock-out","codepoint":"F0154","aliases":[],"tags":["Date \/ Time"],"author":"Simran","version":"1.5.54"},{"id":"E3A4F70D-92EF-4115-BBB3-3BE68A788F5D","name":"clock-outline","codepoint":"F0150","aliases":["access-time","query-builder","schedule"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"85A4435A-CDCF-42BC-8F2C-B46EDF8820BD","name":"clock-start","codepoint":"F0155","aliases":[],"tags":["Date \/ Time"],"author":"Simran","version":"1.5.54"},{"id":"A215B597-8863-41CD-93D7-3258F35E0323","name":"clock-time-eight","codepoint":"F1446","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"BD5AEE68-BAA7-498A-9C16-E4BAEEC10758","name":"clock-time-eight-outline","codepoint":"F1452","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"F00F4BD4-FA53-4F36-A6EF-20C61E728DE4","name":"clock-time-eleven","codepoint":"F1449","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"A157DC0E-2973-49C5-83A6-A59B395000B0","name":"clock-time-eleven-outline","codepoint":"F1455","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"5EADCD37-E186-4701-B55D-490373E248DE","name":"clock-time-five","codepoint":"F1443","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"8F93B149-9B68-43A0-9DB6-BCE3AF32DA17","name":"clock-time-five-outline","codepoint":"F144F","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"5850EAB7-9808-4FC7-B107-ECBC0D74321A","name":"clock-time-four","codepoint":"F1442","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"3EB1620A-C31A-4570-A0CA-4D4B1194B5FC","name":"clock-time-four-outline","codepoint":"F144E","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"DA361B2F-72DD-46ED-9920-558A9AD81B3B","name":"clock-time-nine","codepoint":"F1447","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"B3B33DCF-9627-4286-8D43-674E066D5CF8","name":"clock-time-nine-outline","codepoint":"F1453","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"FE16FC41-411F-423D-96AC-835A334051DF","name":"clock-time-one","codepoint":"F143F","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"CD2F6CA1-A725-4997-9EDF-7CDD3875997D","name":"clock-time-one-outline","codepoint":"F144B","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"814B2984-F25E-40EE-98E7-9CDCE300AA0C","name":"clock-time-seven","codepoint":"F1445","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"0249D6C9-BACD-4514-96DB-6ABF4C8756C4","name":"clock-time-seven-outline","codepoint":"F1451","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"58E0112F-0E05-4C53-8AF2-663009045010","name":"clock-time-six","codepoint":"F1444","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"D8D8CBCB-DCCF-4FB0-A6E2-3D45E732AD90","name":"clock-time-six-outline","codepoint":"F1450","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"5EE154C9-B581-4AB9-A086-38AE96A919E1","name":"clock-time-ten","codepoint":"F1448","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"DDACEAB9-676D-4D4A-9508-CE1241D983BC","name":"clock-time-ten-outline","codepoint":"F1454","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"DA0656E4-D609-441D-93C3-488D36BB9BDA","name":"clock-time-three","codepoint":"F1441","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"465F6D88-CD51-4BA8-AFBE-0D20845906DD","name":"clock-time-three-outline","codepoint":"F144D","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"CEA21098-6201-4E2F-A24E-865B4FFD7870","name":"clock-time-twelve","codepoint":"F144A","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"375B6D36-CFC4-4DB4-BFDE-364E129EDFBB","name":"clock-time-twelve-outline","codepoint":"F1456","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"3F6D9697-9536-4D51-87D3-839E7579451B","name":"clock-time-two","codepoint":"F1440","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"20918EE1-9806-4E1D-BD7C-A723AC2A97FF","name":"clock-time-two-outline","codepoint":"F144C","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"FEA26660-7D6A-4C2A-9F13-7AE125FBA543","name":"close","codepoint":"F0156","aliases":["clear","multiply","remove","cancel"],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"0823D18B-529A-4B7E-8090-A913399A3D5E","name":"close-box","codepoint":"F0157","aliases":["multiply-box","clear-box","cancel-box","remove-box"],"tags":["Math"],"author":"Gabriel","version":"1.5.54"},{"id":"63F3E252-98F2-4851-A887-E99FACD6B280","name":"close-box-multiple","codepoint":"F0C5D","aliases":["close-boxes","library-remove","library-close","multiply-boxes","multiply-box-multiple","cancel-box-multiple","remove-box-multiple"],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"596F26BB-8E10-4530-98CE-FFDACBF07F6B","name":"close-box-multiple-outline","codepoint":"F0C5E","aliases":["close-boxes-outline","library-remove-outline","library-close-outline","multiply-boxes-outline","multiply-box-multiple-outline","remove-box-multiple","cancel-box-multiple"],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"05B8E566-B224-4ECC-AE70-2BF8BE90C82A","name":"close-box-outline","codepoint":"F0158","aliases":["multiply-box-outline","clear-box-outline","remove-box-outline","cancel-box-outline"],"tags":["Math"],"author":"Gabriel","version":"1.5.54"},{"id":"DC0E1491-A8A0-4563-ACEC-C795D96602A7","name":"close-circle","codepoint":"F0159","aliases":["remove-circle","cancel-circle","multiply-circle","clear-circle"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"77B97AED-2613-434C-BD9C-82755C8B468C","name":"close-circle-multiple","codepoint":"F062A","aliases":["remove-circle-multiple","coins-close","coins-remove","clear-circle-multiple","multiply-circle-multiple"],"tags":[],"author":"Michael Irigoyen","version":"1.6.50"},{"id":"B77F1750-F3D8-43A5-A2D1-EEF2E3EB584B","name":"close-circle-multiple-outline","codepoint":"F0883","aliases":["remove-circle-multiple-outline","coins-close-outline","coins-remove-outline","cancel-circle-multiple-outline","multiply-circle-multiple-outline","clear-circle-multiple-outline"],"tags":[],"author":"Michael Irigoyen","version":"2.1.99"},{"id":"EA41E6BB-A176-4E0E-896A-36F9FA5AA62F","name":"close-circle-outline","codepoint":"F015A","aliases":["highlight-off","multiply-circle-outline","remove-circle-outline","clear-circle-outline","cancel-circle-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4043C369-E619-47E9-9363-E5E9C43457FB","name":"close-network","codepoint":"F015B","aliases":["remove-network","cancel-network","multiply-network","clear-network"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"6BB0D686-C2A2-47D0-A50C-91E0300AF12E","name":"close-network-outline","codepoint":"F0C5F","aliases":["remove-network-outline","cancel-network-outline","multiply-network-outline","clear-network-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"BA7E9F56-A5F5-4BEE-8934-90CA070A6029","name":"close-octagon","codepoint":"F015C","aliases":["dangerous","multiply-octagon","remove-octagon","cancel-octagon","clear-octagon","stop-remove"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"9676C4C3-D8C3-44A6-A447-59A56A15DA34","name":"close-octagon-outline","codepoint":"F015D","aliases":["remove-octagon-outline","multiply-octagon-outline","clear-octagon-outline","cancel-octagon-outline","stop-remove-outline"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"2FEE0020-4271-487C-897D-75529B20C4C6","name":"close-outline","codepoint":"F06C9","aliases":["remove-outline","cancel-outline","multiply-outline","clear-outline"],"tags":[],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"C6B8442F-446D-4690-866F-AF0F27C1EAB2","name":"close-thick","codepoint":"F1398","aliases":["close-bold","remove-thick","remove-bold","multiply-thick","multiply-bold","clear-thick","clear-bold","cancel-thick","cancel-bold"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"5367B460-F7E5-46C5-A4F5-40B339BF9DAD","name":"closed-caption","codepoint":"F015E","aliases":["cc"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"08F32D33-77C4-4FEB-AAF6-04468AF0875F","name":"closed-caption-outline","codepoint":"F0DBD","aliases":["cc-outline"],"tags":[],"author":"Google","version":"3.5.94"},{"id":"CF07C502-388E-4A65-BD89-FACCFD00C245","name":"cloud","codepoint":"F015F","aliases":["wb-cloudy"],"tags":["Cloud","Weather"],"author":"Google","version":"1.5.54"},{"id":"4ACCBA06-78DB-492F-98F6-08AEE743744A","name":"cloud-alert","codepoint":"F09E0","aliases":["cloud-warning"],"tags":["Alert \/ Error","Cloud","Weather"],"author":"TheChilliPL","version":"2.5.94"},{"id":"6ED02FDD-323E-4004-9D7B-336F2402DF8E","name":"cloud-braces","codepoint":"F07B5","aliases":["cloud-json"],"tags":["Cloud"],"author":"Andy Martinez","version":"2.0.46"},{"id":"5B607B90-B492-43AD-A5B0-4AC800A9F7DA","name":"cloud-check","codepoint":"F0160","aliases":["cloud-done","cloud-tick"],"tags":["Cloud"],"author":"Google","version":"1.5.54"},{"id":"A56D0A20-FC19-455F-B1E8-3CA24270957A","name":"cloud-check-outline","codepoint":"F12CC","aliases":[],"tags":["Cloud"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"06BCD41B-8BFF-43C0-88A1-69F262C51C5F","name":"cloud-circle","codepoint":"F0161","aliases":[],"tags":["Cloud"],"author":"Google","version":"1.5.54"},{"id":"D8C49CD8-61B2-4F34-A4B8-543396B4A610","name":"cloud-download","codepoint":"F0162","aliases":[],"tags":["Cloud"],"author":"Google","version":"1.5.54"},{"id":"41CC8340-22F2-4C91-BA1E-97E3A0EA461F","name":"cloud-download-outline","codepoint":"F0B7D","aliases":[],"tags":["Cloud"],"author":"Google","version":"3.0.39"},{"id":"8F0ED421-A552-4920-A46D-13F246A25689","name":"cloud-lock","codepoint":"F11F1","aliases":[],"tags":["Cloud","Lock"],"author":"Michael Richins","version":"4.5.95"},{"id":"9ADC05C4-6BC2-4D66-80B0-CB6677A08271","name":"cloud-lock-outline","codepoint":"F11F2","aliases":[],"tags":["Cloud","Lock"],"author":"Michael Richins","version":"4.5.95"},{"id":"E19C3062-FFE5-441C-91C8-B1792E3AA3CA","name":"cloud-off-outline","codepoint":"F0164","aliases":[],"tags":["Cloud"],"author":"Google","version":"1.5.54"},{"id":"6EBE020D-405B-4E36-8B47-CAC6FAF1166C","name":"cloud-outline","codepoint":"F0163","aliases":["cloud-queue"],"tags":["Cloud","Weather"],"author":"Google","version":"1.5.54"},{"id":"DB32F759-BA18-488B-9260-9A38529BE7A8","name":"cloud-print","codepoint":"F0165","aliases":[],"tags":["Cloud","Printer","Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"7B3F8F72-1F4B-429A-B969-8E42ADBBD3E1","name":"cloud-print-outline","codepoint":"F0166","aliases":[],"tags":["Cloud","Printer","Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"C36FF6E2-EF4E-4FD1-9620-9580BC48B325","name":"cloud-question","codepoint":"F0A39","aliases":[],"tags":["Cloud"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"1771EA83-96FC-4A06-8A03-E4048C9F9C27","name":"cloud-refresh","codepoint":"F052A","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"BF384FFB-7E5D-4C2E-ADC5-4BEEAF61A81C","name":"cloud-search","codepoint":"F0956","aliases":[],"tags":["Cloud"],"author":"Michael Richins","version":"2.4.85"},{"id":"5C72BE2A-A04D-4B36-9390-024C5A1214D9","name":"cloud-search-outline","codepoint":"F0957","aliases":[],"tags":["Cloud"],"author":"Michael Richins","version":"2.4.85"},{"id":"BEA2DB85-AD43-4208-8F5E-5029997B23B7","name":"cloud-sync","codepoint":"F063F","aliases":[],"tags":["Cloud"],"author":"Michael Irigoyen","version":"1.6.50"},{"id":"FA6B7B54-7817-40EE-9A64-3D30EAC0F4CF","name":"cloud-sync-outline","codepoint":"F12D6","aliases":[],"tags":["Cloud"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"AE3A5033-BA77-4E82-BFD0-4C23275B602F","name":"cloud-tags","codepoint":"F07B6","aliases":["cloud-xml"],"tags":["Cloud"],"author":"Andy Martinez","version":"2.0.46"},{"id":"BB4F16F6-B596-4725-8831-A794321542EB","name":"cloud-upload","codepoint":"F0167","aliases":["backup"],"tags":["Cloud"],"author":"Google","version":"1.5.54"},{"id":"88ACA1F5-0FDE-4E89-8144-28BA5E5F1B51","name":"cloud-upload-outline","codepoint":"F0B7E","aliases":["backup-outline"],"tags":["Cloud"],"author":"Google","version":"3.0.39"},{"id":"0B70716D-3C56-43F1-85D4-B264C05DCC32","name":"clover","codepoint":"F0816","aliases":["luck"],"tags":["Nature"],"author":"Michael Richins","version":"2.1.19"},{"id":"113768A1-5B09-41DD-9570-31434A34823D","name":"coach-lamp","codepoint":"F1020","aliases":["coach-light","carriage-lamp","carriage-light"],"tags":["Home Automation"],"author":"Borre Haugen","version":"4.1.95"},{"id":"21D89E60-3522-4F1F-A1D2-60E67B2C9552","name":"coat-rack","codepoint":"F109E","aliases":[],"tags":["Home Automation","Clothing"],"author":"Michael Richins","version":"4.2.95"},{"id":"04020C45-A5ED-4D33-A7BD-AE986516C0DE","name":"code-array","codepoint":"F0168","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1F6661BC-6538-4EF0-92B5-46EFAE5E0C77","name":"code-braces","codepoint":"F0169","aliases":["set"],"tags":["Developer \/ Languages","Math"],"author":"Simran","version":"1.5.54"},{"id":"A65C5C08-F94C-4A68-BA7B-5557C94C5C37","name":"code-braces-box","codepoint":"F10D6","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"C08498C1-E43B-4E79-817C-121AD2827689","name":"code-brackets","codepoint":"F016A","aliases":["square-brackets"],"tags":["Developer \/ Languages","Math"],"author":"Simran","version":"1.5.54"},{"id":"16C07036-EE56-4447-8495-EB2FAD143072","name":"code-equal","codepoint":"F016B","aliases":[],"tags":["Developer \/ Languages"],"author":"Simran","version":"1.5.54"},{"id":"2C70B20E-4B20-4CF6-8775-339C1184E032","name":"code-greater-than","codepoint":"F016C","aliases":[],"tags":["Developer \/ Languages","Math"],"author":"Simran","version":"1.5.54"},{"id":"3C9D2060-53C2-4D66-BE38-C46EE87D8D46","name":"code-greater-than-or-equal","codepoint":"F016D","aliases":[],"tags":["Developer \/ Languages","Math"],"author":"Simran","version":"1.5.54"},{"id":"24C1AA84-85C2-41F4-A5E3-8FE7421CD359","name":"code-json","codepoint":"F0626","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"92266B3A-6EC4-4CE7-9904-2A793B2A4084","name":"code-less-than","codepoint":"F016E","aliases":[],"tags":["Developer \/ Languages","Math"],"author":"Simran","version":"1.5.54"},{"id":"3D003F4A-7BCB-4946-AE70-CCAA2B7D5B10","name":"code-less-than-or-equal","codepoint":"F016F","aliases":[],"tags":["Developer \/ Languages","Math"],"author":"Simran","version":"1.5.54"},{"id":"1A01458F-59E8-4AF9-B398-8058900EE85F","name":"code-not-equal","codepoint":"F0170","aliases":[],"tags":["Developer \/ Languages"],"author":"Simran","version":"1.5.54"},{"id":"05E12366-E7AA-46B9-8D6E-3664EBD34BB3","name":"code-not-equal-variant","codepoint":"F0171","aliases":[],"tags":["Developer \/ Languages"],"author":"Simran","version":"1.5.54"},{"id":"A4E1DE1B-754D-4884-9902-8D5DDE2182B0","name":"code-parentheses","codepoint":"F0172","aliases":[],"tags":["Developer \/ Languages"],"author":"Simran","version":"1.5.54"},{"id":"2609C9BB-3F62-432A-9D27-0D30845F8086","name":"code-parentheses-box","codepoint":"F10D7","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"76686B91-00D8-4ADD-A502-8D1788C9C17B","name":"code-string","codepoint":"F0173","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.5.54"},{"id":"609A0AB0-05EE-4824-BD40-A4E78F4A74D3","name":"code-tags","codepoint":"F0174","aliases":[],"tags":["Developer \/ Languages"],"author":"Google","version":"1.5.54"},{"id":"7F098441-8B1D-4FB1-88EC-95726397BA7C","name":"code-tags-check","codepoint":"F0694","aliases":["code-tags-tick"],"tags":["Developer \/ Languages"],"author":"Simran","version":"1.7.12"},{"id":"FB9F6D89-8A07-407E-AD97-AAEF0E022585","name":"codepen","codepoint":"F0175","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"1.5.54"},{"id":"C95D04C5-F5EE-411A-88F7-A9872B2B4021","name":"coffee","codepoint":"F0176","aliases":["tea","cup","free-breakfast","local-cafe","drink"],"tags":["Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"62F4C783-4BE1-4EB6-B454-E41A50B91857","name":"coffee-maker","codepoint":"F109F","aliases":["espresso-maker","coffee-machine","espresso-machine"],"tags":["Home Automation","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"E3C8FAA1-E273-44BC-8C43-1CB0E5E5C2AB","name":"coffee-off","codepoint":"F0FAA","aliases":["drink-off","tea-off","cup-off","free-breakfast-off","local-cafe-off"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"B8D17AA8-7B65-4CA7-B9A9-6960C2A64164","name":"coffee-off-outline","codepoint":"F0FAB","aliases":["drink-off-outline","cup-off-outline","tea-off-outline","free-breakfast-off-outline","local-cafe-off-outline"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"8994C73B-937C-4541-AAFF-6FA2CE0573DF","name":"coffee-outline","codepoint":"F06CA","aliases":["tea-outline","cup-outline","drink-outline","free-breakfast-outline","local-cafe-outline"],"tags":["Food \/ Drink"],"author":"Google","version":"1.8.36"},{"id":"8093CDE7-C795-4415-94C6-2EF40ED6D057","name":"coffee-to-go","codepoint":"F0177","aliases":["tea-to-go","drink-to-go","cup-to-go","free-breakfast-to-go","local-cafe-to-go"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DC66752A-65C6-461D-AAA6-65E8389E7D3B","name":"coffee-to-go-outline","codepoint":"F130E","aliases":["tea-to-go-outline","cup-to-go-outline","drink-to-go-outline","free-breakfast-to-go-outline","local-cafe-to-go-outline"],"tags":["Food \/ Drink"],"author":"Simran","version":"4.8.95"},{"id":"AC6E8289-8D3C-4CE0-ADA6-D17DC639B7FB","name":"coffin","codepoint":"F0B7F","aliases":[],"tags":["Holiday"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"E4A14909-3821-4DB1-A739-4DA464ABEEB7","name":"cog","codepoint":"F0493","aliases":["settings","gear"],"tags":["Settings"],"author":"Google","version":"1.5.54"},{"id":"6F15658D-723C-4BE9-85D1-F170E4B90281","name":"cog-box","codepoint":"F0494","aliases":["gear-box","settings-applications","settings-box"],"tags":["Settings"],"author":"Google","version":"1.5.54"},{"id":"3E835EBE-D768-428D-8440-E162EC9F90E4","name":"cog-clockwise","codepoint":"F11DD","aliases":[],"tags":["Settings"],"author":"Fran\u00e7ois Risoud","version":"4.5.95"},{"id":"C9468BA3-4E63-41DB-BACE-4AED3A543147","name":"cog-counterclockwise","codepoint":"F11DE","aliases":[],"tags":["Settings"],"author":"Fran\u00e7ois Risoud","version":"4.5.95"},{"id":"7251B1CF-41C8-46F7-991D-83F5996CF0C1","name":"cog-off","codepoint":"F13CE","aliases":["settings-off"],"tags":["Settings"],"author":"Simran","version":"5.1.45"},{"id":"83E26995-9267-4A7B-8271-885FEF6303D8","name":"cog-off-outline","codepoint":"F13CF","aliases":["settings-off-outline"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"D29B92ED-BC81-44F0-8031-2E48A90ABAD8","name":"cog-outline","codepoint":"F08BB","aliases":["gear-outline","settings-outline"],"tags":["Settings"],"author":"Google","version":"2.2.43"},{"id":"5F716B9D-4A30-4D1A-B452-B6B0D8B27EDE","name":"cog-refresh","codepoint":"F145E","aliases":["settings-refresh"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"C9E15196-FEB0-4F26-96C2-0E050F959806","name":"cog-refresh-outline","codepoint":"F145F","aliases":["settings-refresh-outline"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"BEC36759-CFB0-4475-A65B-B10F860E850A","name":"cog-sync","codepoint":"F1460","aliases":["settings-sync"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"204F6FF9-EFD1-4B79-9DDF-2642984189F0","name":"cog-sync-outline","codepoint":"F1461","aliases":["settings-sync-outline"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"17CD5A77-2809-4DDC-B876-877D8B913217","name":"cog-transfer","codepoint":"F105B","aliases":["settings-transfer"],"tags":["Settings"],"author":"Michael Richins","version":"4.1.95"},{"id":"AD008794-9094-40B5-91E8-6648E1CBADAD","name":"cog-transfer-outline","codepoint":"F105C","aliases":["settings-transfer-outline"],"tags":["Settings"],"author":"Michael Richins","version":"4.1.95"},{"id":"2EF56130-ECE9-4432-B59E-36F646DE1C86","name":"cogs","codepoint":"F08D6","aliases":["settings","manufacturing"],"tags":["Settings"],"author":"Google","version":"2.3.50"},{"id":"8FD44CCD-5073-4C73-98BE-139F777F6E94","name":"collage","codepoint":"F0640","aliases":["auto-awesome-mosaic"],"tags":[],"author":"Google","version":"1.6.50"},{"id":"C66052C9-BB2A-4E5F-A890-C6D8156E5621","name":"collapse-all","codepoint":"F0AA6","aliases":["animation-minus"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"8672E491-9415-4259-A9E5-E0E3552187CB","name":"collapse-all-outline","codepoint":"F0AA7","aliases":["animation-minus-outline"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"F27490D2-F7BE-4B35-83E6-40D1F7247755","name":"color-helper","codepoint":"F0179","aliases":["colour-helper"],"tags":["Text \/ Content \/ Format","Color"],"author":"Google","version":"1.5.54"},{"id":"55F32835-0982-43F9-9F2D-42585183016A","name":"comma","codepoint":"F0E23","aliases":[],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"CEC57068-18E1-42DA-8788-EDCC009DFB7D","name":"comma-box","codepoint":"F0E2B","aliases":[],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"19DFF0F1-FA41-4345-8494-32F42055155B","name":"comma-box-outline","codepoint":"F0E24","aliases":[],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"71A7159C-EFDE-4B44-B956-47D588CF74D3","name":"comma-circle","codepoint":"F0E25","aliases":[],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"0958EE2B-BD3A-4548-A641-759FC170847A","name":"comma-circle-outline","codepoint":"F0E26","aliases":[],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"B42FD735-27ED-47EC-887B-F5108774E6BC","name":"comment","codepoint":"F017A","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E0D4328B-7A71-46E7-804B-DFC3753BEDF6","name":"comment-account","codepoint":"F017B","aliases":["comment-user","comment-person"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"1.5.54"},{"id":"18A9FFE4-B768-4A8F-BD55-778C8E8C41FC","name":"comment-account-outline","codepoint":"F017C","aliases":["comment-user-outline","comment-person-outline"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"1.5.54"},{"id":"04CF8C3D-0D65-41CA-8D0D-53DD7EAB25B8","name":"comment-alert","codepoint":"F017D","aliases":["comment-warning"],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CBAD69A4-A6FF-4A8A-AA85-B5962910106E","name":"comment-alert-outline","codepoint":"F017E","aliases":["comment-warning-outline"],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AECA1A18-D8EA-4130-B33C-86D608E030BB","name":"comment-arrow-left","codepoint":"F09E1","aliases":["comment-previous"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"192F008B-D02E-4C2A-A43F-058A19E41D30","name":"comment-arrow-left-outline","codepoint":"F09E2","aliases":["comment-previous-outline"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"256DE915-25D5-4777-AA1A-A432ABB6E039","name":"comment-arrow-right","codepoint":"F09E3","aliases":["comment-next"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"E34BA65C-995B-4E2F-A40E-8833E55187FC","name":"comment-arrow-right-outline","codepoint":"F09E4","aliases":["comment-next-outline"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"AEB3B1E9-D2B4-497C-9939-BFB549F57019","name":"comment-bookmark","codepoint":"F15AE","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"342B6E5C-FE9B-4A5A-940C-3918AB609441","name":"comment-bookmark-outline","codepoint":"F15AF","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"5D2CEEF1-3F19-4AD2-8965-13DB365B0013","name":"comment-check","codepoint":"F017F","aliases":["comment-tick"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D9BBEE92-5775-4364-8ECD-89C0872BE79F","name":"comment-check-outline","codepoint":"F0180","aliases":["comment-tick-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8729ADA4-D1A0-477A-B670-EC5CFF2A3A7E","name":"comment-edit","codepoint":"F11BF","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"3A7903C6-EA94-4FF6-8B95-FECC91058756","name":"comment-edit-outline","codepoint":"F12C4","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"7CDBE4A1-9E98-419D-A309-4ECB9476DA12","name":"comment-eye","codepoint":"F0A3A","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"470DE0A7-8431-42B7-BC50-E46D0DEBE759","name":"comment-eye-outline","codepoint":"F0A3B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"27CE0231-2BF3-43E1-9852-3044D59DA0F2","name":"comment-flash","codepoint":"F15B0","aliases":["comment-quick"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"68AA7A36-BF66-4F18-8BEE-78448FDBF5B9","name":"comment-flash-outline","codepoint":"F15B1","aliases":["comment-quick-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"B3DD4217-5AB7-4E9F-979E-7E16A2DA8E76","name":"comment-minus","codepoint":"F15DF","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"C63B509C-5F87-42E1-A53B-0623A2EA4461","name":"comment-minus-outline","codepoint":"F15E0","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"63AC824E-16A4-4FBE-A6DF-588DEBCA47C1","name":"comment-multiple","codepoint":"F085F","aliases":["comments"],"tags":[],"author":"Michael Richins","version":"2.1.99"},{"id":"A5FAC5DC-088F-485C-A885-FBBEEC70B352","name":"comment-multiple-outline","codepoint":"F0181","aliases":["comments-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"9BBD8848-EA4F-4052-9361-B5D7AFCEBFF6","name":"comment-off","codepoint":"F15E1","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"14104E5E-1FA3-441C-9705-66D86F8E28DB","name":"comment-off-outline","codepoint":"F15E2","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"B1A0A26E-3E9C-4718-8A26-2837A981D9B5","name":"comment-outline","codepoint":"F0182","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"6C595408-3938-4111-9566-7149810D4A73","name":"comment-plus","codepoint":"F09E5","aliases":["comment-add"],"tags":[],"author":"Peter Noble","version":"2.5.94"},{"id":"813C3AFA-56D8-472B-8C1C-C365AC752663","name":"comment-plus-outline","codepoint":"F0183","aliases":["comment-add-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D07698E0-AB53-4E7A-9C25-9A25D1D5CDA9","name":"comment-processing","codepoint":"F0184","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0CDF5E61-25C4-4E30-8E16-32E4E7EDE705","name":"comment-processing-outline","codepoint":"F0185","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"49412CCB-C5F6-460F-A2DB-76BCCB668BCC","name":"comment-question","codepoint":"F0817","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.1.19"},{"id":"7BD335A6-C4A7-48F1-B04F-F1457B7B1F20","name":"comment-question-outline","codepoint":"F0186","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"6A2BA297-7401-4727-B79F-8C8DD0F56FE7","name":"comment-quote","codepoint":"F1021","aliases":["feedback"],"tags":[],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"5510BB9F-2D63-471A-86F3-732E91A513E4","name":"comment-quote-outline","codepoint":"F1022","aliases":["feedback-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"834998BB-D7F4-41F3-86B8-5EE5631B524A","name":"comment-remove","codepoint":"F05DE","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"520544E5-1693-4084-BB9C-B6FA70204B2C","name":"comment-remove-outline","codepoint":"F0187","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"02BA858D-5D62-487B-B423-22EBB73E10A9","name":"comment-search","codepoint":"F0A3C","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.6.95"},{"id":"17A45B1C-290F-4654-9C8D-3F3F641AB5CD","name":"comment-search-outline","codepoint":"F0A3D","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.6.95"},{"id":"483321DB-C7E5-4E48-B739-8500F6153446","name":"comment-text","codepoint":"F0188","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"88EDEE2E-AB1B-4287-A082-E3B139F8E69A","name":"comment-text-multiple","codepoint":"F0860","aliases":["comments-text"],"tags":[],"author":"Michael Richins","version":"2.1.99"},{"id":"B7CBD1E2-9677-4D9B-B7BD-CA5493920BE6","name":"comment-text-multiple-outline","codepoint":"F0861","aliases":["comments-text-outline"],"tags":[],"author":"Michael Richins","version":"2.1.99"},{"id":"3D9E4543-670E-4434-8C82-3A80122ED4EE","name":"comment-text-outline","codepoint":"F0189","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"A9786B48-6664-4170-B56C-6F2868D5000D","name":"compare","codepoint":"F018A","aliases":["theme-light-dark"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"C2F3461E-363D-42B9-AEF0-3E8A92EB2569","name":"compare-horizontal","codepoint":"F1492","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.3.45"},{"id":"2E95C78F-AAF9-4E1F-8241-4F781389EFF7","name":"compare-vertical","codepoint":"F1493","aliases":[],"tags":["Arrow"],"author":"Google","version":"5.3.45"},{"id":"8FE64B61-0FD6-4056-9A4F-E62408CE70FE","name":"compass","codepoint":"F018B","aliases":["explore"],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"2D283145-478B-4863-9889-CFDDB88342A3","name":"compass-off","codepoint":"F0B80","aliases":[],"tags":["Geographic Information System","Navigation"],"author":"Google","version":"3.0.39"},{"id":"ACF5388A-9C33-4466-A6E7-E0EFE1508C28","name":"compass-off-outline","codepoint":"F0B81","aliases":[],"tags":["Geographic Information System","Navigation"],"author":"Google","version":"3.0.39"},{"id":"EDA6D9AB-4AAE-4080-A1D3-78762666D7B1","name":"compass-outline","codepoint":"F018C","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Gabriel","version":"1.5.54"},{"id":"D7B6D7B4-F143-477C-A402-963791DB0029","name":"compass-rose","codepoint":"F1382","aliases":[],"tags":["Navigation"],"author":"Michael Richins","version":"4.9.95"},{"id":"9C32EF89-4919-4CF1-A266-A0AB4C1C11EA","name":"concourse-ci","codepoint":"F10A0","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.2.95"},{"id":"C66F7470-8691-4B30-A8F6-5250389E1D48","name":"connection","codepoint":"F1616","aliases":["plug"],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"DCD0A183-A5DC-43BD-BC48-8FFF0CA0FA9C","name":"console","codepoint":"F018D","aliases":["terminal"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D6FF21C5-201A-43E0-B8AF-276A6BED653A","name":"console-line","codepoint":"F07B7","aliases":["terminal-line"],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"19A41CF5-CA4E-411C-8C34-14895B4B90DD","name":"console-network","codepoint":"F08A9","aliases":["terminal-network"],"tags":[],"author":"Michael Richins","version":"2.2.43"},{"id":"48F71C58-812D-40AA-BC4D-9D4381684E90","name":"console-network-outline","codepoint":"F0C60","aliases":["terminal-network-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"79D6D751-2470-4ACC-B67E-40F5FF12BC25","name":"consolidate","codepoint":"F10D8","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"45F3DDED-3C5E-4B6B-941E-7283657A1577","name":"contactless-payment","codepoint":"F0D6A","aliases":[],"tags":["Currency"],"author":"Michael Richins","version":"3.4.93"},{"id":"445CF970-F03C-4DDC-A326-F77DA919CB39","name":"contactless-payment-circle","codepoint":"F0321","aliases":[],"tags":["Currency"],"author":"Google","version":"1.5.54"},{"id":"E7D24172-A5A7-4BAE-A679-D2191E8E7F51","name":"contactless-payment-circle-outline","codepoint":"F0408","aliases":[],"tags":["Currency"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"5A68EA78-9792-4223-808D-17E5205765E6","name":"contacts","codepoint":"F06CB","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"5D5E7753-B3F1-4D0C-B175-62749D448492","name":"contacts-outline","codepoint":"F05B8","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"44029D6D-5640-4AE5-907B-8388B0438FF0","name":"contain","codepoint":"F0A3E","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"B786A80C-161C-492C-B405-A10087092CDC","name":"contain-end","codepoint":"F0A3F","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"5161A499-05B1-444F-84E6-359F5C46F84C","name":"contain-start","codepoint":"F0A40","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"2B3B8FC2-C8AB-40AF-9B3F-AFFC93482676","name":"content-copy","codepoint":"F018F","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D4028362-37C3-4EED-BE0B-C78927C3F55D","name":"content-cut","codepoint":"F0190","aliases":["scissors","clip"],"tags":["Health \/ Beauty"],"author":"Google","version":"1.5.54"},{"id":"B1A86989-2CB4-47DC-BC93-67A077792F72","name":"content-duplicate","codepoint":"F0191","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"75856C98-A0D6-4C78-A323-BD170B6E6094","name":"content-paste","codepoint":"F0192","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"29F946C0-CA58-4287-AF0B-964961E5CC2C","name":"content-save","codepoint":"F0193","aliases":["floppy-disc"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"E4BAD28B-B196-42B5-BD4D-92C81A8EADAE","name":"content-save-alert","codepoint":"F0F42","aliases":["floppy-disc-alert"],"tags":["Alert \/ Error"],"author":"Michael Richins","version":"3.9.97"},{"id":"21B9916D-3D1A-43AF-91B2-56A4D5C493C2","name":"content-save-alert-outline","codepoint":"F0F43","aliases":["floppy-disc-alert-outline"],"tags":["Alert \/ Error"],"author":"Michael Richins","version":"3.9.97"},{"id":"B9BE7889-D858-41A1-AB4E-9C58325261E9","name":"content-save-all","codepoint":"F0194","aliases":["floppy-disc-multiple"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B65ADBE9-DE1B-4879-A34F-602A3DA4D12A","name":"content-save-all-outline","codepoint":"F0F44","aliases":["floppy-disc-multiple-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"E909F872-44CC-4D23-8AD2-95BFE02A5E2D","name":"content-save-cog","codepoint":"F145B","aliases":["floppy-disc-cog"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"A145BFEF-B18C-49C5-B24C-7918C878307E","name":"content-save-cog-outline","codepoint":"F145C","aliases":["floppy-disc-cog-outline"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"12E2DE0D-BF3F-402D-8044-B18E269D32C2","name":"content-save-edit","codepoint":"F0CFB","aliases":["floppy-disc-edit"],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"B8D3719E-E67F-4008-9F43-458D75857769","name":"content-save-edit-outline","codepoint":"F0CFC","aliases":["floppy-disc-edit-outline"],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"FC4F757F-2540-4853-89A3-7FE07FC710C0","name":"content-save-move","codepoint":"F0E27","aliases":["floppy-disc-move"],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"12F9DD45-1D74-45E3-84B7-CDE90A3FD174","name":"content-save-move-outline","codepoint":"F0E28","aliases":["floppy-disc-move-outline"],"tags":[],"author":"Michael Richins","version":"3.6.95"},{"id":"E5889AAE-7F3E-46F3-BEF6-36F4BE570DE8","name":"content-save-off","codepoint":"F1643","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"178D08A9-7C54-4F7A-9335-726030578718","name":"content-save-off-outline","codepoint":"F1644","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"707F4114-BD2F-4601-82C4-CFB6B2D2F359","name":"content-save-outline","codepoint":"F0818","aliases":[],"tags":[],"author":"Google","version":"2.1.19"},{"id":"67E755F6-209A-41EF-98C5-423739A3AC10","name":"content-save-settings","codepoint":"F061B","aliases":["floppy-disc-settings"],"tags":["Settings"],"author":"Simran","version":"1.6.50"},{"id":"2EDEEDF4-2AE3-4365-8F49-DC6F869EC520","name":"content-save-settings-outline","codepoint":"F0B2E","aliases":["floppy-disc-settings-outline"],"tags":["Settings"],"author":"Contributors","version":"2.8.94"},{"id":"B50D388A-4647-4780-83E7-2C5AD8375FB9","name":"contrast","codepoint":"F0195","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B7FCC914-C6E9-4919-8574-F0161C2CF28D","name":"contrast-box","codepoint":"F0196","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A7CBFD5D-FDFD-4202-A290-840219A79F2F","name":"contrast-circle","codepoint":"F0197","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"2D97B0F0-9662-4323-8F5B-0677507461EE","name":"controller-classic","codepoint":"F0B82","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"3.0.39"},{"id":"053ECCDF-BF30-417F-85D4-FF2614402B5A","name":"controller-classic-outline","codepoint":"F0B83","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"3.0.39"},{"id":"8E3FB537-B293-41A6-B6C5-B2BE927091F5","name":"cookie","codepoint":"F0198","aliases":["biscuit"],"tags":["Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"D37F1726-BDD9-4AFB-84E0-A62587AAA6CC","name":"cookie-alert","codepoint":"F16D0","aliases":["biscuit-alert"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"927FC7C7-8DF3-47FE-BAC4-7DF8DAF3F936","name":"cookie-alert-outline","codepoint":"F16D1","aliases":["biscuit-alert-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"DB07C270-5421-41A3-BBFF-350874DE3534","name":"cookie-check","codepoint":"F16D2","aliases":["biscuit-check"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"65B2C1ED-992F-45D8-A0C0-4481F99748BF","name":"cookie-check-outline","codepoint":"F16D3","aliases":["biscuit-check-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"9DEBBFC6-6734-4D46-A7C0-3A11793C4708","name":"cookie-clock","codepoint":"F16E4","aliases":["biscuit-clock"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"5F7A7D4A-D4ED-4AE6-987D-A735A7403C00","name":"cookie-clock-outline","codepoint":"F16E5","aliases":["biscuit-clock-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"5923CF0C-4D34-4BF1-8401-3AEEDC0DE9BC","name":"cookie-cog","codepoint":"F16D4","aliases":["biscuit-cog"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"96AE483D-C5CD-424A-A553-C9D5399CAD7F","name":"cookie-cog-outline","codepoint":"F16D5","aliases":["biscuit-cog-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"E36B77B1-913A-45CC-A23B-02EA12161352","name":"cookie-edit","codepoint":"F16E6","aliases":["biscuit-edit"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"0A7C1A34-8BC9-4A44-93F3-59F9235274AB","name":"cookie-edit-outline","codepoint":"F16E7","aliases":["biscuit-edit-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"FD4F6EA6-712D-4E1E-AF1E-25CB27AE66CE","name":"cookie-lock","codepoint":"F16E8","aliases":["biscuit-lock"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"CB5D57DF-BA59-4C98-9FA7-96536EF9FAA0","name":"cookie-lock-outline","codepoint":"F16E9","aliases":["biscuit-lock-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"215F338E-A35C-4C54-9AC7-C4F4BB9A7206","name":"cookie-minus","codepoint":"F16DA","aliases":["biscuit-minus"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"E5590F64-7B4E-4506-AF93-ED7F3E6AB988","name":"cookie-minus-outline","codepoint":"F16DB","aliases":["biscuit-minus-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"9B401BB3-9510-457F-9C35-BAC5A30BF91F","name":"cookie-off","codepoint":"F16EA","aliases":["biscuit-off"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"4355ECEC-E157-4BC8-AF80-45FAC597F188","name":"cookie-off-outline","codepoint":"F16EB","aliases":["biscuit-off-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"AF77B3DF-8565-4A84-A58F-83FD2E55EB10","name":"cookie-outline","codepoint":"F16DE","aliases":["biscuit-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"272BE458-B01F-4437-B083-65175B327D05","name":"cookie-plus","codepoint":"F16D6","aliases":["biscuit-plus"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"AB2BBE22-85B2-4D5B-9F99-099DE970A9EC","name":"cookie-plus-outline","codepoint":"F16D7","aliases":["biscuit-plus-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"184857B9-228F-4DD2-AF53-603277AEEB7F","name":"cookie-refresh","codepoint":"F16EC","aliases":["biscuit-refresh"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"CA84B827-73C5-4C28-AC8B-82AADD5469E9","name":"cookie-refresh-outline","codepoint":"F16ED","aliases":["biscuit-refresh-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"25272102-387C-4333-BF16-3308E6EFF94F","name":"cookie-remove","codepoint":"F16D8","aliases":["biscuit-remove"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"12200D0C-1B01-4165-A2D1-C5BE30B3E3A7","name":"cookie-remove-outline","codepoint":"F16D9","aliases":["biscuit-remove-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"B8F9243C-188F-4EC1-9051-5BAA942D7F42","name":"cookie-settings","codepoint":"F16DC","aliases":["biscuit-settings","cookie-crumbs","biscuit-crumbs"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"FF72A11B-A9E5-47B7-967F-C520DC965CE2","name":"cookie-settings-outline","codepoint":"F16DD","aliases":["biscuit-settings-outline","cookie-crumbs-outline","biscuit-crumbs-outline"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"A260896B-178E-4E3A-9F2C-793AD68154F4","name":"coolant-temperature","codepoint":"F03C8","aliases":[],"tags":["Automotive"],"author":"Simran","version":"1.5.54"},{"id":"34B43A77-9873-4723-AA65-45D42992748E","name":"copyright","codepoint":"F05E6","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"C3F97D60-41A7-49A3-A8B7-C63D724B12FF","name":"cordova","codepoint":"F0958","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"2.4.85"},{"id":"B49614ED-B7AB-4123-BD9C-B50CE119C76C","name":"corn","codepoint":"F07B8","aliases":[],"tags":["Agriculture","Food \/ Drink"],"author":"Thomas Hunsaker","version":"2.0.46"},{"id":"E2947B22-1F7A-4638-8B16-27DA49F5BD52","name":"corn-off","codepoint":"F13EF","aliases":[],"tags":["Food \/ Drink","Agriculture"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"4969E6E7-4311-4F1E-B9ED-070DE4473A65","name":"cosine-wave","codepoint":"F1479","aliases":[],"tags":["Audio"],"author":"Haley Halcyon","version":"5.2.45"},{"id":"F789F2E4-022E-4A5A-B548-30D21BC3A7F6","name":"counter","codepoint":"F0199","aliases":["score","numbers","odometer"],"tags":["Automotive"],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"1D459B7E-A98C-4E02-929B-FA0BA329B97F","name":"cow","codepoint":"F019A","aliases":[],"tags":["Animal","Agriculture"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BC9DA934-ED6D-4EC4-9FA4-2B6FF26B3058","name":"cpu-32-bit","codepoint":"F0EDF","aliases":["chip-32-bit"],"tags":[],"author":"GreenTurtwig","version":"3.8.95"},{"id":"BC47ABAD-66D6-4EEA-9512-CB33318F62EF","name":"cpu-64-bit","codepoint":"F0EE0","aliases":["chip-64-bit"],"tags":[],"author":"GreenTurtwig","version":"3.8.95"},{"id":"8C0FE6E3-3D82-4FCA-9CCC-73CA8C5299D1","name":"crane","codepoint":"F0862","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.1.99"},{"id":"598B7931-3DF8-4CFA-A6E6-80550CA31372","name":"creation","codepoint":"F0674","aliases":["auto-awesome"],"tags":[],"author":"Google","version":"1.7.12"},{"id":"8973B8C3-527C-48D1-9E5B-CB0A35DE2B77","name":"creative-commons","codepoint":"F0D6B","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"3.4.93"},{"id":"91CCFF94-D3F6-48B2-B62C-02DC1B6DBC1E","name":"credit-card","codepoint":"F0FEF","aliases":[],"tags":["Banking","Currency"],"author":"Michael Richins","version":"4.0.96"},{"id":"1CE6C99F-BA66-4069-B014-67E4FB6E5EB9","name":"credit-card-check","codepoint":"F13D0","aliases":[],"tags":["Banking"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"96023451-FCAA-40E0-839C-A7F98C3553F1","name":"credit-card-check-outline","codepoint":"F13D1","aliases":[],"tags":["Banking"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"0FBFF192-59C3-447E-A987-4BE568865C8E","name":"credit-card-clock","codepoint":"F0EE1","aliases":[],"tags":["Banking","Date \/ Time"],"author":"Michael Richins","version":"3.8.95"},{"id":"851D92B4-4326-4913-AA2F-05F3595614C2","name":"credit-card-clock-outline","codepoint":"F0EE2","aliases":[],"tags":["Banking","Date \/ Time"],"author":"Michael Richins","version":"3.8.95"},{"id":"21D860AE-A880-4ED2-9E11-617D888BD744","name":"credit-card-marker","codepoint":"F06A8","aliases":[],"tags":["Banking"],"author":"Michael Irigoyen","version":"1.7.12"},{"id":"B026E6BC-FFD6-44FA-96AC-6F4A902FD596","name":"credit-card-marker-outline","codepoint":"F0DBE","aliases":["cod","payment-on-delivery"],"tags":["Banking"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"97D593C8-1C57-4597-AB1C-C6B487633BBD","name":"credit-card-minus","codepoint":"F0FAC","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"E35A35BC-A59A-440D-820A-3BB61E1AA9BA","name":"credit-card-minus-outline","codepoint":"F0FAD","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"25C1F858-600D-42A4-801F-5F85F22ACB52","name":"credit-card-multiple","codepoint":"F0FF0","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"D7C8ADB6-B7C9-4653-9EA7-EB98552304BA","name":"credit-card-multiple-outline","codepoint":"F019C","aliases":["credit-cards"],"tags":["Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5DC17348-DD99-40EA-804E-CB20BEE93C07","name":"credit-card-off","codepoint":"F0FF1","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"CD527CB6-15F0-41BF-BF50-2BCB8B6C769F","name":"credit-card-off-outline","codepoint":"F05E4","aliases":[],"tags":["Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A121DBBB-C9E6-4534-AA7B-F59496787BD2","name":"credit-card-outline","codepoint":"F019B","aliases":["payment"],"tags":["Shopping","Banking","Currency"],"author":"Google","version":"1.5.54"},{"id":"DE6FDD30-069D-4377-96D1-9DAC014B6A8F","name":"credit-card-plus","codepoint":"F0FF2","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"FA914D65-0F2C-463D-A54F-9B0DE9FBEED3","name":"credit-card-plus-outline","codepoint":"F0676","aliases":["credit-card-add"],"tags":["Banking"],"author":"Austin Andrews","version":"1.7.12"},{"id":"F768F993-4A1F-4A1E-8EED-11526704C22F","name":"credit-card-refresh","codepoint":"F1645","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"0ECF7DE7-9F12-4635-902C-1BBF1064DC21","name":"credit-card-refresh-outline","codepoint":"F1646","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"90A38F47-9EFD-4468-A1B9-E31A6781F69D","name":"credit-card-refund","codepoint":"F0FF3","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"4C2633A8-8E84-4301-A470-0408DCFFEEF8","name":"credit-card-refund-outline","codepoint":"F0AA8","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"2.7.94"},{"id":"6CD92C52-D816-4930-B504-ECB4B8744CEA","name":"credit-card-remove","codepoint":"F0FAE","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"003200AA-03EB-4AFA-BE66-B1858B39DA19","name":"credit-card-remove-outline","codepoint":"F0FAF","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"A3BF84E0-A214-410C-9890-851855025247","name":"credit-card-scan","codepoint":"F0FF4","aliases":[],"tags":["Banking"],"author":"Michael Richins","version":"4.0.96"},{"id":"CF494E4E-F1FC-411D-87FD-933CC17EE08C","name":"credit-card-scan-outline","codepoint":"F019D","aliases":[],"tags":["Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"8E913524-BAAE-48B9-A45A-69192B159EE4","name":"credit-card-search","codepoint":"F1647","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"8A0B7BE3-D653-4009-8E42-B3E280F7152C","name":"credit-card-search-outline","codepoint":"F1648","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"194059D5-3FF9-4DA7-8C7E-81092D38889B","name":"credit-card-settings","codepoint":"F0FF5","aliases":[],"tags":["Banking","Settings"],"author":"Michael Richins","version":"4.0.96"},{"id":"8EF337DF-4858-4BC2-8C48-BD0911AF0FEB","name":"credit-card-settings-outline","codepoint":"F08D7","aliases":["payment-settings"],"tags":["Banking","Settings"],"author":"Peter Noble","version":"2.3.50"},{"id":"76407FAE-6EB4-4486-9A60-5D62801B78E4","name":"credit-card-sync","codepoint":"F1649","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"FB29966A-E0BE-41FC-92D0-4218B160DCF4","name":"credit-card-sync-outline","codepoint":"F164A","aliases":[],"tags":["Banking"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"7894F13C-362E-4628-B0D4-E9AC990CCB41","name":"credit-card-wireless","codepoint":"F0802","aliases":[],"tags":["Currency","Banking"],"author":"Michael Irigoyen","version":"2.1.19"},{"id":"9BDEAB2C-8D25-43FA-9722-9FD68D21E76A","name":"credit-card-wireless-off","codepoint":"F057A","aliases":[],"tags":["Banking"],"author":"Simran","version":"1.5.54"},{"id":"00E657E0-F05A-423A-813F-3DC14C5E6439","name":"credit-card-wireless-off-outline","codepoint":"F057B","aliases":[],"tags":["Banking"],"author":"Simran","version":"1.5.54"},{"id":"694399D0-1348-4EB0-BA34-ECD2FE4987C2","name":"credit-card-wireless-outline","codepoint":"F0D6C","aliases":["credit-card-contactless"],"tags":["Currency","Banking"],"author":"Michael Richins","version":"3.4.93"},{"id":"9C7DBA7B-099C-460D-BD51-2B2F70EBE39A","name":"cricket","codepoint":"F0D6D","aliases":["cricket-bat"],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"FA68ACCA-389F-453E-B886-FF3DAFE10530","name":"crop","codepoint":"F019E","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"17AB799B-F531-4800-A7DE-23C5D95238F4","name":"crop-free","codepoint":"F019F","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DE641C3F-FEF6-4764-A276-F6FECFE031DA","name":"crop-landscape","codepoint":"F01A0","aliases":["crop-5-4"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"02E45E84-72D2-4FE1-BF98-6A9521E31A8A","name":"crop-portrait","codepoint":"F01A1","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"03774672-2612-4A56-9E32-69060B32B94C","name":"crop-rotate","codepoint":"F0696","aliases":[],"tags":[],"author":"Google","version":"1.7.12"},{"id":"72BA6354-04A5-4BE9-A84C-843B9441164E","name":"crop-square","codepoint":"F01A2","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"33845FDE-0003-4780-8DC9-07FC29D46599","name":"crosshairs","codepoint":"F01A3","aliases":["gps-not-fixed","location-searching"],"tags":["Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"D3A1EC2E-98D5-46B6-BF33-DECBBAACEFBE","name":"crosshairs-gps","codepoint":"F01A4","aliases":["gps-fixed","my-location"],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"BD55C800-ECAF-4839-82BD-980B3891ADF5","name":"crosshairs-off","codepoint":"F0F45","aliases":[],"tags":["Geographic Information System"],"author":"Google","version":"3.9.97"},{"id":"0842BFCE-4511-40B1-8E66-33CFED0A139B","name":"crosshairs-question","codepoint":"F1136","aliases":["crosshairs-unknown","gps-unknown"],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"4.4.95"},{"id":"266349FD-1B26-4BCD-A682-D25C4469B682","name":"crown","codepoint":"F01A5","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D0B6994F-78AD-4D69-ADED-CD0C15D0D62B","name":"crown-outline","codepoint":"F11D0","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.5.95"},{"id":"803712F9-6CAD-47C9-8B54-08B134949FB3","name":"cryengine","codepoint":"F0959","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.4.85"},{"id":"730684B8-2187-4AD1-A257-CECF232856FD","name":"crystal-ball","codepoint":"F0B2F","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"2.8.94"},{"id":"64E19922-572B-41F8-9139-BE6CBC8A0F80","name":"cube","codepoint":"F01A6","aliases":[],"tags":["Shape"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C2D996BC-2459-44E7-94FB-EE181E03B8C3","name":"cube-off","codepoint":"F141C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"0A2F7725-8D0E-4C67-8EC3-03D8F92EEB33","name":"cube-off-outline","codepoint":"F141D","aliases":["sugar-off","sugar-cube-off","sugar-free"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"11B7F7B5-8813-48DE-9469-B1159355DDC3","name":"cube-outline","codepoint":"F01A7","aliases":["sugar","sugar-cube"],"tags":["Shape","Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"101B8439-F611-400E-A2DF-0D7AE40C1005","name":"cube-scan","codepoint":"F0B84","aliases":["view-in-ar","view-in-augmented-reality"],"tags":[],"author":"Google","version":"3.0.39"},{"id":"F0726D57-782C-44E8-A404-336480FC9E7B","name":"cube-send","codepoint":"F01A8","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"A22472A9-D83E-4234-AAF0-F60AFB7C57DB","name":"cube-unfolded","codepoint":"F01A9","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D5DA2C54-C8D0-469F-99A9-C8DB9D3A6F15","name":"cup","codepoint":"F01AA","aliases":["glass","drink"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FD336A31-52C0-41AF-A0F3-BA475DEA1A54","name":"cup-off","codepoint":"F05E5","aliases":["glass-off","drink-off"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C3BC4A94-7F95-4E12-A715-45830DEDA014","name":"cup-off-outline","codepoint":"F137D","aliases":["glass-off-outline","drink-off-outline"],"tags":["Food \/ Drink"],"author":"Simran","version":"4.9.95"},{"id":"FEA3388A-F985-482C-8CE0-0B4ABCD31691","name":"cup-outline","codepoint":"F130F","aliases":["glass-outline","drink-outline"],"tags":["Food \/ Drink"],"author":"Simran","version":"4.8.95"},{"id":"AC4AD054-775A-4D59-BF92-A57A6A952607","name":"cup-water","codepoint":"F01AB","aliases":["local-drink","glass-water","drink-water","cup-liquid","glass-liquid"],"tags":["Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"112A3BDB-8748-4118-8315-326E140C101B","name":"cupboard","codepoint":"F0F46","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"13FBEF67-6AB8-471D-BC66-DE521D91D0FC","name":"cupboard-outline","codepoint":"F0F47","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"CF09105E-AB0E-4393-ADCC-4E6DFC513C9C","name":"cupcake","codepoint":"F095A","aliases":[],"tags":["Food \/ Drink"],"author":"Nick","version":"2.4.85"},{"id":"75F948EB-5A9C-4F7A-9841-2B93AC222605","name":"curling","codepoint":"F0863","aliases":[],"tags":["Sport"],"author":"Nick","version":"2.1.99"},{"id":"FB0C738C-21DE-4643-9B5D-690CE7AAEAEE","name":"currency-bdt","codepoint":"F0864","aliases":["taka","bangladeshi-taka"],"tags":["Banking","Currency"],"author":"Michael Richins","version":"2.1.99"},{"id":"20E50505-DD23-4A07-AAE7-024BE3774018","name":"currency-brl","codepoint":"F0B85","aliases":["brazilian-real"],"tags":["Banking","Currency"],"author":"Austin Andrews","version":"3.0.39"},{"id":"CCAF9A48-2989-47C7-B4A5-1CF424A339CC","name":"currency-btc","codepoint":"F01AC","aliases":["bitcoin"],"tags":["Currency","Brand \/ Logo","Banking"],"author":"Contributors","version":"1.5.54"},{"id":"0F5809A3-18DD-4B42-9A7E-B35B65EF3751","name":"currency-cny","codepoint":"F07BA","aliases":["yuan","renminbi"],"tags":["Currency","Banking"],"author":"Haley Halcyon","version":"2.0.46"},{"id":"222B8F14-2217-4FC1-8940-AC1CF8AB150B","name":"currency-eth","codepoint":"F07BB","aliases":["ethereum","xi"],"tags":["Currency","Brand \/ Logo","Banking"],"author":"Peter Noble","version":"2.0.46"},{"id":"94C667B3-E2EB-428D-B422-751C234CCF44","name":"currency-eur","codepoint":"F01AD","aliases":["euro","euro-symbol"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"010841EE-1569-425A-9849-9FC6E4D05C3B","name":"currency-eur-off","codepoint":"F1315","aliases":[],"tags":["Currency"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"F9BD830F-EBB6-45A4-A576-0DEC27084A95","name":"currency-gbp","codepoint":"F01AE","aliases":["pound","sterling"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A55AD931-CE89-49C0-9F1C-F699C422843C","name":"currency-ils","codepoint":"F0C61","aliases":[],"tags":["Banking","Currency"],"author":"Contributors","version":"3.2.89"},{"id":"AB8EAA72-9A34-4F87-937A-9A8FDEFA1FEF","name":"currency-inr","codepoint":"F01AF","aliases":["rupee"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"639A8D4C-086C-4038-A569-F9387E851262","name":"currency-jpy","codepoint":"F07BC","aliases":["yen"],"tags":["Currency","Banking"],"author":"Haley Halcyon","version":"2.0.46"},{"id":"72750D9E-229F-4D77-B1CB-9C2C0FD12335","name":"currency-krw","codepoint":"F07BD","aliases":["won"],"tags":["Currency","Banking"],"author":"Haley Halcyon","version":"2.0.46"},{"id":"FDA284E5-BF4A-47DC-B68F-255E07DB89CF","name":"currency-kzt","codepoint":"F0865","aliases":["kazakhstani-tenge"],"tags":["Banking","Currency"],"author":"Augustin Ursu","version":"2.1.99"},{"id":"D0B20B31-ADBD-4F8A-9B72-52CC2FE4C3F4","name":"currency-mnt","codepoint":"F1512","aliases":["currency-mongolian-tugrug"],"tags":["Currency"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"2F091499-4472-423E-A0C5-8C96CDDE1ABF","name":"currency-ngn","codepoint":"F01B0","aliases":["naira"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"734CB783-C788-4F5E-BB90-BFBF4E3C22DC","name":"currency-php","codepoint":"F09E6","aliases":["philippine-peso"],"tags":["Banking","Currency"],"author":"Michael Richins","version":"2.5.94"},{"id":"55D42287-2705-451B-B87A-91C23AF3A945","name":"currency-rial","codepoint":"F0E9C","aliases":["currency-riyal","currency-irr","currency-omr","currency-yer","currency-sar"],"tags":["Currency","Banking"],"author":"Haley Halcyon","version":"3.7.94"},{"id":"57057EA1-1BA7-49F3-A8C7-51AF633DED68","name":"currency-rub","codepoint":"F01B1","aliases":["ruble"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"17CFE8D4-18D7-4414-B8EE-244D5A8FF791","name":"currency-sign","codepoint":"F07BE","aliases":["currency-scarab"],"tags":["Currency","Banking"],"author":"Michael Richins","version":"2.0.46"},{"id":"94DAFCB6-FA70-4DAE-B3DF-A107031F81E8","name":"currency-try","codepoint":"F01B2","aliases":["lira"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54"},{"id":"E0103EBC-20BF-48EA-BC8F-BEF04BF2A581","name":"currency-twd","codepoint":"F07BF","aliases":["new-taiwan-dollar"],"tags":["Currency","Banking"],"author":"Haley Halcyon","version":"2.0.46"},{"id":"3FA4946C-029B-42D3-AA31-3D607FB4A2F1","name":"currency-usd","codepoint":"F01C1","aliases":["attach-money","dollar"],"tags":["Currency","Banking"],"author":"Google","version":"1.5.54"},{"id":"9DA90BB6-B525-47A8-879F-66EC572FE31B","name":"currency-usd-circle","codepoint":"F116B","aliases":["coin"],"tags":["Banking","Currency"],"author":"Michael Richins","version":"4.4.95","deprecated":true},{"id":"42F0733E-F36F-491B-ADC9-AC8ABAF2C0B7","name":"currency-usd-circle-outline","codepoint":"F0178","aliases":["coin-outline"],"tags":["Currency","Banking"],"author":"Austin Andrews","version":"1.5.54","deprecated":true},{"id":"5E9D35E4-9487-4A9B-9D4B-E1BBCA52AE0C","name":"currency-usd-off","codepoint":"F067A","aliases":["money-off","dollar-off"],"tags":["Currency","Banking"],"author":"Google","version":"1.7.12"},{"id":"BB0EDAF7-B538-4DAA-8406-36470F472EA1","name":"current-ac","codepoint":"F1480","aliases":["alternating-current"],"tags":[],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"2A23AD1A-C4F1-47B1-B482-05836097CE51","name":"current-dc","codepoint":"F095C","aliases":["direct-current"],"tags":["Battery"],"author":"Nick","version":"2.4.85"},{"id":"2B463003-089D-47DE-97F7-434F16A4735B","name":"cursor-default","codepoint":"F01C0","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"C5C0F16E-6D8B-49DB-8374-9B26C9E76B0D","name":"cursor-default-click","codepoint":"F0CFD","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"CE0F1A1D-5BE5-48A7-9DF2-3021489E4937","name":"cursor-default-click-outline","codepoint":"F0CFE","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"450BD54E-A467-41D8-B428-50779BB451C4","name":"cursor-default-gesture","codepoint":"F1127","aliases":[],"tags":[],"author":"Contributors","version":"4.3.95"},{"id":"ABCE3774-DAC9-494D-99D3-1054160ECC7E","name":"cursor-default-gesture-outline","codepoint":"F1128","aliases":[],"tags":[],"author":"Contributors","version":"4.3.95"},{"id":"E6A56AAF-22C5-4DAE-9E97-184501755DF5","name":"cursor-default-outline","codepoint":"F01BF","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"EDAD5377-8923-4D6C-AC12-CBDC6C78DC7F","name":"cursor-move","codepoint":"F01BE","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B5465B23-729A-405E-9155-486A36D8135F","name":"cursor-pointer","codepoint":"F01BD","aliases":["cursor-hand"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"76C56C15-C2A3-4042-95C7-F143A3B58765","name":"cursor-text","codepoint":"F05E7","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"82D8E45B-5E04-4094-818B-DE18775F9A91","name":"dance-ballroom","codepoint":"F15FB","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"45E2144E-5240-4557-B9A9-45DD7B514738","name":"dance-pole","codepoint":"F1578","aliases":["kho-kho"],"tags":["Sport"],"author":"Haley Halcyon","version":"5.5.55"},{"id":"7727E2AF-BD33-4C14-9FF4-6FA4BBA8594C","name":"data-matrix","codepoint":"F153C","aliases":[],"tags":[],"author":"David Kon\u00ed\u0159","version":"5.4.55"},{"id":"7D6DC2D9-EDDF-4C82-AA10-CEC85C4DF7BF","name":"data-matrix-edit","codepoint":"F153D","aliases":[],"tags":["Edit \/ Modify"],"author":"David Kon\u00ed\u0159","version":"5.4.55"},{"id":"EA63161B-B010-4BEC-A5B0-774C2007C0D0","name":"data-matrix-minus","codepoint":"F153E","aliases":[],"tags":[],"author":"David Kon\u00ed\u0159","version":"5.4.55"},{"id":"0B183EEE-8B38-4B8E-A049-96AC93BCD1EA","name":"data-matrix-plus","codepoint":"F153F","aliases":[],"tags":[],"author":"David Kon\u00ed\u0159","version":"5.4.55"},{"id":"0809BEAA-8884-4116-B319-9AD6C11A86BE","name":"data-matrix-remove","codepoint":"F1540","aliases":[],"tags":[],"author":"David Kon\u00ed\u0159","version":"5.4.55"},{"id":"8B555E52-AD00-4ECF-8533-02D9AC92E7F5","name":"data-matrix-scan","codepoint":"F1541","aliases":[],"tags":[],"author":"David Kon\u00ed\u0159","version":"5.4.55"},{"id":"C8FC48A7-AE19-4BD8-B57E-14B76D93937B","name":"database","codepoint":"F01BC","aliases":["storage"],"tags":["Geographic Information System","Database"],"author":"Simran","version":"1.5.54"},{"id":"7B3AB47E-C134-4AE9-82A2-DD0F95D6EF3F","name":"database-alert","codepoint":"F163A","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"27B8C966-DE22-4B45-99A6-5CF769BECD07","name":"database-alert-outline","codepoint":"F1624","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"82BC4255-42E2-4B69-ADE4-A3519DE84E22","name":"database-arrow-down","codepoint":"F163B","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"8A490A09-A803-4333-BB10-5758643AD4F4","name":"database-arrow-down-outline","codepoint":"F1625","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"FB778AE2-E52D-4C2A-BEF7-C48A805F8A57","name":"database-arrow-left","codepoint":"F163C","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"A51D37EB-0B92-4F4A-8402-E0C33825D05B","name":"database-arrow-left-outline","codepoint":"F1626","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"AE5DDB91-CE2C-4EE3-8247-E4818F488EE0","name":"database-arrow-right","codepoint":"F163D","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"097A9369-2179-49DB-891C-5A61C88A985C","name":"database-arrow-right-outline","codepoint":"F1627","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"EC1BF4CB-2B6B-4B69-96E6-599E77D02885","name":"database-arrow-up","codepoint":"F163E","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"2E041168-F122-45CC-84AD-2A05428C211A","name":"database-arrow-up-outline","codepoint":"F1628","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"C241F52F-EA70-4784-9455-AA7D05663C90","name":"database-check","codepoint":"F0AA9","aliases":["database-tick"],"tags":["Geographic Information System","Database"],"author":"Andrew Nenakhov","version":"2.7.94"},{"id":"1B7F6C62-E464-42F6-B7C0-CDD637A520F6","name":"database-check-outline","codepoint":"F1629","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"1401D168-E1ED-403A-9154-F89133195BF9","name":"database-clock","codepoint":"F163F","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"093C4D34-DC23-4FE7-9AD0-05FCFFBB41A6","name":"database-clock-outline","codepoint":"F162A","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"2D941DD1-7B07-4E4B-B164-42AF6F751D34","name":"database-cog","codepoint":"F164B","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"A15AD70B-D874-46B1-BD26-2A5627DBF201","name":"database-cog-outline","codepoint":"F164C","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"A9C5BB4C-C89F-4ADE-80C2-FB39A942DE6A","name":"database-edit","codepoint":"F0B86","aliases":[],"tags":["Edit \/ Modify","Geographic Information System","Database"],"author":"Michael Richins","version":"3.0.39"},{"id":"6428E607-E036-481B-AF42-B09894C68E19","name":"database-edit-outline","codepoint":"F162B","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"6E50F0F8-1116-4090-9468-54B2CE8FBB19","name":"database-export","codepoint":"F095E","aliases":[],"tags":["Geographic Information System","Database"],"author":"Michael Richins","version":"2.4.85"},{"id":"E620893F-9644-4E75-8904-C81B85B6D58D","name":"database-export-outline","codepoint":"F162C","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"733A4C8A-FAA5-42BE-882E-98EC734E8493","name":"database-import","codepoint":"F095D","aliases":[],"tags":["Geographic Information System","Database"],"author":"Michael Richins","version":"2.4.85"},{"id":"4D0E6B34-7EAB-4EC4-9782-F2318139A3E2","name":"database-import-outline","codepoint":"F162D","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"3A6B098D-F7AD-4D2C-A039-201319B5FDD7","name":"database-lock","codepoint":"F0AAA","aliases":[],"tags":["Lock","Geographic Information System","Database"],"author":"Andrew Nenakhov","version":"2.7.94"},{"id":"A03B26F4-54BB-4E3D-B4E7-EAFE3351A6BA","name":"database-lock-outline","codepoint":"F162E","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"91AD02DB-7EBD-4B39-AACB-8037B50728AC","name":"database-marker","codepoint":"F12F6","aliases":[],"tags":["Geographic Information System","Database"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"163262B4-672A-4194-B002-3F414DF6C7A5","name":"database-marker-outline","codepoint":"F162F","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"31CE0431-ABF2-4650-8439-515C0E9012CD","name":"database-minus","codepoint":"F01BB","aliases":[],"tags":["Geographic Information System","Database"],"author":"Simran","version":"1.5.54"},{"id":"96D5DD75-E7C1-444F-AD36-AB601BB9C504","name":"database-minus-outline","codepoint":"F1630","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"5E0B7DCE-B912-4789-A0F9-86DBA5D27DBE","name":"database-off","codepoint":"F1640","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"4DD86D39-4EC5-44BD-BA05-AA763999E390","name":"database-off-outline","codepoint":"F1631","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"76AAFFAC-C2C7-4375-A175-765848BF08AA","name":"database-outline","codepoint":"F1632","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"940D2514-B309-4CE0-A2E4-D02121415CA3","name":"database-plus","codepoint":"F01BA","aliases":["database-add"],"tags":["Geographic Information System","Database"],"author":"Simran","version":"1.5.54"},{"id":"2250D162-41A7-4852-B3E2-555180A5A57C","name":"database-plus-outline","codepoint":"F1633","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"C43C676A-F2BE-489A-8613-BE6EF651F0AC","name":"database-refresh","codepoint":"F05C2","aliases":[],"tags":["Database"],"author":"Contributors","version":"1.5.54"},{"id":"03B12B1B-7AF3-42C7-89CA-482DC21F12CE","name":"database-refresh-outline","codepoint":"F1634","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"20B59D03-2EF5-4C5D-BB00-2CC611297AC0","name":"database-remove","codepoint":"F0D00","aliases":[],"tags":["Geographic Information System","Database"],"author":"Michael Richins","version":"3.3.92"},{"id":"32FBEA36-9F09-4D8D-A355-2DD6FB2AA837","name":"database-remove-outline","codepoint":"F1635","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"58E36A40-053B-42EB-8879-9CB0948B58D4","name":"database-search","codepoint":"F0866","aliases":["sql-query"],"tags":["Geographic Information System","Database"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"EFAB71E6-7F67-40B9-B388-0B4AFFC6B799","name":"database-search-outline","codepoint":"F1636","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"CBD96BE0-807C-4102-AC0B-AEFFE4D322F7","name":"database-settings","codepoint":"F0D01","aliases":[],"tags":["Settings","Geographic Information System","Database"],"author":"Michael Richins","version":"3.3.92"},{"id":"9AB5AF13-E028-49FA-B81E-EFFF8A8EB144","name":"database-settings-outline","codepoint":"F1637","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"5E954303-C1CF-406B-A9B5-A72E5C25E499","name":"database-sync","codepoint":"F0CFF","aliases":[],"tags":["Geographic Information System","Database"],"author":"Michael Richins","version":"3.3.92"},{"id":"9E1F0B0A-332A-473D-8CA2-DD30E03E76B9","name":"database-sync-outline","codepoint":"F1638","aliases":[],"tags":["Database"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"309A4ABA-E450-437D-8AD1-EE6A850D421B","name":"death-star","codepoint":"F08D8","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"2.3.50"},{"id":"51D35A62-F308-48B6-B471-D58CFE4CD6BC","name":"death-star-variant","codepoint":"F08D9","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"2.3.50"},{"id":"BC446853-45C9-4374-8980-579BCD93355A","name":"deathly-hallows","codepoint":"F0B87","aliases":["harry-potter"],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"250883A1-65B8-4092-9B92-C9BD810ADB5A","name":"debian","codepoint":"F08DA","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.3.50"},{"id":"316468B3-C3F6-4A7B-B7B2-061E5C35FFE9","name":"debug-step-into","codepoint":"F01B9","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"08B9B3C7-BB6B-4110-ACEC-3BB947FFCFBA","name":"debug-step-out","codepoint":"F01B8","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8242E7C8-1400-476D-AC27-DCA7B6292C70","name":"debug-step-over","codepoint":"F01B7","aliases":["skip","jump"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"DA734DBD-1239-4E30-B688-ADF6A9D222D0","name":"decagram","codepoint":"F076C","aliases":["starburst"],"tags":["Shape"],"author":"Austin Andrews","version":"1.9.32"},{"id":"5F4B9A38-F090-4FA3-A138-1F758A9D446E","name":"decagram-outline","codepoint":"F076D","aliases":["starburst-outline"],"tags":["Shape"],"author":"Austin Andrews","version":"1.9.32"},{"id":"4A055D0D-18CA-45D9-96E1-B25448138888","name":"decimal","codepoint":"F10A1","aliases":[],"tags":["Math"],"author":"Michael Richins","version":"4.2.95"},{"id":"A8C5A79A-EA59-4AA8-B432-98F66AFDAFD3","name":"decimal-comma","codepoint":"F10A2","aliases":[],"tags":["Math"],"author":"Michael Richins","version":"4.2.95"},{"id":"E9237D99-5BD3-434A-B574-97C60B544EE1","name":"decimal-comma-decrease","codepoint":"F10A3","aliases":[],"tags":["Math"],"author":"Michael Richins","version":"4.2.95"},{"id":"3B4E5DF0-02B3-469D-9C6E-754683655184","name":"decimal-comma-increase","codepoint":"F10A4","aliases":[],"tags":["Math"],"author":"Michael Richins","version":"4.2.95"},{"id":"3A6FCF00-DE3C-4CD7-BF06-1D26E37E0C47","name":"decimal-decrease","codepoint":"F01B6","aliases":[],"tags":["Math"],"author":"Simran","version":"1.5.54"},{"id":"E99CB4D3-330D-493C-9C6B-FD43B27522FD","name":"decimal-increase","codepoint":"F01B5","aliases":[],"tags":["Math"],"author":"Simran","version":"1.5.54"},{"id":"71CD492D-A1E8-4A7A-961A-51DA30952BAD","name":"delete","codepoint":"F01B4","aliases":["trash","bin","rubbish","garbage","rubbish-bin","trash-can","garbage-can"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"2FF4634B-095D-4827-9735-E345A46FC488","name":"delete-alert","codepoint":"F10A5","aliases":[],"tags":["Alert \/ Error"],"author":"idevo89","version":"4.2.95"},{"id":"CFE12054-7E04-4144-B0CA-0DA9FE494E82","name":"delete-alert-outline","codepoint":"F10A6","aliases":[],"tags":["Alert \/ Error"],"author":"idevo89","version":"4.2.95"},{"id":"1158F80B-E934-4E74-A4C6-7750BDCC409E","name":"delete-circle","codepoint":"F0683","aliases":["trash-circle","bin-circle","garbage-can-circle","garbage-circle","rubbish-bin-circle","rubbish-circle","trash-can-circle"],"tags":[],"author":"Austin Andrews","version":"1.7.12"},{"id":"854068FB-F9DA-40B4-A427-F2317075CD95","name":"delete-circle-outline","codepoint":"F0B88","aliases":["bin-circle-outline","garbage-can-circle-outline","garbage-circle-outline","rubbish-bin-circle-outline","rubbish-circle-outline","trash-can-circle-outline","trash-circle-outline"],"tags":[],"author":"TheChilliPL","version":"3.0.39"},{"id":"3B615510-4D78-4743-9FB0-A3D45F267B04","name":"delete-clock","codepoint":"F1556","aliases":[],"tags":["Date \/ Time"],"author":"CoreyVidal","version":"5.5.55"},{"id":"7544FA9D-AFFB-4038-8D9F-FEE3EB918342","name":"delete-clock-outline","codepoint":"F1557","aliases":[],"tags":["Date \/ Time"],"author":"CoreyVidal","version":"5.5.55"},{"id":"E39FB607-9058-4C00-840C-AF666F372071","name":"delete-empty","codepoint":"F06CC","aliases":["trash-empty","bin-empty","rubbish-empty","rubbish-bin-empty","trash-can-empty","garbage-empty","garbage-can-empty"],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"69108916-6CE9-456A-A1BE-9113F49B425E","name":"delete-empty-outline","codepoint":"F0E9D","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.7.94"},{"id":"52AFD546-8C5D-4E77-8D83-D4D058A742FE","name":"delete-forever","codepoint":"F05E8","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"103DF12F-6279-4967-8BF8-F72ED139E8E7","name":"delete-forever-outline","codepoint":"F0B89","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"C0E55306-EBD8-46D9-BF50-7285DC72D4B7","name":"delete-off","codepoint":"F10A7","aliases":[],"tags":[],"author":"idevo89","version":"4.2.95"},{"id":"4D2C0D3A-46A6-42B9-974E-F1B677C61D21","name":"delete-off-outline","codepoint":"F10A8","aliases":[],"tags":[],"author":"idevo89","version":"4.2.95"},{"id":"59ADF7EF-9F3E-4957-A789-95788D13B9E4","name":"delete-outline","codepoint":"F09E7","aliases":["garbage-outline","bin-outline","rubbish-outline","garbage-can-outline","rubbish-bin-outline","trash-outline","trash-can-outline"],"tags":[],"author":"Google","version":"2.5.94"},{"id":"7837B9B7-2A6F-42E3-894D-C40D0080FB7B","name":"delete-restore","codepoint":"F0819","aliases":["trash-restore","bin-restore","restore-from-trash"],"tags":[],"author":"Google","version":"2.1.19"},{"id":"3B3D514C-AFC3-4D04-91EA-E18F03BB494A","name":"delete-sweep","codepoint":"F05E9","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"18C79874-01B2-4A65-AD4E-B8600C3F3ADD","name":"delete-sweep-outline","codepoint":"F0C62","aliases":[],"tags":[],"author":"Google","version":"3.2.89"},{"id":"DC3862AC-6945-4104-9F15-50BD46D13705","name":"delete-variant","codepoint":"F01B3","aliases":["trash-variant","bin-variant","cup-ice","drink-ice"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D4B29470-8EE3-4ED8-BB01-6C942CE7E748","name":"delta","codepoint":"F01C2","aliases":["change-history"],"tags":["Math","Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"35E2D33D-B4A8-4E12-B844-8EC1172F15A9","name":"desk","codepoint":"F1239","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"80459D13-2662-4F47-AB31-F6A2B84C8DEB","name":"desk-lamp","codepoint":"F095F","aliases":[],"tags":["Home Automation"],"author":"Contributors","version":"2.4.85"},{"id":"C05777DC-F874-4231-B9EB-5675C808F7BB","name":"deskphone","codepoint":"F01C3","aliases":[],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Chris Litherland","version":"1.5.54"},{"id":"40B89929-0709-461F-8C7A-ED94CDDCC4AC","name":"desktop-classic","codepoint":"F07C0","aliases":["computer-classic"],"tags":["Device \/ Tech","Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"4B4C339D-D581-44A3-95DE-4254CC42AC8D","name":"desktop-mac","codepoint":"F01C4","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"A3CC4F14-35C0-421B-A818-9B8E4E852522","name":"desktop-mac-dashboard","codepoint":"F09E8","aliases":[],"tags":["Device \/ Tech"],"author":"Michael Richins","version":"2.5.94"},{"id":"362BCE24-8F91-491A-8EE8-BD08C296511A","name":"desktop-tower","codepoint":"F01C5","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Chris Litherland","version":"1.5.54"},{"id":"D7BED84E-B592-46F0-8A5B-DD8677088837","name":"desktop-tower-monitor","codepoint":"F0AAB","aliases":[],"tags":["Device \/ Tech"],"author":"SarinManS","version":"2.7.94"},{"id":"21A2819F-3B97-49D0-A588-30CF7B8915F5","name":"details","codepoint":"F01C6","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D3E5B7D2-2301-4D35-A95E-1C1B0A6C9224","name":"dev-to","codepoint":"F0D6E","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"3.4.93"},{"id":"7D1C43A0-CDE0-416B-A1A9-1CD07F930284","name":"developer-board","codepoint":"F0697","aliases":[],"tags":[],"author":"Google","version":"1.7.12"},{"id":"ECD72042-9BA7-4C24-A740-7F538B443302","name":"deviantart","codepoint":"F01C7","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"D8990892-9C02-46AC-9A91-3D4D9A2EFF19","name":"devices","codepoint":"F0FB0","aliases":["monitor","watch","smartwatch","smartphone","cellphone","television"],"tags":["Device \/ Tech"],"author":"Google","version":"4.0.96"},{"id":"B0973EC9-B27B-4666-8E9E-C766A601BB0A","name":"diabetes","codepoint":"F1126","aliases":["hand-blood"],"tags":["Medical \/ Hospital"],"author":"Michael Richins","version":"4.3.95"},{"id":"B732FAD7-93A7-478E-810F-835069DE6EDB","name":"dialpad","codepoint":"F061C","aliases":["keypad"],"tags":[],"author":"Google","version":"1.6.50"},{"id":"64CBC510-072A-477D-99DD-F8114E7E312E","name":"diameter","codepoint":"F0C63","aliases":["circle-diameter","sphere-diameter"],"tags":["Math"],"author":"Michael Richins","version":"3.2.89"},{"id":"ABE01F05-E04E-4C5F-8F70-F8A9DB484E89","name":"diameter-outline","codepoint":"F0C64","aliases":["circle-diameter-outline","sphere-diameter-outline"],"tags":["Math"],"author":"Michael Richins","version":"3.2.89"},{"id":"B1744A41-3289-4535-81F8-E23617C701FE","name":"diameter-variant","codepoint":"F0C65","aliases":["circle-diameter-variant","sphere-diameter-variant"],"tags":["Math"],"author":"Michael Richins","version":"3.2.89"},{"id":"BC337E6C-8077-4D79-9596-6B9EDDA6DE0D","name":"diamond","codepoint":"F0B8A","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"4D922F91-E62D-42BB-86E4-BE8A96BC2B80","name":"diamond-outline","codepoint":"F0B8B","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"7AEA1B64-9B6D-4D55-91F8-05BA1BF3BF89","name":"diamond-stone","codepoint":"F01C8","aliases":["jewel"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"F8E5E9B6-9953-46F8-84DC-CFBB11DEFFB7","name":"dice-1","codepoint":"F01CA","aliases":["die-1","dice-one"],"tags":["Gaming \/ RPG"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"430F434F-E5F5-4D54-97B0-F6D1CE844365","name":"dice-1-outline","codepoint":"F114A","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"07927207-23B1-4A93-BB8A-E6B5F41B919A","name":"dice-2","codepoint":"F01CB","aliases":["die-2","dice-two"],"tags":["Gaming \/ RPG"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"BA4A2CA9-22E9-450E-B8CA-99A8ED5E0A1B","name":"dice-2-outline","codepoint":"F114B","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"2948109E-F9DA-4306-8247-665CC05BDB21","name":"dice-3","codepoint":"F01CC","aliases":["die-3","dice-three"],"tags":["Gaming \/ RPG"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"D4689BAD-0911-4832-9A8E-AD334D834773","name":"dice-3-outline","codepoint":"F114C","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"F7FA1307-CC98-4B93-B42A-533F1F6E851C","name":"dice-4","codepoint":"F01CD","aliases":["die-4","dice-four"],"tags":["Gaming \/ RPG"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"A24BDBB1-DF5E-4022-8AF0-3D4989B0F2EE","name":"dice-4-outline","codepoint":"F114D","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"9B9F7FE0-5AA9-4B5F-B865-D7F21C1382AF","name":"dice-5","codepoint":"F01CE","aliases":["die-5","dice-five"],"tags":["Gaming \/ RPG"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"07A26D74-6460-4AD8-9470-E4E0A39E9DAB","name":"dice-5-outline","codepoint":"F114E","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"015F173B-CA59-4125-8F19-925ED108BE07","name":"dice-6","codepoint":"F01CF","aliases":["die-6","dice-six"],"tags":["Gaming \/ RPG"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"359B124F-4377-4580-9C7C-494539D087DB","name":"dice-6-outline","codepoint":"F114F","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"F80FBAEF-6EE5-4F02-AAA8-7E3FBA618708","name":"dice-d10","codepoint":"F1153","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"47BB1E5C-0CCD-4A50-B1EF-2437411217C0","name":"dice-d10-outline","codepoint":"F076F","aliases":["die-d10"],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.9.32"},{"id":"87285D65-197B-46D6-BAD6-F9EE53DD5F28","name":"dice-d12","codepoint":"F1154","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"E27CCA75-CE3E-4C7D-81AA-D3A1391A819E","name":"dice-d12-outline","codepoint":"F0867","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.99"},{"id":"948F2639-1E9E-478F-BCC9-4EC7147F8616","name":"dice-d20","codepoint":"F1155","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"926FAA94-AB58-44AA-916C-66AF56A5BCCF","name":"dice-d20-outline","codepoint":"F05EA","aliases":["die-d20"],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"876805AB-7EC6-4CD8-A9D4-17213004A83A","name":"dice-d4","codepoint":"F1150","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"DCC141FA-CA87-48E1-969D-BB010C973DD5","name":"dice-d4-outline","codepoint":"F05EB","aliases":["die-d4"],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A62117B1-58C5-4A44-B6B1-C6E1DCEB7E00","name":"dice-d6","codepoint":"F1151","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"A0F00FDF-6648-475B-819B-29E4C0769FFA","name":"dice-d6-outline","codepoint":"F05ED","aliases":["die-d6"],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5EA075B9-0455-42DA-AB57-47BAFADF0160","name":"dice-d8","codepoint":"F1152","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"64967BE6-CAAF-4F28-BF55-C5451D4E8B94","name":"dice-d8-outline","codepoint":"F05EC","aliases":["die-d8"],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"8C9D5084-1B34-4AB9-BE23-E44B03AE85E5","name":"dice-multiple","codepoint":"F076E","aliases":["die-multiple"],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"1.9.32"},{"id":"4F078165-F841-4013-B24C-4FA639C7F708","name":"dice-multiple-outline","codepoint":"F1156","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"58BA7D31-6B34-46E6-B325-080C95B32A6F","name":"digital-ocean","codepoint":"F1237","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"2356EE38-11BE-44B1-BAD9-D74ECE86F8E7","name":"dip-switch","codepoint":"F07C1","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"4C84603B-BEB6-4282-B6CE-D9AD3C098627","name":"directions","codepoint":"F01D0","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8F53DAC3-E72D-473E-ABD1-AC1849EB660A","name":"directions-fork","codepoint":"F0641","aliases":[],"tags":[],"author":"Google","version":"1.6.50"},{"id":"95CEA0DD-5123-4FFA-B906-E6C55766030D","name":"disc","codepoint":"F05EE","aliases":[],"tags":["Music"],"author":"Simran","version":"1.5.54"},{"id":"63A41E0F-CCDB-42F8-848B-F64AA94F9BDF","name":"disc-alert","codepoint":"F01D1","aliases":["disc-full","disc-warning"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"DA84CDD7-3881-4DE0-8CEB-51F1BD086A3A","name":"disc-player","codepoint":"F0960","aliases":[],"tags":["Home Automation","Device \/ Tech"],"author":"Austin Andrews","version":"2.4.85"},{"id":"2C23A3F9-54C7-4C7F-8C2F-182A4F75F894","name":"discord","codepoint":"F066F","aliases":[],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.6.50"},{"id":"41CB517E-41F5-47D4-A8A2-E9512CB065DD","name":"dishwasher","codepoint":"F0AAC","aliases":[],"tags":["Home Automation"],"author":"Google","version":"2.7.94"},{"id":"A72D6C1A-A953-4F9B-BD38-0E0ACF1A6C58","name":"dishwasher-alert","codepoint":"F11B8","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"5BB3E0C6-278F-4008-8327-0124D7A209A6","name":"dishwasher-off","codepoint":"F11B9","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"28670432-3B76-43FC-B879-558B338F1E1F","name":"disqus","codepoint":"F01D2","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"BA55B495-6775-4070-9ADC-FF56EB8E067D","name":"distribute-horizontal-center","codepoint":"F11C9","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"22C7EA3A-483D-4BFD-A115-42F86F164135","name":"distribute-horizontal-left","codepoint":"F11C8","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"771135B5-F856-4AAE-9FD1-8F728964DE2F","name":"distribute-horizontal-right","codepoint":"F11CA","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"DDF54E4F-65E8-407A-961F-5B02A3A0DC37","name":"distribute-vertical-bottom","codepoint":"F11CB","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"35AAECBA-CF24-4DCC-99F0-20D9CB21B58B","name":"distribute-vertical-center","codepoint":"F11CC","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"F1C73D50-8C76-4269-8CBB-D232C55BD100","name":"distribute-vertical-top","codepoint":"F11CD","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"B57B062B-66A2-4F90-85A3-97446E1934D2","name":"diving-flippers","codepoint":"F0DBF","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"3.5.94"},{"id":"4732B7F8-F8EF-4E5A-A889-BA5770B1B4FF","name":"diving-helmet","codepoint":"F0DC0","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"6C2E4BEE-6D01-4B09-A501-CE976EE20740","name":"diving-scuba","codepoint":"F0DC1","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"3.5.94"},{"id":"7B600593-08CB-42D0-B106-0EDF12132BFC","name":"diving-scuba-flag","codepoint":"F0DC2","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"64055E84-7F77-4020-A105-313AAD36353E","name":"diving-scuba-tank","codepoint":"F0DC3","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"868AEE51-0552-43D0-97FA-9F783BB2A67C","name":"diving-scuba-tank-multiple","codepoint":"F0DC4","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"227F84AF-3BC0-4C9D-BADB-DC8B1A110ED8","name":"diving-snorkel","codepoint":"F0DC5","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"3.5.94"},{"id":"FB313489-5EA3-4F07-ABA4-F84995D7DD13","name":"division","codepoint":"F01D4","aliases":["obelus"],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1A0BABA0-5F5E-45ED-A4BB-DCBD569F6E43","name":"division-box","codepoint":"F01D5","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"15C7622F-855B-4FFA-BA1A-ED0ED470078B","name":"dlna","codepoint":"F0A41","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.6.95"},{"id":"2C726E7E-53C8-410C-82F4-FE5DE9EF4BC1","name":"dna","codepoint":"F0684","aliases":["helix"],"tags":["Science"],"author":"Haley Halcyon","version":"1.7.12"},{"id":"D4A20191-F5B8-4323-A0A8-F4C15A86A83B","name":"dns","codepoint":"F01D6","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D81BA495-F83D-4CFF-A9A5-B398D7E53DC7","name":"dns-outline","codepoint":"F0B8C","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"F33DB278-2B2B-4731-9FDD-6D053EC2CBAB","name":"do-not-disturb","codepoint":"F0698","aliases":["no-entry"],"tags":[],"author":"Google","version":"1.7.12","deprecated":true},{"id":"092B5CD3-BB99-492C-9784-4BE71B0C7F5B","name":"do-not-disturb-off","codepoint":"F0699","aliases":[],"tags":[],"author":"Google","version":"1.7.12","deprecated":true},{"id":"E6B5C99C-7C0F-4F61-AEF9-7FDF6851D426","name":"dock-bottom","codepoint":"F10A9","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"59BABD0B-E745-4389-B318-4E166F2ED0C0","name":"dock-left","codepoint":"F10AA","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"3AF2E71C-A865-4512-8B41-3803BFA84C48","name":"dock-right","codepoint":"F10AB","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"4014E87F-B3F7-465B-B84D-ED2408AA95EE","name":"dock-top","codepoint":"F1513","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"6EF77419-3085-4805-804C-096C6D8A4450","name":"dock-window","codepoint":"F10AC","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"8EE88381-B350-4C63-B26D-F340FE54D668","name":"docker","codepoint":"F0868","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"3772A377-C71A-429B-A4A6-3979DA3BC588","name":"doctor","codepoint":"F0A42","aliases":[],"tags":["Medical \/ Hospital"],"author":"Augustin Ursu","version":"2.6.95"},{"id":"8D6EB954-B4C9-44D5-9E70-C4E186C35957","name":"dog","codepoint":"F0A43","aliases":[],"tags":["Animal"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"C0CF99F2-5D8E-4478-9602-9866AF83B94B","name":"dog-service","codepoint":"F0AAD","aliases":["guide-dog"],"tags":["Animal"],"author":"Michael Richins","version":"2.7.94"},{"id":"4A3EEFF6-77EF-498F-9450-7AE3D3EC7BC6","name":"dog-side","codepoint":"F0A44","aliases":[],"tags":["Animal"],"author":"Nick","version":"2.6.95"},{"id":"74FE76CF-E5A5-42F3-97BD-0BCDF17DBFFF","name":"dog-side-off","codepoint":"F16EE","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"FE71CD75-B2E7-49A5-B00B-732BACB52F6F","name":"dolby","codepoint":"F06B3","aliases":[],"tags":["Audio","Brand \/ Logo","Home Automation"],"author":"Contributors","version":"1.7.22"},{"id":"6F2EAC1C-802A-48CF-A9E1-7EBFD4893BAF","name":"dolly","codepoint":"F0E9E","aliases":["hand-truck","trolley"],"tags":[],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"CA264BA4-62A9-4823-A172-22DD413A6CF5","name":"domain","codepoint":"F01D7","aliases":["building","company","business"],"tags":["Places"],"author":"Google","version":"1.5.54"},{"id":"77232563-20F2-4C73-B30E-5F83D237E7D7","name":"domain-off","codepoint":"F0D6F","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"C19B8872-80EF-439B-A7B8-5F043DC66991","name":"domain-plus","codepoint":"F10AD","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"BB1C669D-D6EA-47D7-B15C-10A236D214AA","name":"domain-remove","codepoint":"F10AE","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"E17E8B8F-361D-4467-97BE-71C3ABE9355A","name":"dome-light","codepoint":"F141E","aliases":[],"tags":[],"author":"Tim Grelka","version":"5.2.45"},{"id":"4621ACB1-6F3D-414D-8724-B276982DB087","name":"domino-mask","codepoint":"F1023","aliases":["robber-mask","zorro-mask"],"tags":[],"author":"Andrew Nenakhov","version":"4.1.95"},{"id":"7027E5FC-228D-4E32-B2BB-02287E94D132","name":"donkey","codepoint":"F07C2","aliases":[],"tags":["Animal"],"author":"Contributors","version":"2.0.46"},{"id":"858F8782-5001-4950-96F2-65032091A847","name":"door","codepoint":"F081A","aliases":[],"tags":["Home Automation"],"author":"Haley Halcyon","version":"2.1.19"},{"id":"DFE96305-5114-4F53-AB08-08F99F37C2FE","name":"door-closed","codepoint":"F081B","aliases":[],"tags":["Home Automation"],"author":"Haley Halcyon","version":"2.1.19"},{"id":"792A98B0-E031-43CF-AF8B-ACF21C97C4C2","name":"door-closed-lock","codepoint":"F10AF","aliases":[],"tags":["Home Automation","Lock"],"author":"Michael Richins","version":"4.2.95"},{"id":"A64D06DE-1EE4-400F-9E17-2B5D319475A3","name":"door-open","codepoint":"F081C","aliases":[],"tags":["Home Automation"],"author":"Haley Halcyon","version":"2.1.19"},{"id":"91D0BB43-E5D4-4F0B-89E7-B379A6F9A455","name":"doorbell","codepoint":"F12E6","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"63848BB0-8CBA-491A-9D3A-5964BAA67CC2","name":"doorbell-video","codepoint":"F0869","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"E05A9EE4-A599-4195-93F9-0E4024670E81","name":"dot-net","codepoint":"F0AAE","aliases":["microsoft-dot-net"],"tags":["Developer \/ Languages"],"author":"Contributors","version":"2.7.94"},{"id":"9BBDE78A-ADFF-4FFB-AC79-C7B1FDAB633E","name":"dots-grid","codepoint":"F15FC","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.6.55"},{"id":"92CE1CCF-7652-4292-831D-CFE1ADBB54B6","name":"dots-hexagon","codepoint":"F15FF","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.6.55"},{"id":"9156AFAA-25BB-4E97-9EC8-BB9BE9AF60B0","name":"dots-horizontal","codepoint":"F01D8","aliases":["more","ellipsis-horizontal","more-horiz","menu"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"2ED6A664-DAE9-427C-8810-496C331C9BE0","name":"dots-horizontal-circle","codepoint":"F07C3","aliases":["ellipsis-horizontal-circle","more-circle","menu"],"tags":[],"author":"Contributors","version":"2.0.46"},{"id":"378E8311-F963-41EC-9AFF-5B30EF975313","name":"dots-horizontal-circle-outline","codepoint":"F0B8D","aliases":["ellipsis-horizontal-circle-outline","more-circle-outline","menu"],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"57A090F9-EBDF-4A60-8B83-1D5E5A61B73E","name":"dots-square","codepoint":"F15FD","aliases":["perimeter"],"tags":[],"author":"Jeff Hilnbrand","version":"5.6.55"},{"id":"37FA940A-635C-48A5-988B-D1F4BBC0A7E0","name":"dots-triangle","codepoint":"F15FE","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.6.55"},{"id":"5D70B3D1-8407-42C9-A3C1-42EE68FF18F3","name":"dots-vertical","codepoint":"F01D9","aliases":["ellipsis-vertical","more-vert","menu"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"5D23E65D-271A-463B-972F-E8524E76E6D7","name":"dots-vertical-circle","codepoint":"F07C4","aliases":["ellipsis-vertical-circle","menu"],"tags":[],"author":"Contributors","version":"2.0.46"},{"id":"E2CD4D50-D64C-47B9-AF3B-C464D65CD4EB","name":"dots-vertical-circle-outline","codepoint":"F0B8E","aliases":["ellipsis-vertical-circle-outline","menu"],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"FF8D4F38-8A77-4FDD-8C6D-D17F6A44516D","name":"douban","codepoint":"F069A","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.7.12"},{"id":"704F7397-0E85-4213-8D76-FE156DF1795F","name":"download","codepoint":"F01DA","aliases":["file-download","get-app"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"49E1E432-8C28-43AA-818C-EB62ACF5EC06","name":"download-box","codepoint":"F1462","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.2.45"},{"id":"48A14899-8641-40E7-BF9D-06BD6AE9BB54","name":"download-box-outline","codepoint":"F1463","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.2.45"},{"id":"B4B33DFC-4361-478D-A3A3-3FD224B95C16","name":"download-circle","codepoint":"F1464","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.2.45"},{"id":"0F2CB73D-1357-4004-88DE-6E57549B8F1C","name":"download-circle-outline","codepoint":"F1465","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.2.45"},{"id":"F70D7D6A-B496-4182-A423-939E2CCF21AC","name":"download-lock","codepoint":"F1320","aliases":[],"tags":["Lock"],"author":"Michael Richins","version":"4.9.95"},{"id":"CDB71553-149F-452B-A0DC-2CD8EFA41150","name":"download-lock-outline","codepoint":"F1321","aliases":[],"tags":["Lock"],"author":"Michael Richins","version":"4.9.95"},{"id":"EEECC393-B78C-43DE-BDA4-F31DACA25F56","name":"download-multiple","codepoint":"F09E9","aliases":["downloads"],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"8DD93DC3-060D-4CB3-AB41-8A1A5243BFFD","name":"download-network","codepoint":"F06F4","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"EACBF539-FF17-4F63-8782-AB4146D9B072","name":"download-network-outline","codepoint":"F0C66","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"C582FB3E-A708-411C-91C8-FA660E313AAE","name":"download-off","codepoint":"F10B0","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"0FFB4F5B-34FB-4E1F-AA6B-96C5CD8F9632","name":"download-off-outline","codepoint":"F10B1","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"AB9770C4-6886-4A46-8F4E-B96CBCCCF839","name":"download-outline","codepoint":"F0B8F","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"2366C232-208F-4A03-9FC9-D9C8C52622CA","name":"drag","codepoint":"F01DB","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"544A0702-E7DC-4E1F-9A6E-8785AA3048D8","name":"drag-horizontal","codepoint":"F01DC","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"FA5B1F76-C0C4-4F08-B545-D28E78781F67","name":"drag-horizontal-variant","codepoint":"F12F0","aliases":[],"tags":[],"author":"Google","version":"4.8.95"},{"id":"5B3C7AEE-2539-4DD7-AA86-D5B3ED1EB097","name":"drag-variant","codepoint":"F0B90","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.0.39"},{"id":"4B8D8E9B-547D-4DE3-B8E1-5023867EF965","name":"drag-vertical","codepoint":"F01DD","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"BAD1F323-E74E-4E04-A1F6-4CCC7CAC2E34","name":"drag-vertical-variant","codepoint":"F12F1","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"ACAF4137-3EA8-4B7C-A1DB-C34759C70A5D","name":"drama-masks","codepoint":"F0D02","aliases":["comedy","tragedy","theatre"],"tags":[],"author":"Augustin Ursu","version":"3.3.92"},{"id":"ECDE04BF-F8A5-4DAD-B4F9-887CAE97CBE3","name":"draw","codepoint":"F0F49","aliases":["sign","signature"],"tags":["Drawing \/ Art","Form"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"E8557F02-8241-47FB-B546-402947A5818C","name":"drawing","codepoint":"F01DE","aliases":[],"tags":["Drawing \/ Art","Shape"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BF9750EC-EB85-4670-A4DE-4808729249B5","name":"drawing-box","codepoint":"F01DF","aliases":[],"tags":["Drawing \/ Art","Shape"],"author":"Google","version":"1.5.54"},{"id":"BBA92DC7-D461-44FA-8FA2-6D8846368E5C","name":"dresser","codepoint":"F0F4A","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"B70C7178-DB6F-4172-8440-3A9003AA040D","name":"dresser-outline","codepoint":"F0F4B","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"B6A0EC44-BDF3-4001-ABBF-51E0F2522BD3","name":"drone","codepoint":"F01E2","aliases":[],"tags":["Transportation + Flying"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C8E22510-9369-4C7C-B598-8799DB9FE2A2","name":"dropbox","codepoint":"F01E3","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"5FCCAA35-0339-4B8F-984A-D4112C3277C1","name":"drupal","codepoint":"F01E4","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"74F300CC-D7A5-45AF-A946-B219E82F8997","name":"duck","codepoint":"F01E5","aliases":[],"tags":["Animal"],"author":"Austin Andrews","version":"1.5.54"},{"id":"E792948B-8E66-49B5-83E7-8CDF1ECE6C5D","name":"dumbbell","codepoint":"F01E6","aliases":["weights","fitness-center","gym","barbell"],"tags":["Sport"],"author":"Google","version":"1.5.54"},{"id":"50BCAB01-5182-4FBA-9F6D-62DF6872B743","name":"dump-truck","codepoint":"F0C67","aliases":["tipper-lorry"],"tags":["Transportation + Road","Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"9F02DA93-0C4D-4A77-8F6B-E4220480AB55","name":"ear-hearing","codepoint":"F07C5","aliases":[],"tags":[],"author":"Google","version":"2.0.46"},{"id":"78ACE34A-8AC2-4259-AD8D-1118A11C6800","name":"ear-hearing-off","codepoint":"F0A45","aliases":["hearing-impaired"],"tags":[],"author":"Henrique C\u00e9sar Madeira","version":"2.6.95"},{"id":"0D1618BF-A3AD-4B4A-92EA-5DBF93BF7625","name":"earth","codepoint":"F01E7","aliases":["globe","public","planet"],"tags":["Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"E6C7261B-1CC0-41EA-844B-0DA761CDCC12","name":"earth-arrow-right","codepoint":"F1311","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"3F4C3330-49D5-4F2B-8FCC-A3448BEF521E","name":"earth-box","codepoint":"F06CD","aliases":[],"tags":[],"author":"GreenTurtwig","version":"1.8.36"},{"id":"C6EEACD5-6E55-4A4A-8E66-0CC8233470DA","name":"earth-box-minus","codepoint":"F1407","aliases":[],"tags":[],"author":"Muhammet Balsoy","version":"5.1.45"},{"id":"CAE8B8BC-E89F-49C3-8178-6F09ACED1FC3","name":"earth-box-off","codepoint":"F06CE","aliases":[],"tags":[],"author":"GreenTurtwig","version":"1.8.36"},{"id":"5CEC6008-A993-410B-985A-4E41291BE614","name":"earth-box-plus","codepoint":"F1406","aliases":[],"tags":[],"author":"Muhammet Balsoy","version":"5.1.45"},{"id":"A7F1974D-8084-4EBF-A932-2051938CB985","name":"earth-box-remove","codepoint":"F1408","aliases":[],"tags":[],"author":"Muhammet Balsoy","version":"5.1.45"},{"id":"1C8EADAE-667F-4048-A393-B05980A7CA11","name":"earth-minus","codepoint":"F1404","aliases":[],"tags":[],"author":"Muhammet Balsoy","version":"5.1.45"},{"id":"519E0041-FD5F-4DAD-96A4-BED1EDE9A20B","name":"earth-off","codepoint":"F01E8","aliases":[],"tags":["Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"046CC069-3771-4172-A9E6-F8D18161551F","name":"earth-plus","codepoint":"F1403","aliases":[],"tags":[],"author":"Muhammet Balsoy","version":"5.1.45"},{"id":"75FA6A35-88AE-4790-9B1A-0D0FD453E472","name":"earth-remove","codepoint":"F1405","aliases":[],"tags":[],"author":"Muhammet Balsoy","version":"5.1.45"},{"id":"993BB952-DF8E-47E6-AF9A-1FCBF15C6B63","name":"egg","codepoint":"F0AAF","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"2.7.94"},{"id":"5A81CAFD-E110-476D-9F72-70CC1E05D164","name":"egg-easter","codepoint":"F0AB0","aliases":[],"tags":["Holiday"],"author":"Michael Richins","version":"2.7.94"},{"id":"AF15DB15-3F15-4D7B-9EBA-EFA8E0735D30","name":"egg-off","codepoint":"F13F0","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"1813E684-616A-403C-9D59-B1ED3373B750","name":"egg-off-outline","codepoint":"F13F1","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"9C36DCFC-FBBE-4AE2-8E27-952D10E296E3","name":"egg-outline","codepoint":"F13F2","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"2E11359F-82B1-469C-9A51-F7B0EFAA3171","name":"eiffel-tower","codepoint":"F156B","aliases":["paris","france"],"tags":["Places"],"author":"Nicolas Gres","version":"5.5.55"},{"id":"589595AF-C8FF-451B-A623-2A22D0D2A181","name":"eight-track","codepoint":"F09EA","aliases":["8-track"],"tags":["Music"],"author":"GreenTurtwig","version":"2.5.94"},{"id":"4B57E9DF-354F-460D-9551-65C0DB55D788","name":"eject","codepoint":"F01EA","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"6E8EC35B-2DF2-4451-9649-E0DBA823E3B7","name":"eject-outline","codepoint":"F0B91","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"70653C90-39FA-4FA7-81D9-F1D792253067","name":"electric-switch","codepoint":"F0E9F","aliases":[],"tags":[],"author":"Louistwee","version":"3.7.94"},{"id":"7F2511AE-AD30-41EB-AEEA-5CF18C81CF91","name":"electric-switch-closed","codepoint":"F10D9","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"B17B6901-E163-48A2-8101-E1986C1400C0","name":"electron-framework","codepoint":"F1024","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"4.1.95"},{"id":"0332819B-1686-4375-86E9-0866AE19C2BF","name":"elephant","codepoint":"F07C6","aliases":[],"tags":["Animal"],"author":"Contributors","version":"2.0.46"},{"id":"6057DE08-41EC-4DE6-9ACC-7FB5AF3D4536","name":"elevation-decline","codepoint":"F01EB","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"CEFE04E6-CBE8-4DDD-BCF2-F445579B68FE","name":"elevation-rise","codepoint":"F01EC","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8A9045D4-D6AC-4660-8C55-D622156A1B8C","name":"elevator","codepoint":"F01ED","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"1.5.54"},{"id":"57DB3FF8-34D8-46A7-8D41-1A99EB31AD59","name":"elevator-down","codepoint":"F12C2","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"4.8.95"},{"id":"559121CE-CD01-4B96-9C0B-66DF7EED8944","name":"elevator-passenger","codepoint":"F1381","aliases":[],"tags":["Transportation + Other"],"author":"Moma Design Studio","version":"4.9.95"},{"id":"8EA26066-2C66-4A38-996B-8F23E288E0B7","name":"elevator-up","codepoint":"F12C1","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"4.8.95"},{"id":"0CAAACF8-3D1C-4CCA-A3E4-3590CDEEC5D6","name":"ellipse","codepoint":"F0EA0","aliases":[],"tags":["Shape"],"author":"Michael Richins","version":"3.7.94"},{"id":"EA110B23-B08F-4DAE-8F23-37A298B89A74","name":"ellipse-outline","codepoint":"F0EA1","aliases":[],"tags":["Shape"],"author":"Michael Richins","version":"3.7.94"},{"id":"14AAE073-8399-4D67-9F7E-8E9424328681","name":"email","codepoint":"F01EE","aliases":["local-post-office","mail","markunread","envelope"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8031577D-2528-4278-9F7B-93BD5DED18E3","name":"email-alert","codepoint":"F06CF","aliases":["email-warning","envelope-alert","envelope-warning"],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"1.8.36"},{"id":"91B50C6E-CEBB-42A7-8D07-8D73F2EB20C1","name":"email-alert-outline","codepoint":"F0D42","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"6930A4EF-08EB-4649-B2BB-369269DA918F","name":"email-box","codepoint":"F0D03","aliases":["envelope-box"],"tags":[],"author":"GreenTurtwig","version":"3.3.92"},{"id":"04876E3C-0FEA-43D5-9B5C-9CFFC711B180","name":"email-check","codepoint":"F0AB1","aliases":["email-tick"],"tags":[],"author":"Andrew Nenakhov","version":"2.7.94"},{"id":"465CA7E2-56E8-4AC8-9A0D-CFF225C3948A","name":"email-check-outline","codepoint":"F0AB2","aliases":["email-tick-outline"],"tags":[],"author":"Andrew Nenakhov","version":"2.7.94"},{"id":"99DE8F28-37C2-4784-8B62-5E5FD499A664","name":"email-edit","codepoint":"F0EE3","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Richins","version":"3.8.95"},{"id":"D2C2975C-678E-40BB-A313-44340B286BBE","name":"email-edit-outline","codepoint":"F0EE4","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Richins","version":"3.8.95"},{"id":"04288F6D-7E3C-4BB6-8FDE-B8951C0D0BDF","name":"email-lock","codepoint":"F01F1","aliases":["envelope-secure","email-secure","envelope-lock"],"tags":["Lock"],"author":"Simran","version":"1.5.54"},{"id":"F5FF3FDF-2BEC-4DCB-A6AB-9FF483126C70","name":"email-mark-as-unread","codepoint":"F0B92","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"FCBACFB7-0431-4F59-BCEB-75D4325DC82C","name":"email-minus","codepoint":"F0EE5","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"F2B06422-BB50-4C83-B1F2-591120544972","name":"email-minus-outline","codepoint":"F0EE6","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"7DCBC245-D966-4018-8E53-272058C73507","name":"email-multiple","codepoint":"F0EE7","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.8.95"},{"id":"A92BBC88-FCE7-41A7-813E-873B81C7F4E9","name":"email-multiple-outline","codepoint":"F0EE8","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.8.95"},{"id":"97179388-624E-48F5-9E21-1179BE74829B","name":"email-newsletter","codepoint":"F0FB1","aliases":[],"tags":[],"author":"GreenTurtwig","version":"4.0.96"},{"id":"D14EAB52-8253-40C3-AABC-43267D588B01","name":"email-off","codepoint":"F13E3","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"8495D960-EBB0-487C-A97B-64CF696DCDF4","name":"email-off-outline","codepoint":"F13E4","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"1E550A45-9D97-4918-9DEC-F536EC5C7A1C","name":"email-open","codepoint":"F01EF","aliases":["drafts","envelope-open"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"36BC0D33-4834-41EA-8EA2-90285635005A","name":"email-open-multiple","codepoint":"F0EE9","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.8.95"},{"id":"A45E544D-6002-4F11-A03C-05221DE5C502","name":"email-open-multiple-outline","codepoint":"F0EEA","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.8.95"},{"id":"4F7B4311-FC6B-463D-A2A3-760554AF144E","name":"email-open-outline","codepoint":"F05EF","aliases":["envelope-open-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"53CE3621-DBCC-45E8-B105-2BEA7493CCA0","name":"email-outline","codepoint":"F01F0","aliases":["mail-outline","envelope-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"910E199F-4A9F-473A-90A9-F69C05BD67F1","name":"email-plus","codepoint":"F09EB","aliases":["email-add","envelope-add","envelope-plus"],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"156DF0DC-6BDA-4204-BDDB-5FA69911CDDB","name":"email-plus-outline","codepoint":"F09EC","aliases":["email-add-outline","envelope-add-outline","envelope-plus-outline"],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"68040E6F-6BCD-4505-94D6-55D1E11E82ED","name":"email-receive","codepoint":"F10DA","aliases":[],"tags":[],"author":"Michael Richins","version":"4.3.95"},{"id":"2DF250FF-F6DC-4C7D-A5A6-AFEAEBAD45F4","name":"email-receive-outline","codepoint":"F10DB","aliases":[],"tags":[],"author":"Michael Richins","version":"4.3.95"},{"id":"AB3FC883-2737-4D9D-AAF4-3695BD6C7882","name":"email-remove","codepoint":"F1661","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"5EDCFB59-BBEC-407A-B079-5EC7E7686800","name":"email-remove-outline","codepoint":"F1662","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"AE2AF6F2-9E5A-4949-901F-0B5F599428C7","name":"email-search","codepoint":"F0961","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"3BC4A964-0137-4E75-B25E-7F01EDFEE1A8","name":"email-search-outline","codepoint":"F0962","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"7C66176F-E1BF-4F04-A761-377F67916FDA","name":"email-send","codepoint":"F10DC","aliases":[],"tags":[],"author":"Michael Richins","version":"4.3.95"},{"id":"795B1734-652A-4DCC-98B6-433C79C33001","name":"email-send-outline","codepoint":"F10DD","aliases":[],"tags":[],"author":"Michael Richins","version":"4.3.95"},{"id":"72B2D41E-42AA-44E7-8F1E-42AC62577F73","name":"email-sync","codepoint":"F12C7","aliases":["email-refresh","email-resend"],"tags":[],"author":"Simran","version":"4.8.95"},{"id":"0FAB1B0E-FEAB-4F12-A7FC-58D48CB9682F","name":"email-sync-outline","codepoint":"F12C8","aliases":["email-refresh-outline","email-resend-outline"],"tags":[],"author":"Simran","version":"4.8.95"},{"id":"80BB05EB-8F75-4205-9952-60B09204A9F6","name":"email-variant","codepoint":"F05F0","aliases":["envelope-variant"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"37F09EC6-7F8F-4DDB-BB18-774880A5C312","name":"ember","codepoint":"F0B30","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.8.94"},{"id":"7CACE4E9-A4B1-461E-A8E5-8032C22E86A1","name":"emby","codepoint":"F06B4","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.7.22"},{"id":"E8F2B8BE-F4EC-4B9C-BB15-001752B29FFD","name":"emoticon","codepoint":"F0C68","aliases":["smiley","face"],"tags":["Emoji"],"author":"Google","version":"3.2.89"},{"id":"5DD5C53F-8D3F-43DE-81B9-667A5372A808","name":"emoticon-angry","codepoint":"F0C69","aliases":["smiley-angry","face-angry"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"EEE3E9C1-D1B5-4D57-AD8B-7F6AD4852EE6","name":"emoticon-angry-outline","codepoint":"F0C6A","aliases":["smiley-angry-outline","face-angry-outline"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"DD5A65E9-E309-457F-9662-94AAB236A703","name":"emoticon-confused","codepoint":"F10DE","aliases":["face-confused"],"tags":["Emoji"],"author":"Michael Richins","version":"4.3.95"},{"id":"CB195387-50AC-46A3-B1C4-F3DA96E0EE42","name":"emoticon-confused-outline","codepoint":"F10DF","aliases":["face-confused-outline"],"tags":["Emoji"],"author":"Michael Richins","version":"4.3.95"},{"id":"77FAFB8C-4322-4A18-8E92-0CE311F775D3","name":"emoticon-cool","codepoint":"F0C6B","aliases":["smiley-cool","face-cool","face-sunglasses"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"62BB1B4E-67AC-4DFE-B37C-65D0F04F71D0","name":"emoticon-cool-outline","codepoint":"F01F3","aliases":["smiley-cool-outline","face-cool-outline","face-sunglasses-outline"],"tags":["Emoji"],"author":"Austin Andrews","version":"1.5.54"},{"id":"39704938-DF4F-4E60-8C20-0569B4B1819C","name":"emoticon-cry","codepoint":"F0C6C","aliases":["smiley-cry","face-cry"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"BA4B161E-72CB-476B-9894-20A90B28B4A3","name":"emoticon-cry-outline","codepoint":"F0C6D","aliases":["smiley-cry-outline","face-cry-outline"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"187185AC-5567-44DC-AC70-14B0D89C270C","name":"emoticon-dead","codepoint":"F0C6E","aliases":["smiley-dead","face-dead"],"tags":["Emoji"],"author":"Google","version":"3.2.89"},{"id":"47AD308C-C9D8-43DB-8E92-B0FB02B906CF","name":"emoticon-dead-outline","codepoint":"F069B","aliases":["smiley-dead-outline","face-dead-outline"],"tags":["Emoji"],"author":"Google","version":"1.7.12"},{"id":"7781F4B7-849F-42A4-82B1-791DBDE91295","name":"emoticon-devil","codepoint":"F0C6F","aliases":["smiley-devil","face-devil"],"tags":["Emoji"],"author":"Austin Andrews","version":"3.2.89"},{"id":"916B1319-9E91-48C0-AD65-B21B599D8FCA","name":"emoticon-devil-outline","codepoint":"F01F4","aliases":["smiley-devil-outline","face-devil-outline"],"tags":["Emoji"],"author":"Austin Andrews","version":"1.5.54"},{"id":"86E664CC-39C1-4E36-81BB-AC3BFFE65281","name":"emoticon-excited","codepoint":"F0C70","aliases":["smiley-excited","face-excited"],"tags":["Emoji"],"author":"Google","version":"3.2.89"},{"id":"828FF1EE-1B9B-4407-A45B-A071FA938158","name":"emoticon-excited-outline","codepoint":"F069C","aliases":["smiley-excited-outline","face-excited-outline"],"tags":["Emoji"],"author":"Google","version":"1.7.12"},{"id":"D5AC778B-0269-4AC5-A2D8-FD5F4D27785F","name":"emoticon-frown","codepoint":"F0F4C","aliases":["face-frown"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"AE6333C6-8334-4F90-9230-6527F3A38C8A","name":"emoticon-frown-outline","codepoint":"F0F4D","aliases":["face-frown-outline"],"tags":["Emoji"],"author":"Google","version":"3.9.97"},{"id":"CCA0187D-B8BA-4AC3-8523-B6B8F05EA5BA","name":"emoticon-happy","codepoint":"F0C71","aliases":["smiley-happy","face-happy"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"F51C2659-3EE9-471C-A919-190D3C1A9681","name":"emoticon-happy-outline","codepoint":"F01F5","aliases":["smiley-happy-outline","face-happy-outline"],"tags":["Emoji"],"author":"Gabriel","version":"1.5.54"},{"id":"01F0C520-7626-4BA6-A678-1EAB14AE2C1B","name":"emoticon-kiss","codepoint":"F0C72","aliases":["smiley-kiss","face-kiss"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"806569AC-841D-4B4E-849E-43BACC3D2268","name":"emoticon-kiss-outline","codepoint":"F0C73","aliases":["smiley-kiss-outline","face-kiss-outline"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"11CEDEB3-DB1A-45F4-92C9-6AF6FCEE4FC5","name":"emoticon-lol","codepoint":"F1214","aliases":["face-lol"],"tags":["Emoji"],"author":"Michael Richins","version":"4.6.95"},{"id":"2A7BA4B1-C436-4EE6-BF5A-34B150A9A746","name":"emoticon-lol-outline","codepoint":"F1215","aliases":["face-lol-outline"],"tags":["Emoji"],"author":"Michael Richins","version":"4.6.95"},{"id":"922B06B7-9C78-452C-AF29-79A47F0F6931","name":"emoticon-neutral","codepoint":"F0C74","aliases":["smiley-neutral","face-neutral"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"17F30B32-37E2-41BB-876C-70E568D04623","name":"emoticon-neutral-outline","codepoint":"F01F6","aliases":["smiley-neutral-outline","face-neutral-outline"],"tags":["Emoji"],"author":"Austin Andrews","version":"1.5.54"},{"id":"69AAECAA-0B17-4C53-8345-4F172B7FEF50","name":"emoticon-outline","codepoint":"F01F2","aliases":["insert-emoticon","mood","sentiment-very-satisfied","tag-faces","smiley-outline","face-outline"],"tags":["Emoji"],"author":"Google","version":"1.5.54"},{"id":"968319FB-0E94-4F04-A6D8-9E71DF200E1F","name":"emoticon-poop","codepoint":"F01F7","aliases":["smiley-poop","face-poop"],"tags":["Emoji"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1E402C80-69DB-432F-BB0F-C05ACB6A7839","name":"emoticon-poop-outline","codepoint":"F0C75","aliases":["face-poop-outline"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"CDA3C920-C286-4000-A7FC-C530CBC62CF7","name":"emoticon-sad","codepoint":"F0C76","aliases":["smiley-sad","face-sad"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"6D8A3A11-7A90-424C-82A6-93C455379743","name":"emoticon-sad-outline","codepoint":"F01F8","aliases":["smiley-sad-outline","face-sad-outline"],"tags":["Emoji"],"author":"Gabriel","version":"1.5.54"},{"id":"523F5AB1-3598-40F1-AAB5-6DF361FF6970","name":"emoticon-sick","codepoint":"F157C","aliases":["face-sick","fever"],"tags":["Emoji","Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"CBB4F1C3-3479-4F94-9F15-3D844889609A","name":"emoticon-sick-outline","codepoint":"F157D","aliases":["face-sick-outline","fever-outline"],"tags":["Emoji","Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"57288378-59EE-4705-ACD5-3B424ACA70C1","name":"emoticon-tongue","codepoint":"F01F9","aliases":["smiley-tongue","face-tongue"],"tags":["Emoji"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A08556AE-A0AD-4C7E-9A14-0CD05EE66E03","name":"emoticon-tongue-outline","codepoint":"F0C77","aliases":["smiley-tongue-outline","face-tongue-outline"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"652D2244-1764-4B42-B04D-157DDD9DC464","name":"emoticon-wink","codepoint":"F0C78","aliases":["smiley-wink","face-wink"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"C8E56EC6-52DA-4BC7-81C0-1E5B14509086","name":"emoticon-wink-outline","codepoint":"F0C79","aliases":["smiley-wink-outline","face-wink-outline"],"tags":["Emoji"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"290CA835-F009-4630-87D3-D4515E1F5527","name":"engine","codepoint":"F01FA","aliases":["motor"],"tags":["Automotive"],"author":"Simran","version":"1.5.54"},{"id":"114C29E0-B66E-49EF-8D45-77FF8EED43B1","name":"engine-off","codepoint":"F0A46","aliases":["motor-off"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"81317A61-047B-47D4-A154-CEA3C6B9F61C","name":"engine-off-outline","codepoint":"F0A47","aliases":["motor-off-outline"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"75A5F242-D136-49B9-9DFF-25F0631743A7","name":"engine-outline","codepoint":"F01FB","aliases":["motor-outline"],"tags":["Automotive"],"author":"Simran","version":"1.5.54"},{"id":"C0C7DFD3-F590-4965-A38F-167F48469E6F","name":"epsilon","codepoint":"F10E0","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Sascha Wohlgemuth","version":"4.3.95"},{"id":"119DD58E-769B-47C2-9AB8-1671DEC4FE4A","name":"equal","codepoint":"F01FC","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F98CD2ED-FD62-414E-9116-94BA99713526","name":"equal-box","codepoint":"F01FD","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4F6A532E-58ED-4CB5-9BBB-9E77C128D536","name":"equalizer","codepoint":"F0EA2","aliases":[],"tags":["Audio"],"author":"Google","version":"3.7.94"},{"id":"D3AB11FD-F0D5-4228-A6C7-69AC34649A53","name":"equalizer-outline","codepoint":"F0EA3","aliases":[],"tags":["Audio"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"758CA292-BBF5-4C08-BCBD-88B7A84C8BC6","name":"eraser","codepoint":"F01FE","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8E45C70B-EE1A-48AE-B97F-204F1958E788","name":"eraser-variant","codepoint":"F0642","aliases":[],"tags":[],"author":"Google","version":"1.6.50"},{"id":"2DB352CF-8F2F-43FD-BCA0-675F7C9D298C","name":"escalator","codepoint":"F01FF","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B4972D96-B8A1-4964-8A58-FAEA2D0C5FF9","name":"escalator-box","codepoint":"F1399","aliases":[],"tags":[],"author":"Moma Design Studio","version":"5.0.45"},{"id":"F29A47AC-C3B6-4568-8ADA-94C5F92F0DC0","name":"escalator-down","codepoint":"F12C0","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"4.8.95"},{"id":"4BA51088-9403-4E34-A829-1F31D8DE2646","name":"escalator-up","codepoint":"F12BF","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"4.8.95"},{"id":"9D305B93-7722-4784-A9D3-8F64824A67AB","name":"eslint","codepoint":"F0C7A","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"3.2.89"},{"id":"C3E4BC72-74F1-450D-8B6F-FCF0CB60AA27","name":"et","codepoint":"F0AB3","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"D59C885E-233F-4472-AB8C-00C41F96134E","name":"ethereum","codepoint":"F086A","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"3AB3C243-0FD3-4903-A6EA-B0B29ABFAD6C","name":"ethernet","codepoint":"F0200","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"FC900F32-A228-4E42-9E09-EA7CCDEC08F2","name":"ethernet-cable","codepoint":"F0201","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"79E1B678-8458-4750-9EE0-C5CE7E57E9F1","name":"ethernet-cable-off","codepoint":"F0202","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"7C687673-B2F0-43B6-A5E3-E25B9FFA0F8E","name":"ev-plug-ccs1","codepoint":"F1519","aliases":["ev-plug-ccs-combo-1","ev-charger-ccs1"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"4FE92E92-170B-495E-A16E-0897AD787E02","name":"ev-plug-ccs2","codepoint":"F151A","aliases":["ev-plug-ccs-combo-2","ev-charger-ccs2"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"C2C4C1DC-0FB1-4A1A-AA85-8FD1D8DF4532","name":"ev-plug-chademo","codepoint":"F151B","aliases":["ev-charger-chademo"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"04B5C8D6-9732-4D4D-AC1B-0C9ED9E3B8DF","name":"ev-plug-tesla","codepoint":"F151C","aliases":["ev-charger-tesla"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"781567F7-B41B-4CB2-BDD8-DDF3AB75CC57","name":"ev-plug-type1","codepoint":"F151D","aliases":["ev-plug-j1772","ev-charger-type1"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"F5687378-A23D-4D4C-98A2-55E95642FD06","name":"ev-plug-type2","codepoint":"F151E","aliases":["ev-plug-mennekes","ev-charger-type2"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"7C859DE1-16F6-4EF2-9097-A1D0C14CC3A2","name":"ev-station","codepoint":"F05F1","aliases":["charging-station","ev-charger","wall-charger","wallbox","electric-vehicle-charger","evse","electric-charger"],"tags":["Places","Automotive"],"author":"Google","version":"1.5.54"},{"id":"193F4AB4-12B2-4E3C-965F-284967A7F736","name":"evernote","codepoint":"F0204","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"0BD56A12-3F3B-4A3E-96E4-868B5414FD06","name":"excavator","codepoint":"F1025","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"06E68A9B-2ED4-4697-82A2-02F1FA342D55","name":"exclamation","codepoint":"F0205","aliases":["factorial"],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2DEA5CA1-8412-4DA4-95C4-7E1AA2C27404","name":"exclamation-thick","codepoint":"F1238","aliases":["exclamation-bold"],"tags":[],"author":"frankgrinaert","version":"4.6.95"},{"id":"9F68722F-B500-48AD-BE3A-EB7591496084","name":"exit-run","codepoint":"F0A48","aliases":["emergency-exit"],"tags":[],"author":"Simran","version":"2.6.95"},{"id":"DD2BE6C6-A15C-44D4-807A-C29DE965CF22","name":"exit-to-app","codepoint":"F0206","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"85080AB7-D860-4D74-86D8-1A2BFF0C0514","name":"expand-all","codepoint":"F0AB4","aliases":["animation-plus"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"934C9329-AC58-499E-BE89-A5E43FA71C6F","name":"expand-all-outline","codepoint":"F0AB5","aliases":["animation-plus-outline"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"6FFC7116-2E5B-40A8-A612-90706DC5EECF","name":"expansion-card","codepoint":"F08AE","aliases":["gpu","graphics-processing-unit","nic","network-interface-card"],"tags":["Gaming \/ RPG"],"author":"GreenTurtwig","version":"2.2.43"},{"id":"A644DCA0-BDC5-480E-AA15-EFD1B1D4BDEB","name":"expansion-card-variant","codepoint":"F0FB2","aliases":["graphics-processing-unit","gpu","network-interface-card","nice"],"tags":[],"author":"Michael Richins","version":"4.0.96"},{"id":"E26684D6-5292-4B09-98A9-C6C416FD236D","name":"exponent","codepoint":"F0963","aliases":["power"],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"F061DE5C-F495-4EDF-BD16-DAD6B07605BC","name":"exponent-box","codepoint":"F0964","aliases":["power-box"],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"670C2CEA-D9B1-4126-89F4-C881D032F3AD","name":"export","codepoint":"F0207","aliases":["output"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"ECCA4152-AD73-4986-ADC4-9FACDC925868","name":"export-variant","codepoint":"F0B93","aliases":["ios-share"],"tags":[],"author":"Google","version":"3.0.39"},{"id":"3C2B7DF3-97FE-4EC4-B6A9-69A75FB26B67","name":"eye","codepoint":"F0208","aliases":["show","visibility","remove-red-eye"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"7534EBC5-1A5B-4837-8C13-88CFA5FB4D49","name":"eye-check","codepoint":"F0D04","aliases":["eye-tick"],"tags":[],"author":"Austin Andrews","version":"3.3.92"},{"id":"A2829948-6FFA-48BB-B387-959A7E3658DE","name":"eye-check-outline","codepoint":"F0D05","aliases":["eye-tick-outline"],"tags":[],"author":"Austin Andrews","version":"3.3.92"},{"id":"9E70DE8C-C973-4A18-A68D-DB6670F5F38A","name":"eye-circle","codepoint":"F0B94","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"4F1A805C-7120-44A2-9A3F-8285411EFE87","name":"eye-circle-outline","codepoint":"F0B95","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"67AEA391-FE01-41D0-B594-36433AAB099E","name":"eye-minus","codepoint":"F1026","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"F36594D9-9F22-4C8B-BB09-6B89CF203881","name":"eye-minus-outline","codepoint":"F1027","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"4D1385CF-1389-43D3-BD88-A83018434FB6","name":"eye-off","codepoint":"F0209","aliases":["hide","visibility-off"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D88D00BE-0B70-40F5-AFD0-51C65DE8D674","name":"eye-off-outline","codepoint":"F06D1","aliases":["hide-outline","visibility-off-outline"],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"F2AA59FA-23F6-4FE8-A52A-AEC674A9E864","name":"eye-outline","codepoint":"F06D0","aliases":["show-outline","visibility-outline"],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"644FD0C7-1B46-48D8-A410-FDA22E63BFCF","name":"eye-plus","codepoint":"F086B","aliases":["eye-add"],"tags":[],"author":"GreenTurtwig","version":"2.1.99"},{"id":"C82BEE88-7AAC-4F8D-9A8A-4B0C7CCDF216","name":"eye-plus-outline","codepoint":"F086C","aliases":["eye-add-outline"],"tags":[],"author":"GreenTurtwig","version":"2.1.99"},{"id":"4CAD2E1D-F56B-40AA-B008-46DEFF9C9540","name":"eye-remove","codepoint":"F15E3","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"A1F300D2-BA71-410B-BB70-F18FC666CF35","name":"eye-remove-outline","codepoint":"F15E4","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"1155E86D-5CA5-4CC0-B089-23DFFC1A3DDD","name":"eye-settings","codepoint":"F086D","aliases":[],"tags":["Settings"],"author":"Michael Richins","version":"2.1.99"},{"id":"45112AC7-F34D-40E8-8C37-D8660B7017E9","name":"eye-settings-outline","codepoint":"F086E","aliases":[],"tags":["Settings"],"author":"Michael Richins","version":"2.1.99"},{"id":"89350468-16D8-4F39-AA78-C3E00EE8FB2C","name":"eyedropper","codepoint":"F020A","aliases":["pipette"],"tags":["Color","Drawing \/ Art","Science"],"author":"Austin Andrews","version":"1.5.54"},{"id":"384E765A-8184-4E9C-8300-FB4928CADA31","name":"eyedropper-minus","codepoint":"F13DD","aliases":[],"tags":["Science"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"F4A65E44-6B1F-4E9C-954A-B05FAAB3EE6D","name":"eyedropper-off","codepoint":"F13DF","aliases":[],"tags":["Science"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"FF767930-F19C-4935-8ABB-566DD8B8CF0D","name":"eyedropper-plus","codepoint":"F13DC","aliases":[],"tags":["Science"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"1224B69E-00A5-422C-A358-61201346175F","name":"eyedropper-remove","codepoint":"F13DE","aliases":[],"tags":["Science"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"24A1E7A8-D8A4-4216-B467-72C144972358","name":"eyedropper-variant","codepoint":"F020B","aliases":["colorize","colourise","pipette-variant"],"tags":["Color","Science"],"author":"Google","version":"1.5.54"},{"id":"D41E7F40-FF48-422F-A64B-4908C6C10F00","name":"face","codepoint":"F0643","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"1.6.50"},{"id":"3E0B74E0-1F0F-4820-A02F-B370CD56E463","name":"face-agent","codepoint":"F0D70","aliases":["customer-service","support"],"tags":[],"author":"Contributors","version":"3.4.93"},{"id":"8E3EC802-4BC1-44CA-83AB-9A43E55E238C","name":"face-mask","codepoint":"F1586","aliases":[],"tags":["Medical \/ Hospital","Clothing"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"0143A0CC-E3FA-485F-B3CA-6B61EE86F066","name":"face-mask-outline","codepoint":"F1587","aliases":[],"tags":["Medical \/ Hospital","Clothing"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"CFDA13BC-C61A-4FE0-8094-7B51E8EB3F82","name":"face-outline","codepoint":"F0B96","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"3.0.39"},{"id":"97E9CDDB-45B3-4592-8E1F-0DB66E16E1A3","name":"face-profile","codepoint":"F0644","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"1.6.50"},{"id":"144C6FB3-DBAC-4CA7-B07C-51265D8EE619","name":"face-profile-woman","codepoint":"F1076","aliases":[],"tags":["People \/ Family"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"FDC4CFE0-5CA9-4F8E-A126-EC98BF900228","name":"face-recognition","codepoint":"F0C7B","aliases":["facial-recognition","scan"],"tags":["Photography"],"author":"Michael Richins","version":"3.2.89"},{"id":"4680BCD4-CD85-45A0-9F1C-FB367E768664","name":"face-shimmer","codepoint":"F15CC","aliases":["face-retouching-natural"],"tags":["Photography","Account \/ User","Health \/ Beauty","People \/ Family"],"author":"Google","version":"5.6.55"},{"id":"CC7A66A4-2118-4635-B227-C184D8903867","name":"face-shimmer-outline","codepoint":"F15CD","aliases":["face-retouching-natural-outline"],"tags":["People \/ Family","Photography","Health \/ Beauty","Account \/ User"],"author":"Simran","version":"5.6.55"},{"id":"C591017E-E3D0-48CA-A517-86B21DE853A0","name":"face-woman","codepoint":"F1077","aliases":[],"tags":["People \/ Family"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"F8B0D936-DFD2-469C-B671-599D3B277B51","name":"face-woman-outline","codepoint":"F1078","aliases":[],"tags":["People \/ Family"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"97F4C885-AB98-45C3-85C7-E5DA25ECD271","name":"face-woman-shimmer","codepoint":"F15CE","aliases":["face-retouching-natural-woman"],"tags":["People \/ Family","Photography","Health \/ Beauty","Account \/ User"],"author":"Simran","version":"5.6.55"},{"id":"43851D4C-D310-45C3-9A86-6BF5DFD51055","name":"face-woman-shimmer-outline","codepoint":"F15CF","aliases":["face-retouching-natural-woman-outline"],"tags":["People \/ Family","Photography","Health \/ Beauty","Account \/ User"],"author":"Simran","version":"5.6.55"},{"id":"95CC9E46-A553-42B3-B44E-2E88DB13C1E1","name":"facebook","codepoint":"F020C","aliases":[],"tags":["Brand \/ Logo","Social Media"],"author":"Contributors","version":"1.5.54"},{"id":"62F96579-80AE-4827-9C18-1C1FD239DE49","name":"facebook-gaming","codepoint":"F07DD","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.0.46"},{"id":"1989DA16-DAA9-4C95-A61F-BA512FE5592D","name":"facebook-messenger","codepoint":"F020E","aliases":[],"tags":["Brand \/ Logo","Social Media"],"author":"Contributors","version":"1.5.54"},{"id":"767ACA6B-1ECD-4D4E-AE5D-4E1EB3C87D72","name":"facebook-workplace","codepoint":"F0B31","aliases":[],"tags":["Brand \/ Logo","Social Media"],"author":"Contributors","version":"2.8.94"},{"id":"B74F1DE6-5DEC-4866-AEED-DE85FE09C52F","name":"factory","codepoint":"F020F","aliases":["industrial"],"tags":["Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AB0F3BD7-1D6E-4ED6-8CC4-28E5ECCEF017","name":"family-tree","codepoint":"F160E","aliases":[],"tags":["People \/ Family"],"author":"Simran","version":"5.6.55"},{"id":"2606F8A3-AFD7-41EB-BD2D-C3546FEADB2F","name":"fan","codepoint":"F0210","aliases":[],"tags":["Home Automation","Automotive"],"author":"Austin Andrews","version":"1.5.54"},{"id":"94B156B3-7C70-4C0A-B1A8-99BEEA9C6357","name":"fan-alert","codepoint":"F146C","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"E695511A-9F45-44DC-9F98-9E946CC02ECC","name":"fan-auto","codepoint":"F171D","aliases":[],"tags":[],"author":"Contributors","version":"5.9.55"},{"id":"33DAA830-9E16-4AF0-A1B8-F44EA4EF9787","name":"fan-chevron-down","codepoint":"F146D","aliases":["fan-speed-down"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"5.2.45"},{"id":"1FC6584B-6B87-40C8-BA9D-C18E221A247D","name":"fan-chevron-up","codepoint":"F146E","aliases":["fan-speed-up"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"5.2.45"},{"id":"FB53FDB5-A8D0-42F6-882F-63C1A683577E","name":"fan-minus","codepoint":"F1470","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"BB761A30-6F3C-484D-A0C9-501972F544AB","name":"fan-off","codepoint":"F081D","aliases":[],"tags":["Home Automation","Automotive"],"author":"GreenTurtwig","version":"2.1.19"},{"id":"DD3CD93C-5877-4234-9944-61C10457FDCE","name":"fan-plus","codepoint":"F146F","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"3E4A1DFD-92C2-4CA0-BD74-A98496721825","name":"fan-remove","codepoint":"F1471","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"F01D5822-D36A-4A41-9544-3B1E8702582F","name":"fan-speed-1","codepoint":"F1472","aliases":["fan-speed-low"],"tags":["Home Automation"],"author":"Contributors","version":"5.2.45"},{"id":"AFC8D4DB-4196-41E6-8EBC-A6509F96EA71","name":"fan-speed-2","codepoint":"F1473","aliases":["fan-speed-medium"],"tags":["Home Automation"],"author":"Contributors","version":"5.2.45"},{"id":"0EA7825B-6236-40D5-A8D9-858B2B4DB595","name":"fan-speed-3","codepoint":"F1474","aliases":["fan-speed-high"],"tags":["Home Automation"],"author":"Contributors","version":"5.2.45"},{"id":"98B9D071-70A9-422B-BCC1-55DC4C2E0744","name":"fast-forward","codepoint":"F0211","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"960E88C3-D86B-4A9A-8581-799816D12194","name":"fast-forward-10","codepoint":"F0D71","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.4.93"},{"id":"23895783-905C-45DE-BF43-D58214199B75","name":"fast-forward-30","codepoint":"F0D06","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.3.92"},{"id":"C57CDDE7-5F5E-44B4-B1E2-E5FEFBB17A85","name":"fast-forward-5","codepoint":"F11F8","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"CF6C15FF-1B2F-4E4B-AE45-C1487815CA07","name":"fast-forward-60","codepoint":"F160B","aliases":[],"tags":[],"author":"Terren","version":"5.6.55"},{"id":"05435BA8-4BB4-4581-A2BA-D2D7679B831F","name":"fast-forward-outline","codepoint":"F06D2","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"2C398569-5DBF-4405-AF73-6F5CA629AEE1","name":"fax","codepoint":"F0212","aliases":[],"tags":["Printer","Cellphone \/ Phone"],"author":"Simran","version":"1.5.54"},{"id":"A0C975EA-A25D-4882-96DE-39CB72DAC2CA","name":"feather","codepoint":"F06D3","aliases":["quill"],"tags":["Nature"],"author":"Simran","version":"1.8.36"},{"id":"FC8210F4-FE5E-4A83-86DE-DA1B19739118","name":"feature-search","codepoint":"F0A49","aliases":["box","box-search"],"tags":[],"author":"Simran","version":"2.6.95"},{"id":"AE8C42B6-43EE-433C-83A3-83CE7464240E","name":"feature-search-outline","codepoint":"F0A4A","aliases":["box","box-outline","box-search-outline"],"tags":[],"author":"Simran","version":"2.6.95"},{"id":"15F2366C-5930-4473-B298-A5B952F07D59","name":"fedora","codepoint":"F08DB","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.3.50"},{"id":"325210DA-E889-4CBD-B0A7-8A32D706322B","name":"fencing","codepoint":"F14C1","aliases":["sword-fight"],"tags":["Sport"],"author":"Google","version":"5.3.45"},{"id":"AD285056-9A97-4C52-8D7D-06D4D1DA4213","name":"ferris-wheel","codepoint":"F0EA4","aliases":[],"tags":[],"author":"Google","version":"3.7.94"},{"id":"F138AC6A-406B-4EB0-BB85-0FDB5415B6F8","name":"ferry","codepoint":"F0213","aliases":["cargo-ship","boat","ship","directions-boat","directions-ferry"],"tags":["Transportation + Water","Navigation"],"author":"Google","version":"1.5.54"},{"id":"BFF59001-B52D-47E6-A217-C9095F81C3B8","name":"file","codepoint":"F0214","aliases":["insert-drive-file","draft","paper"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"94A8A0E0-B69E-4099-A32E-34B83449AFBC","name":"file-account","codepoint":"F073B","aliases":["file-user","resume"],"tags":["Account \/ User","Files \/ Folders"],"author":"Austin Andrews","version":"1.9.32"},{"id":"E0043E71-ED74-419B-82A9-10D678DF74B3","name":"file-account-outline","codepoint":"F1028","aliases":[],"tags":["Files \/ Folders","Account \/ User"],"author":"Terren","version":"4.1.95"},{"id":"33050FDD-7F04-44B1-AF59-BFED56FE34CF","name":"file-alert","codepoint":"F0A4B","aliases":["file-warning"],"tags":["Files \/ Folders","Alert \/ Error"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"0FF64B42-C9F6-4A0A-B09D-38D2AED8C81C","name":"file-alert-outline","codepoint":"F0A4C","aliases":["file-warning-outline"],"tags":["Files \/ Folders","Alert \/ Error"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"1B650467-2000-4A2D-B16D-9BD8A8F32B85","name":"file-cabinet","codepoint":"F0AB6","aliases":["filing-cabinet"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"AA9999FD-3434-42B9-B589-606EF1D563EA","name":"file-cad","codepoint":"F0EEB","aliases":[],"tags":["Files \/ Folders"],"author":"GreenTurtwig","version":"3.8.95"},{"id":"7FF119BB-AE68-49A0-8104-0C4CA4FE829F","name":"file-cad-box","codepoint":"F0EEC","aliases":[],"tags":["Files \/ Folders"],"author":"GreenTurtwig","version":"3.8.95"},{"id":"1C9C326F-B0B6-41A9-825D-83A458689345","name":"file-cancel","codepoint":"F0DC6","aliases":["ban","forbid"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"1DCEA17F-A76F-412E-8C25-52C9F3D63B48","name":"file-cancel-outline","codepoint":"F0DC7","aliases":["ban","forbid"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"5BEF006A-53C0-4401-87DB-F21642667712","name":"file-certificate","codepoint":"F1186","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.4.95"},{"id":"06595A20-8863-4B8C-B74D-C1DA1D32D88F","name":"file-certificate-outline","codepoint":"F1187","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.4.95"},{"id":"303BB890-634F-405C-B77C-4AC831BCAEC4","name":"file-chart","codepoint":"F0215","aliases":["file-report"],"tags":["Files \/ Folders"],"author":"Simran","version":"1.5.54"},{"id":"E8F550E7-DE55-47CE-B548-4B6987B9FDE7","name":"file-chart-outline","codepoint":"F1029","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"9E66E6CF-74AD-4DB5-953B-DC135B4AD44C","name":"file-check","codepoint":"F0216","aliases":["file-tick"],"tags":["Files \/ Folders"],"author":"Simran","version":"1.5.54"},{"id":"8F78A49B-57D2-4DCC-8A49-8E07F3F5C0D5","name":"file-check-outline","codepoint":"F0E29","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"3.6.95"},{"id":"AA0F1B90-E844-4BE2-BD8F-6D7AAB2451AB","name":"file-clock","codepoint":"F12E1","aliases":[],"tags":["Files \/ Folders","Date \/ Time"],"author":"Simran","version":"4.8.95"},{"id":"90AB6510-AEEC-4C00-BCFD-71B3F6E591CC","name":"file-clock-outline","codepoint":"F12E2","aliases":[],"tags":["Files \/ Folders","Date \/ Time"],"author":"Simran","version":"4.8.95"},{"id":"452A53B0-3718-4483-ABB0-2897EBE97312","name":"file-cloud","codepoint":"F0217","aliases":[],"tags":["Cloud","Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"99B45E9A-4FCA-429F-B98D-1E9C0EAAE0CF","name":"file-cloud-outline","codepoint":"F102A","aliases":[],"tags":["Files \/ Folders","Cloud"],"author":"Terren","version":"4.1.95"},{"id":"F11E3989-CBFD-4431-BDC1-44AEBBCDD8F6","name":"file-code","codepoint":"F022E","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B226F0F1-F2C9-45C1-A940-2517FAC9F623","name":"file-code-outline","codepoint":"F102B","aliases":[],"tags":["Files \/ Folders","Developer \/ Languages"],"author":"Terren","version":"4.1.95"},{"id":"73890E82-6C92-4578-B1D4-51D83CB5DDDE","name":"file-cog","codepoint":"F107B","aliases":["file-settings-cog"],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"6ABE5D01-4204-46C0-B0D8-B3904C2E64C2","name":"file-cog-outline","codepoint":"F107C","aliases":["file-settings-cog-outline"],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"2169C66B-967F-4AB4-9123-A8A2C6129D6C","name":"file-compare","codepoint":"F08AA","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"2.2.43"},{"id":"46650D6B-318F-4202-AB77-79A113EC77AA","name":"file-delimited","codepoint":"F0218","aliases":["file-csv"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"35CE4750-7CA9-4C9B-AB11-5C1F2A092C9C","name":"file-delimited-outline","codepoint":"F0EA5","aliases":["file-csv-outline"],"tags":["Files \/ Folders"],"author":"Terren","version":"3.7.94"},{"id":"B8F65B26-E57F-4879-852E-D894E4ACAB65","name":"file-document","codepoint":"F0219","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"83E06672-D36B-41FF-8463-080EB639F00F","name":"file-document-edit","codepoint":"F0DC8","aliases":["contract"],"tags":["Edit \/ Modify","Files \/ Folders"],"author":"GreenTurtwig","version":"3.5.94"},{"id":"E33F3608-CA6A-4BC3-BA3B-16AC369F10FD","name":"file-document-edit-outline","codepoint":"F0DC9","aliases":["contract-outline"],"tags":["Edit \/ Modify","Files \/ Folders"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"05A5AF1D-055E-4FBB-BDD4-D20F3EF105DC","name":"file-document-multiple","codepoint":"F1517","aliases":[],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"F0545588-B29A-454E-B023-4FC4ED30BCDD","name":"file-document-multiple-outline","codepoint":"F1518","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"5CB4D11F-6B3A-465D-A2CD-F4172AD287B0","name":"file-document-outline","codepoint":"F09EE","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"2.5.94"},{"id":"305DC085-34BD-4CC1-8943-E8A3B64FD110","name":"file-download","codepoint":"F0965","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"2.4.85"},{"id":"50DFA593-C997-41BD-B77E-2468649E2C1B","name":"file-download-outline","codepoint":"F0966","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"2.4.85"},{"id":"65092A6A-E7E4-42BF-91F7-9AE7F50727D4","name":"file-edit","codepoint":"F11E7","aliases":[],"tags":["Edit \/ Modify","Files \/ Folders"],"author":"frankgrinaert","version":"4.5.95"},{"id":"2EE03BED-7F6F-422E-9AAE-AAED4B591266","name":"file-edit-outline","codepoint":"F11E8","aliases":[],"tags":["Edit \/ Modify","Files \/ Folders"],"author":"frankgrinaert","version":"4.5.95"},{"id":"C3AADE94-4136-4D8E-8DFE-9AA7C88EE5D5","name":"file-excel","codepoint":"F021B","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A2FE83DC-3544-4D13-85BD-2C54CDC1A460","name":"file-excel-box","codepoint":"F021C","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"0C257A18-698B-4FF4-BC68-828FFF2A9C34","name":"file-excel-box-outline","codepoint":"F102C","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"73706EB5-5497-459A-B9C7-1C64089F31CE","name":"file-excel-outline","codepoint":"F102D","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"5693BB52-A00A-45E6-8DDD-C84FE3D9D440","name":"file-export","codepoint":"F021D","aliases":[],"tags":["Files \/ Folders"],"author":"Simran","version":"1.5.54"},{"id":"25475106-D60D-4D23-BF07-4BAADB0EA9AA","name":"file-export-outline","codepoint":"F102E","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"1417ADBB-4A11-448B-A6BA-E5D4B5A20BFF","name":"file-eye","codepoint":"F0DCA","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"A2B55937-B45F-441A-802F-4FAD69EB2144","name":"file-eye-outline","codepoint":"F0DCB","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"A9D2E13D-A9F6-48AC-9998-22756DA6C709","name":"file-find","codepoint":"F021E","aliases":["print-preview","find-in-page"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"6CB8D807-BD25-4270-80F7-F71A8D4D57C7","name":"file-find-outline","codepoint":"F0B97","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"3.0.39"},{"id":"22033CAF-C8AF-4C33-9FCD-9D6FC4EE7EAF","name":"file-hidden","codepoint":"F0613","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2318EAB3-F03A-40C3-A245-668B244A9AC1","name":"file-image","codepoint":"F021F","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C86DDD85-B79F-43C4-9497-839FF4BD7526","name":"file-image-outline","codepoint":"F0EB0","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"3.7.94"},{"id":"1294020B-960A-4390-916F-BF8118A6E7C6","name":"file-import","codepoint":"F0220","aliases":[],"tags":["Files \/ Folders"],"author":"Simran","version":"1.5.54"},{"id":"EA70B568-90C1-4512-BF97-00F4AD27F459","name":"file-import-outline","codepoint":"F102F","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"E854DC61-449E-4BA2-BAC7-656A3BB3D775","name":"file-key","codepoint":"F1184","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.4.95"},{"id":"4E2214AD-9EB5-498C-BA9B-38072C463B43","name":"file-key-outline","codepoint":"F1185","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.4.95"},{"id":"AD9A7D67-1BCF-42D6-8321-AFE1705DE2A6","name":"file-link","codepoint":"F1177","aliases":[],"tags":["Files \/ Folders"],"author":"Contributors","version":"4.4.95"},{"id":"337D2BB6-6230-4896-B51B-9A8527FF3DFA","name":"file-link-outline","codepoint":"F1178","aliases":[],"tags":["Files \/ Folders"],"author":"Contributors","version":"4.4.95"},{"id":"1D017133-E895-4103-98C1-E90D26126003","name":"file-lock","codepoint":"F0221","aliases":[],"tags":["Lock","Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"658B01A1-E16D-4D8E-B274-C66465BF1CE3","name":"file-lock-outline","codepoint":"F1030","aliases":[],"tags":["Files \/ Folders","Lock"],"author":"Terren","version":"4.1.95"},{"id":"BB72067F-4002-409B-BD46-6FD6F9CEBA51","name":"file-move","codepoint":"F0AB9","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"2.7.94"},{"id":"B1BE9CC2-F8BF-4EB9-94BB-0B3041D0FBB4","name":"file-move-outline","codepoint":"F1031","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"7696AF65-B943-4BA3-94DB-5E85077F7BA9","name":"file-multiple","codepoint":"F0222","aliases":["files"],"tags":["Files \/ Folders"],"author":"Simran","version":"1.5.54"},{"id":"13BC9B18-661D-4517-84E9-756EC2536F4E","name":"file-multiple-outline","codepoint":"F1032","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"C6CD26A5-C5F6-4C5D-AF2C-919E8ED4166C","name":"file-music","codepoint":"F0223","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C40C225E-F046-442C-BA4D-0531B626609F","name":"file-music-outline","codepoint":"F0E2A","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"3.6.95"},{"id":"36FCB7D4-D7DE-4B44-BD28-53615689D2C6","name":"file-outline","codepoint":"F0224","aliases":["paper-outline"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"D5A23F56-0398-40EF-8B0D-640CD1F39669","name":"file-pdf","codepoint":"F0225","aliases":["file-acrobat"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C09B20B5-3650-4F36-AC40-540ACE36EB6E","name":"file-pdf-box","codepoint":"F0226","aliases":["file-acrobat-box"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"27B28F1C-C311-49C2-B3EE-6D288A9F1165","name":"file-pdf-box-outline","codepoint":"F0FB3","aliases":["file-acrobat-box-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"4DEDCDD8-4C71-46DA-A8C6-04B424DF621C","name":"file-pdf-outline","codepoint":"F0E2D","aliases":["file-acrobat-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"267C5350-A0FC-4683-9FA1-30CD64AAA7E5","name":"file-percent","codepoint":"F081E","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"2.1.19"},{"id":"5ED4C3D2-3E7E-4C28-8FC7-63DE741E186A","name":"file-percent-outline","codepoint":"F1033","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"DA6C6F33-3262-442B-8E07-C22ACA9F3F94","name":"file-phone","codepoint":"F1179","aliases":[],"tags":["Files \/ Folders"],"author":"Contributors","version":"4.4.95"},{"id":"2ED01F6A-EC44-442B-925B-F3A194574EBA","name":"file-phone-outline","codepoint":"F117A","aliases":[],"tags":["Files \/ Folders"],"author":"Contributors","version":"4.4.95"},{"id":"9C42F83F-4C75-4E0A-A1C2-F10FA032E495","name":"file-plus","codepoint":"F0752","aliases":["note-add"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.9.32"},{"id":"3BC5B0CB-8FEA-4C63-A9E3-59471DF11FA1","name":"file-plus-outline","codepoint":"F0EED","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"3.8.95"},{"id":"62D44147-9B6F-4B4A-A06B-1AF92C2E7F3E","name":"file-powerpoint","codepoint":"F0227","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2C917F0E-C35E-45B2-9E60-0C3D7C2630CF","name":"file-powerpoint-box","codepoint":"F0228","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"1620AEF6-DDC2-4FC0-9117-6A3DC4C80FEB","name":"file-powerpoint-box-outline","codepoint":"F1034","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"6A605E14-B9F9-4753-A439-C9F38C0B561D","name":"file-powerpoint-outline","codepoint":"F1035","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"A7F6B3BE-8D61-4AF3-BBFC-15A795254F6A","name":"file-presentation-box","codepoint":"F0229","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"C5EBED58-BD25-4E0C-AEB8-C6316B88B620","name":"file-question","codepoint":"F086F","aliases":[],"tags":["Files \/ Folders"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"B2E908FB-D29C-4F80-BD90-B1F6676C6337","name":"file-question-outline","codepoint":"F1036","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"6AAC6C2E-4B51-4A21-8CDC-BA516D7BAB6B","name":"file-refresh","codepoint":"F0918","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.3.50"},{"id":"B48358A6-983D-4E15-8FE1-905D706A4A4B","name":"file-refresh-outline","codepoint":"F0541","aliases":[],"tags":[],"author":"Contributors","version":"1.5.54"},{"id":"1D2987A7-950D-45DF-AF0C-F465350C6374","name":"file-remove","codepoint":"F0B98","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"3.0.39"},{"id":"26E534DA-72D9-48CD-8748-4E3924E0A974","name":"file-remove-outline","codepoint":"F1037","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"8C05288A-4D13-4252-ABD1-CB288AFE9B4E","name":"file-replace","codepoint":"F0B32","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"2.8.94"},{"id":"C47F7F19-362E-49BA-8BC4-2FE6161AD44D","name":"file-replace-outline","codepoint":"F0B33","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"2.8.94"},{"id":"EE0E5547-D368-43CB-8BDD-7F3774985BEF","name":"file-restore","codepoint":"F0670","aliases":["restore-page"],"tags":["Files \/ Folders"],"author":"Google","version":"1.6.50"},{"id":"3D9EE6A3-0ECC-49C6-84E1-438D2CF2C053","name":"file-restore-outline","codepoint":"F1038","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"8FA2DBB9-E874-4CBB-A466-2691223D0FEF","name":"file-search","codepoint":"F0C7C","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"3.2.89"},{"id":"499004C4-2F88-4681-A8AC-EDE9A4ECE922","name":"file-search-outline","codepoint":"F0C7D","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"3.2.89"},{"id":"CEB97477-6633-4486-BDD4-9E7D7C747805","name":"file-send","codepoint":"F022A","aliases":["file-move"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B828E75F-BBA9-41F9-B877-CB1F1BF29ECA","name":"file-send-outline","codepoint":"F1039","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"DAD983AE-28E9-481D-B0F0-38E1EFD0CAFE","name":"file-settings","codepoint":"F1079","aliases":[],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"6F77BE81-0AD4-4886-93FF-0FA1382B8501","name":"file-settings-outline","codepoint":"F107A","aliases":[],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"E7E04B34-BC51-466F-92A1-78C8A00DDC9D","name":"file-star","codepoint":"F103A","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"B418C938-EE23-4073-B10C-C1D93D54B288","name":"file-star-outline","codepoint":"F103B","aliases":[],"tags":["Files \/ Folders"],"author":"Contributors","version":"4.1.95"},{"id":"01893B96-44C2-43EF-B979-5768B6AF7695","name":"file-swap","codepoint":"F0FB4","aliases":["file-transfer"],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.0.96"},{"id":"22D7F491-0873-43A4-9EE1-330F5BDC0829","name":"file-swap-outline","codepoint":"F0FB5","aliases":["file-transfer-outline"],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.0.96"},{"id":"C17D4D8C-F028-4EED-9C77-B9E1A66FE372","name":"file-sync","codepoint":"F1216","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"F642DE27-0183-4EF7-87FD-70A1D8E031D4","name":"file-sync-outline","codepoint":"F1217","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"663EC5E6-16C5-4075-AB5C-1215864F3B2B","name":"file-table","codepoint":"F0C7E","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"3.2.89"},{"id":"7CBD5B51-1AE9-4FCA-905F-719540F0EA40","name":"file-table-box","codepoint":"F10E1","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"6847431F-22A9-4EAD-A9C6-645C6694D050","name":"file-table-box-multiple","codepoint":"F10E2","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"1C6DE56C-E364-4D47-BA2F-4CE1DF34ACF4","name":"file-table-box-multiple-outline","codepoint":"F10E3","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"3598E989-EAC7-4255-A78F-BB1914D3153F","name":"file-table-box-outline","codepoint":"F10E4","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"D365B2EB-0B21-42D3-BC9E-7A51DE5F0A57","name":"file-table-outline","codepoint":"F0C7F","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"3.2.89"},{"id":"FE2B1AE3-7158-473B-B1EE-45FB9CAE1137","name":"file-tree","codepoint":"F0645","aliases":["subtasks"],"tags":["Files \/ Folders"],"author":"Kai Faust","version":"1.6.50"},{"id":"86EB0B3A-E46E-4439-B7BA-67A88B280961","name":"file-tree-outline","codepoint":"F13D2","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"5CCC54A4-04AF-4241-80AB-177C8365A905","name":"file-undo","codepoint":"F08DC","aliases":["file-revert","file-discard"],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"2.3.50"},{"id":"6B690FE5-C7C6-49FE-90C1-B021BDB1B2A6","name":"file-undo-outline","codepoint":"F103C","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"38FC6E1D-C2F0-4B73-BA30-2C7FAFC0C48E","name":"file-upload","codepoint":"F0A4D","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"2.6.95"},{"id":"0719AAB6-7E18-402E-9E27-C51D44C0A856","name":"file-upload-outline","codepoint":"F0A4E","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"2.6.95"},{"id":"7BEB068A-898D-43FF-AAA6-BC239FBA74F2","name":"file-video","codepoint":"F022B","aliases":[],"tags":["Video \/ Movie","Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6F2D3BA3-B23D-4476-B3D8-920033F6B68B","name":"file-video-outline","codepoint":"F0E2C","aliases":[],"tags":["Files \/ Folders"],"author":"Peter Noble","version":"3.6.95"},{"id":"05004893-1DB7-4A34-AC50-D4B46133A603","name":"file-word","codepoint":"F022C","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AE6B9B24-DD1E-4896-B385-8DBB9D21C9E7","name":"file-word-box","codepoint":"F022D","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"09E0675C-053B-4548-9FC1-2F8DC3B49364","name":"file-word-box-outline","codepoint":"F103D","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"C261E28B-72D8-4D0E-B74A-93333AE4EF4D","name":"file-word-outline","codepoint":"F103E","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"4.1.95"},{"id":"2EFEE436-9663-4C09-AD65-6727A0ED2AFD","name":"film","codepoint":"F022F","aliases":["camera-roll"],"tags":["Photography","Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"10A06B6D-A551-425C-B084-DA3F2239DFA1","name":"filmstrip","codepoint":"F0230","aliases":["local-movies","theaters"],"tags":["Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"FB635DB5-18DA-448E-81C7-0602181EE21A","name":"filmstrip-box","codepoint":"F0332","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"392DCBD5-0766-4719-B198-42A9A66C18B4","name":"filmstrip-box-multiple","codepoint":"F0D18","aliases":["library-movie"],"tags":["Video \/ Movie"],"author":"Google","version":"3.3.92"},{"id":"CB040E6C-85FD-4C09-9ACD-C41EE5FB770E","name":"filmstrip-off","codepoint":"F0231","aliases":[],"tags":["Video \/ Movie"],"author":"Austin Andrews","version":"1.5.54"},{"id":"39CAC4E6-CC95-42C8-94E9-E29089F1E91E","name":"filter","codepoint":"F0232","aliases":["funnel"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"36805F11-BE23-49C3-8D72-682859DD5551","name":"filter-menu","codepoint":"F10E5","aliases":[],"tags":[],"author":"Michael Richins","version":"4.3.95"},{"id":"18CFDA0C-648C-4513-AE67-F5BB93817E0B","name":"filter-menu-outline","codepoint":"F10E6","aliases":[],"tags":[],"author":"Michael Richins","version":"4.3.95"},{"id":"BCA7EE0A-BADF-441A-B660-C37C0DFEF83A","name":"filter-minus","codepoint":"F0EEE","aliases":["funnel-minus"],"tags":[],"author":"GreenTurtwig","version":"3.8.95"},{"id":"7AB99674-5A9A-40BE-94B4-B8CFA4A97434","name":"filter-minus-outline","codepoint":"F0EEF","aliases":["funnel-minus-outline"],"tags":[],"author":"GreenTurtwig","version":"3.8.95"},{"id":"049BC23B-DE87-4AB6-AFC3-38AC296045A3","name":"filter-off","codepoint":"F14EF","aliases":[],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"156D4779-7EC6-4BD9-A7B1-F123A387B109","name":"filter-off-outline","codepoint":"F14F0","aliases":[],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"524BE3DE-F5C8-4E2E-A329-8480136DCBDB","name":"filter-outline","codepoint":"F0233","aliases":["funnel-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"3587C73B-5120-4206-9036-2FA87974681B","name":"filter-plus","codepoint":"F0EF0","aliases":["funnel-plus"],"tags":[],"author":"GreenTurtwig","version":"3.8.95"},{"id":"69D6704C-5371-48C4-AAE1-A53EB581CF72","name":"filter-plus-outline","codepoint":"F0EF1","aliases":["funnel-plus-outline"],"tags":[],"author":"GreenTurtwig","version":"3.8.95"},{"id":"F0D392A7-69A4-4301-8E3B-46A8FC7C3DF9","name":"filter-remove","codepoint":"F0234","aliases":["funnel-remove"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"C6DD0143-A7E3-464D-B0AC-F97E5C51F74C","name":"filter-remove-outline","codepoint":"F0235","aliases":["funnel-remove-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"AECECEA4-9E56-4B4B-ACD6-2C85AB09788A","name":"filter-variant","codepoint":"F0236","aliases":["filter-list"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"10D650FB-B7AA-4439-A3BF-3F5DE934A22C","name":"filter-variant-minus","codepoint":"F1112","aliases":[],"tags":[],"author":"Fran\u00e7ois Risoud","version":"4.3.95"},{"id":"5F4F40C3-F04B-47BE-BB4F-13F080A81C6A","name":"filter-variant-plus","codepoint":"F1113","aliases":[],"tags":[],"author":"Fran\u00e7ois Risoud","version":"4.3.95"},{"id":"AE1B79F5-59D9-4FA4-8006-CE60BB5F5207","name":"filter-variant-remove","codepoint":"F103F","aliases":[],"tags":[],"author":"David Jackson","version":"4.1.95"},{"id":"C39421CD-2A2D-4D92-B59B-69D70A328DF4","name":"finance","codepoint":"F081F","aliases":["chart-finance"],"tags":["Banking","Math"],"author":"Google","version":"2.1.19"},{"id":"D093813C-B59B-42BD-B6C7-B451FA51E87E","name":"find-replace","codepoint":"F06D4","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"F71C897D-9858-40AE-8DB4-253CE675D823","name":"fingerprint","codepoint":"F0237","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"EC570B4F-91D7-4478-9B9F-4C61BC709652","name":"fingerprint-off","codepoint":"F0EB1","aliases":[],"tags":[],"author":"Michael Richins","version":"3.7.94"},{"id":"5259DBA5-B2FB-4112-B1F2-5DC17002205C","name":"fire","codepoint":"F0238","aliases":["whatshot","flame"],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"69B65938-BBEB-4E19-9D12-3924EEAAACF0","name":"fire-alert","codepoint":"F15D7","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"D056C9A3-AA4C-4220-BEE7-79E189C12711","name":"fire-extinguisher","codepoint":"F0EF2","aliases":[],"tags":["Hardware \/ Tools"],"author":"Simran","version":"3.8.95"},{"id":"78842C69-653C-40B5-BA05-578361EA0620","name":"fire-hydrant","codepoint":"F1137","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"506CEB31-5A28-4D8F-947E-A0B0B5211DA1","name":"fire-hydrant-alert","codepoint":"F1138","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"B09CB3ED-6B3A-4B3D-B795-92E96DE01F4B","name":"fire-hydrant-off","codepoint":"F1139","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"DAB67757-2065-4741-A03A-563D0EA202E0","name":"fire-off","codepoint":"F1722","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"1C8EC9A6-0545-4A59-B9F8-5E498E40529D","name":"fire-truck","codepoint":"F08AB","aliases":["fire-engine"],"tags":["Transportation + Road"],"author":"Nick","version":"2.2.43"},{"id":"3A3D9EFD-ABA4-444F-9CB5-A2D8C1322B2C","name":"firebase","codepoint":"F0967","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"2.4.85"},{"id":"2A7EE574-62BE-4000-B8D8-B601C29D2960","name":"firefox","codepoint":"F0239","aliases":["mozilla-firefox"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"B69CC506-E44A-4B60-A170-F4FFD53C67A6","name":"fireplace","codepoint":"F0E2E","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"E2D6EF7A-6C31-4DCD-B385-FC8C9B113538","name":"fireplace-off","codepoint":"F0E2F","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"6385008C-99E4-4459-8B18-0CD594EC5C7E","name":"firework","codepoint":"F0E30","aliases":["bottle-rocket"],"tags":["Holiday"],"author":"Augustin Ursu","version":"3.6.95"},{"id":"16CFC5D9-C749-4148-BF17-D002AFFF9D09","name":"firework-off","codepoint":"F1723","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"91D8C321-95BC-4AC6-9B3E-D38D457BFF75","name":"fish","codepoint":"F023A","aliases":[],"tags":["Animal","Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4F854008-B48E-4134-829A-9D3086C8F1E9","name":"fish-off","codepoint":"F13F3","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"50A773A8-4349-4B7F-A211-6CB14E9C090B","name":"fishbowl","codepoint":"F0EF3","aliases":["aquarium"],"tags":["Animal"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"860D1C47-AD7E-4424-9CB7-BA9D2F86C129","name":"fishbowl-outline","codepoint":"F0EF4","aliases":["aquarium-outline"],"tags":["Animal"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"05E31726-71FE-41C1-B2CC-93E5B4DF25CE","name":"fit-to-page","codepoint":"F0EF5","aliases":[],"tags":["Text \/ Content \/ Format","Arrow"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"0DB84D18-659E-4E93-A078-B3822742C0D4","name":"fit-to-page-outline","codepoint":"F0EF6","aliases":[],"tags":["Text \/ Content \/ Format","Arrow"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"55271063-77EF-43FA-917C-657E57135A24","name":"flag","codepoint":"F023B","aliases":["assistant-photo"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B7386AC8-4DBF-4948-AD45-49234A8A019B","name":"flag-checkered","codepoint":"F023C","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"55982621-FCB3-4A76-8F8C-50E7B6B1C93D","name":"flag-minus","codepoint":"F0B99","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"370C68CC-A001-4368-9617-B7D683361B27","name":"flag-minus-outline","codepoint":"F10B2","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"3C0BD546-A778-4BDC-A30A-A627D61CBA47","name":"flag-outline","codepoint":"F023D","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"EF2E3070-75EC-44C3-9ECE-780BB330D51B","name":"flag-plus","codepoint":"F0B9A","aliases":["flag-add"],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"32EF248B-1462-486E-AEF1-A0ED29670568","name":"flag-plus-outline","codepoint":"F10B3","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"D0FB8B1E-3270-4562-A660-968995E1B9A9","name":"flag-remove","codepoint":"F0B9B","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"65132686-1842-48E2-9AD3-17FEB5EA56F5","name":"flag-remove-outline","codepoint":"F10B4","aliases":[],"tags":[],"author":"Michael Richins","version":"4.2.95"},{"id":"3E14D0C4-25AA-405E-89A7-37E9A224BA93","name":"flag-triangle","codepoint":"F023F","aliases":["milestone"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"9A9DB93D-CE2E-4887-B648-9C70E1922092","name":"flag-variant","codepoint":"F0240","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"756B772A-F638-48EB-918C-2FA4237C7767","name":"flag-variant-outline","codepoint":"F023E","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8F4F8B2A-9E7D-432F-978E-F3F108DA701B","name":"flare","codepoint":"F0D72","aliases":["star"],"tags":[],"author":"Google","version":"3.4.93"},{"id":"EF3D6923-793B-410C-B349-90A6A338F06C","name":"flash","codepoint":"F0241","aliases":["lightning-bolt","flash-on","electricity"],"tags":["Weather"],"author":"Google","version":"1.5.54"},{"id":"59E94B6E-589B-4DB9-AAB7-397E17E2B272","name":"flash-alert","codepoint":"F0EF7","aliases":["lightning-alert","storm-advisory"],"tags":["Weather","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"2770517A-B0A3-4AC5-A6E6-6EFD9DA2C3E5","name":"flash-alert-outline","codepoint":"F0EF8","aliases":["lightning-alert-outline","storm-advisory-outline"],"tags":["Weather","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"D3251831-8AEF-420A-9AA8-2BA0A0621538","name":"flash-auto","codepoint":"F0242","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"F055DA49-5992-4DDC-8C71-E5D331520DEA","name":"flash-circle","codepoint":"F0820","aliases":["amp","offline-bolt","lightning-bolt-circle"],"tags":[],"author":"Google","version":"2.1.19"},{"id":"A6D1B09D-EDB0-4241-B42D-E56052A070DE","name":"flash-off","codepoint":"F0243","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"088BF56F-9281-43DB-879E-EB5158428EB7","name":"flash-outline","codepoint":"F06D5","aliases":["lightning-bolt-outline"],"tags":["Weather"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"C25CEF12-DF9C-45A4-8399-3102B79BDF14","name":"flash-red-eye","codepoint":"F067B","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.7.12"},{"id":"0EC7CDC8-86F4-4C72-AC2E-1DEDB196043F","name":"flashlight","codepoint":"F0244","aliases":["torch"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"043DEA8B-1F5B-49CE-BC9F-AA3FC802A58A","name":"flashlight-off","codepoint":"F0245","aliases":["torch-off"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"5E171637-949C-4091-9A6E-1A56C1DC8347","name":"flask","codepoint":"F0093","aliases":[],"tags":["Science","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"D036C297-DB1B-42F5-A856-13EEBDB48613","name":"flask-empty","codepoint":"F0094","aliases":[],"tags":["Science","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"845569FD-A57A-4F03-9048-707A046521E9","name":"flask-empty-minus","codepoint":"F123A","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"500AF1DD-69C7-4C42-AE74-B6AC589BA8A8","name":"flask-empty-minus-outline","codepoint":"F123B","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"26005876-74DC-411D-BB27-557623A42F8A","name":"flask-empty-off","codepoint":"F13F4","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"E04A35A9-0B00-4FCF-A524-CB3331FFA346","name":"flask-empty-off-outline","codepoint":"F13F5","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"E9FFE6A9-C641-47BE-988B-A94B34A90CED","name":"flask-empty-outline","codepoint":"F0095","aliases":[],"tags":["Science","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"716D7945-ED6F-40B5-890A-18A1F93247B0","name":"flask-empty-plus","codepoint":"F123C","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"DD0BAE86-6060-4A90-8A57-32CCFBC7D617","name":"flask-empty-plus-outline","codepoint":"F123D","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"64BC4DF4-E408-446C-975F-20A2F1646F1F","name":"flask-empty-remove","codepoint":"F123E","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"5B25EC76-4EB5-46AC-9445-7411CD0567DD","name":"flask-empty-remove-outline","codepoint":"F123F","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"E4673F66-5785-4A63-855D-92A9F6B0E4AE","name":"flask-minus","codepoint":"F1240","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"B8EB4BF1-B423-4C0D-9DE5-24D691E9EAF3","name":"flask-minus-outline","codepoint":"F1241","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"D886A9E0-E952-4DF0-97B0-0C630E956766","name":"flask-off","codepoint":"F13F6","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"4AA0C752-79B8-4EF6-A4E2-7B610599DEE3","name":"flask-off-outline","codepoint":"F13F7","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"14C068EE-90AC-42DA-AA1E-D24F74EE7263","name":"flask-outline","codepoint":"F0096","aliases":[],"tags":["Science","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6FA94A7A-788F-44B6-90A7-B4EACF9B6FD3","name":"flask-plus","codepoint":"F1242","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"AE491BF6-EA26-4732-AF63-8A3D83379CC6","name":"flask-plus-outline","codepoint":"F1243","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"ED698844-E3E9-4FD3-89F2-A41163ACD80A","name":"flask-remove","codepoint":"F1244","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"67E2EA68-867E-4514-A952-2E0A90D5C2AC","name":"flask-remove-outline","codepoint":"F1245","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"E7D0BD51-A831-4355-AE75-1D903C121D3F","name":"flask-round-bottom","codepoint":"F124B","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"A08CBFD8-DD21-47F9-B213-7EF3AD89EDAD","name":"flask-round-bottom-empty","codepoint":"F124C","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"2BD05FF6-4E09-40EC-9D34-59FB9CCD09FF","name":"flask-round-bottom-empty-outline","codepoint":"F124D","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"383DEA4E-9820-4C4C-A5FD-05C151C7B82A","name":"flask-round-bottom-outline","codepoint":"F124E","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"4.6.95"},{"id":"1BB3488A-A7B4-4DA5-99A2-AD23A184606B","name":"fleur-de-lis","codepoint":"F1303","aliases":[],"tags":[],"author":"Nick","version":"4.8.95"},{"id":"9D29290D-A243-4C72-BC8C-ABCDFB4448B2","name":"flip-horizontal","codepoint":"F10E7","aliases":[],"tags":["Arrange"],"author":"Google","version":"4.3.95"},{"id":"F9DD0BF3-1CF8-456E-A542-2D22131A5761","name":"flip-to-back","codepoint":"F0247","aliases":[],"tags":["Arrange"],"author":"Google","version":"1.5.54"},{"id":"6CEAE4F9-F6CB-4DA8-A25C-1F41494C6DD5","name":"flip-to-front","codepoint":"F0248","aliases":[],"tags":["Arrange"],"author":"Google","version":"1.5.54"},{"id":"D5DC28B3-CD69-465C-9333-9463A75072DC","name":"flip-vertical","codepoint":"F10E8","aliases":[],"tags":["Arrange"],"author":"Google","version":"4.3.95"},{"id":"BEF1218E-7AF7-45F9-930E-915791D51EDC","name":"floor-lamp","codepoint":"F08DD","aliases":["floor-light"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"08F74DD4-A57F-4CC8-9568-88E826BE71E5","name":"floor-lamp-dual","codepoint":"F1040","aliases":["floor-light-dual"],"tags":["Home Automation"],"author":"Borre Haugen","version":"4.1.95"},{"id":"85969E2D-500B-4565-8B80-A59FB6C8A73B","name":"floor-lamp-variant","codepoint":"F1041","aliases":["floor-light-variant"],"tags":["Home Automation"],"author":"Borre Haugen","version":"4.1.95"},{"id":"131D3C5D-880D-486B-A041-039B1F1E5284","name":"floor-plan","codepoint":"F0821","aliases":[],"tags":["Home Automation"],"author":"Contributors","version":"2.1.19"},{"id":"B4AC5BF4-AF66-4DC5-9743-F62A80489149","name":"floppy","codepoint":"F0249","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8A4453F7-03E3-4F10-B93F-3213645300F8","name":"floppy-variant","codepoint":"F09EF","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"D73BB486-A112-48C1-A4EE-993825164C43","name":"flower","codepoint":"F024A","aliases":["local-florist","plant"],"tags":["Nature"],"author":"Google","version":"1.5.54"},{"id":"0BF283D1-7C12-4E5F-B136-558BE534AC8D","name":"flower-outline","codepoint":"F09F0","aliases":["local-florist-outline","plant"],"tags":["Nature"],"author":"Google","version":"2.5.94"},{"id":"9C310133-C0AC-4456-B8A0-9ED17F2C08BA","name":"flower-poppy","codepoint":"F0D08","aliases":["plant"],"tags":["Nature"],"author":"Colton Wiscombe","version":"3.3.92"},{"id":"4CD0F242-7779-4B61-B13C-876236FE92B4","name":"flower-tulip","codepoint":"F09F1","aliases":["plant"],"tags":["Nature"],"author":"Michael Richins","version":"2.5.94"},{"id":"D6449362-3D4B-42FB-BD25-020B104B4602","name":"flower-tulip-outline","codepoint":"F09F2","aliases":["plant"],"tags":["Nature"],"author":"Michael Richins","version":"2.5.94"},{"id":"F04E0123-6365-491F-9A98-1D634D2F3071","name":"focus-auto","codepoint":"F0F4E","aliases":[],"tags":["Photography"],"author":"Simran","version":"3.9.97"},{"id":"4B35FE7D-BD1E-46D1-9C4C-DCCFC3DCEC44","name":"focus-field","codepoint":"F0F4F","aliases":[],"tags":["Photography"],"author":"Simran","version":"3.9.97"},{"id":"B7F6C8DE-200D-4BCA-9E71-2AF633968C43","name":"focus-field-horizontal","codepoint":"F0F50","aliases":[],"tags":["Photography"],"author":"Simran","version":"3.9.97"},{"id":"CC4C833A-A1B9-4847-9BCB-3EAC3CCF15F5","name":"focus-field-vertical","codepoint":"F0F51","aliases":[],"tags":["Photography"],"author":"Simran","version":"3.9.97"},{"id":"9D8C1CEE-19BE-4B0B-85CC-DEB829F9F045","name":"folder","codepoint":"F024B","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"0C56278E-06DE-4D32-BA08-C78F3EB572CC","name":"folder-account","codepoint":"F024C","aliases":["folder-user","folder-shared"],"tags":["Account \/ User","Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"B905BF65-7312-4F62-8979-EDB2906B38E6","name":"folder-account-outline","codepoint":"F0B9C","aliases":["folder-user-outline","folder-shared-outline"],"tags":["Files \/ Folders","Account \/ User"],"author":"Google","version":"3.0.39"},{"id":"D26F1A90-B76E-4C13-A956-2EBA33493563","name":"folder-alert","codepoint":"F0DCC","aliases":["folder-warning"],"tags":["Files \/ Folders","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"9CF67925-5A21-47F8-8EF5-F567D902C1D2","name":"folder-alert-outline","codepoint":"F0DCD","aliases":["folder-warning-outline"],"tags":["Files \/ Folders","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"A3CB34A0-7E6E-4DF8-B17A-20C9180B3C76","name":"folder-clock","codepoint":"F0ABA","aliases":[],"tags":["Files \/ Folders","Date \/ Time"],"author":"GreenTurtwig","version":"2.7.94"},{"id":"3EC459AC-889B-4D24-A6E2-978BA7A908BB","name":"folder-clock-outline","codepoint":"F0ABB","aliases":[],"tags":["Files \/ Folders","Date \/ Time"],"author":"Austin Andrews","version":"2.7.94"},{"id":"C5113090-DFDF-461C-BD5F-885DF9938A9E","name":"folder-cog","codepoint":"F107F","aliases":["folder-cog"],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"FDC5F42F-066B-4833-B8E9-E2E245FC80F6","name":"folder-cog-outline","codepoint":"F1080","aliases":["folder-cog-outline"],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"E10E0982-353D-484A-886B-30D343261422","name":"folder-download","codepoint":"F024D","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"20FEED41-F560-4872-82F4-4ED5D01EA474","name":"folder-download-outline","codepoint":"F10E9","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.3.95"},{"id":"1C40CBC9-118F-4145-B0A5-B10007870272","name":"folder-edit","codepoint":"F08DE","aliases":[],"tags":["Files \/ Folders","Edit \/ Modify"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"A990E58F-2E88-4293-892E-F58252416749","name":"folder-edit-outline","codepoint":"F0DCE","aliases":[],"tags":["Edit \/ Modify","Files \/ Folders"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"B8ACEEFF-E80A-42A9-BCAE-A804D47D8929","name":"folder-google-drive","codepoint":"F024E","aliases":["folder-mydrive"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"E67BA814-6FCF-48CB-BBB3-359070145BCF","name":"folder-heart","codepoint":"F10EA","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"B8BBFB97-F4D8-4FE1-B2CE-6590CBA2A337","name":"folder-heart-outline","codepoint":"F10EB","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"EF46E7D8-3062-41E5-8FC6-92D66DEF7603","name":"folder-home","codepoint":"F10B5","aliases":[],"tags":["Files \/ Folders"],"author":"Contributors","version":"4.2.95"},{"id":"5CFE89BB-F160-4C01-95C8-CFDF3D2099DA","name":"folder-home-outline","codepoint":"F10B6","aliases":[],"tags":["Files \/ Folders"],"author":"Contributors","version":"4.2.95"},{"id":"726DE98D-9BA1-4E73-8632-FF3F3768A3B3","name":"folder-image","codepoint":"F024F","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A2C97734-F322-430B-BA09-02B0EB2D2CB5","name":"folder-information","codepoint":"F10B7","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"C31ED401-6424-4436-84A8-3E82C95B1E79","name":"folder-information-outline","codepoint":"F10B8","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"30D99FD0-397C-49B6-A5CE-B9D6CFD7E66E","name":"folder-key","codepoint":"F08AC","aliases":[],"tags":["Files \/ Folders"],"author":"Simran","version":"2.2.43"},{"id":"0C6934F1-2CC9-4689-B388-B3F2A78E026A","name":"folder-key-network","codepoint":"F08AD","aliases":[],"tags":["Files \/ Folders"],"author":"Simran","version":"2.2.43"},{"id":"59629095-DF90-4405-8164-0EFB00808958","name":"folder-key-network-outline","codepoint":"F0C80","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"DE3EB621-D1A5-4F61-96F4-C8794191D34F","name":"folder-key-outline","codepoint":"F10EC","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"FABB67CE-5F69-4D45-95B9-02D7BFC9EABD","name":"folder-lock","codepoint":"F0250","aliases":[],"tags":["Lock","Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F89AD3B3-DD09-44F7-81A7-0433ECD44A8F","name":"folder-lock-open","codepoint":"F0251","aliases":[],"tags":["Lock","Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"00FD0F50-240F-4654-9712-C219B0FF9A97","name":"folder-marker","codepoint":"F126D","aliases":[],"tags":["Geographic Information System","Files \/ Folders"],"author":"Contributors","version":"4.7.95"},{"id":"A542AF06-5931-4B8A-8DE0-777F11304ACC","name":"folder-marker-outline","codepoint":"F126E","aliases":[],"tags":["Geographic Information System","Files \/ Folders"],"author":"Contributors","version":"4.7.95"},{"id":"B7AD0302-5738-4474-9679-AC118E566A7E","name":"folder-move","codepoint":"F0252","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"F3985E52-B82C-4008-98E3-48DCDBC21749","name":"folder-move-outline","codepoint":"F1246","aliases":[],"tags":["Files \/ Folders"],"author":"Sascha Wohlgemuth","version":"4.6.95"},{"id":"7116841C-C243-4A44-8C68-267048AAF939","name":"folder-multiple","codepoint":"F0253","aliases":["folders"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"29BE785E-BAAB-4824-A0BF-6892D8027B1E","name":"folder-multiple-image","codepoint":"F0254","aliases":["perm-media","folders-image"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"F91AD38D-33E3-46A4-83BC-17B671750D6C","name":"folder-multiple-outline","codepoint":"F0255","aliases":["folders-outline"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C7BBAA2A-AE24-41E9-AED3-6932D2D0CCAF","name":"folder-multiple-plus","codepoint":"F147E","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"5.3.45"},{"id":"CF776532-C79F-4319-B2FB-F9EDD407E063","name":"folder-multiple-plus-outline","codepoint":"F147F","aliases":[],"tags":["Files \/ Folders"],"author":"Terren","version":"5.3.45"},{"id":"4D36C1AA-F109-485C-8D3C-EDDD054057AF","name":"folder-music","codepoint":"F1359","aliases":[],"tags":["Files \/ Folders"],"author":"\u00d6zg\u00fcr G\u00f6rg\u00fcl\u00fc","version":"4.9.95"},{"id":"629FB453-89C2-4B3F-A12E-2FDC427FCD0D","name":"folder-music-outline","codepoint":"F135A","aliases":[],"tags":["Files \/ Folders"],"author":"\u00d6zg\u00fcr G\u00f6rg\u00fcl\u00fc","version":"4.9.95"},{"id":"7C4EED9D-D897-4B8C-9C0B-FE9A9D820A2D","name":"folder-network","codepoint":"F0870","aliases":[],"tags":["Files \/ Folders"],"author":"Simran","version":"2.1.99"},{"id":"1C9D27B7-BBF8-45BD-AF63-200A7E67E8DA","name":"folder-network-outline","codepoint":"F0C81","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"7BBC57AE-0EBA-4198-8B85-5082A38522DE","name":"folder-open","codepoint":"F0770","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.9.32"},{"id":"DFC9E65E-7019-4520-9797-418E410FEABC","name":"folder-open-outline","codepoint":"F0DCF","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"0524FF60-B273-4675-9B69-043730244645","name":"folder-outline","codepoint":"F0256","aliases":["folder-open"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"BAE32170-6509-4D1F-A6A5-A2FD1A0C679B","name":"folder-plus","codepoint":"F0257","aliases":["create-new-folder","folder-add"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5615B9DB-A490-4977-9513-B21B086BB542","name":"folder-plus-outline","codepoint":"F0B9D","aliases":["create-new-folder-outline","folder-add-outline"],"tags":["Files \/ Folders"],"author":"Google","version":"3.0.39"},{"id":"FEA28688-AA8C-4CEE-937C-9110076B3214","name":"folder-pound","codepoint":"F0D09","aliases":["folder-hash"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"AA3153A7-917B-4D2B-9D8E-297AE296F195","name":"folder-pound-outline","codepoint":"F0D0A","aliases":["folder-hash-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"9B23FB77-FAF2-4F8E-B071-D23726EA8632","name":"folder-refresh","codepoint":"F0749","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.9.32"},{"id":"DBC01AAD-8FE1-4668-9E76-7AF716D30C32","name":"folder-refresh-outline","codepoint":"F0542","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3FF41316-69DC-4913-A299-84206E12FE42","name":"folder-remove","codepoint":"F0258","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1990909C-A843-4BE0-83B9-83FB51707CAD","name":"folder-remove-outline","codepoint":"F0B9E","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"3.0.39"},{"id":"8F02F34C-2C77-43BF-BF20-5EDCA4C37A85","name":"folder-search","codepoint":"F0968","aliases":[],"tags":["Files \/ Folders"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"05CF7DE7-1D45-45C3-9BCC-363735A36550","name":"folder-search-outline","codepoint":"F0969","aliases":[],"tags":["Files \/ Folders"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"E9863879-31CD-48D3-B40B-FD49B692A787","name":"folder-settings","codepoint":"F107D","aliases":[],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"BE00F5DD-75FB-43C5-BE8F-56117E1EC823","name":"folder-settings-outline","codepoint":"F107E","aliases":[],"tags":["Settings","Files \/ Folders"],"author":"Simran","version":"4.2.95"},{"id":"58C8B00C-897C-4381-9AD2-33B754B96865","name":"folder-star","codepoint":"F069D","aliases":["folder-special"],"tags":["Files \/ Folders"],"author":"Google","version":"1.7.12"},{"id":"407F7D88-25F6-4EDF-8489-3F8B7996F704","name":"folder-star-multiple","codepoint":"F13D3","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"C7DD0CB0-EEA4-4D24-BCE2-8184382EF419","name":"folder-star-multiple-outline","codepoint":"F13D4","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"3CE11413-D500-4DFA-8913-A22A16D6DAD5","name":"folder-star-outline","codepoint":"F0B9F","aliases":["folder-special-outline"],"tags":["Files \/ Folders"],"author":"Google","version":"3.0.39"},{"id":"B8D54537-7FBC-44B4-8091-2F85D8ACF05B","name":"folder-swap","codepoint":"F0FB6","aliases":["folder-transfer"],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.0.96"},{"id":"EE80C9C6-6C17-4049-9C87-B6E7E3D956EA","name":"folder-swap-outline","codepoint":"F0FB7","aliases":["folder-transfer-outline"],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.0.96"},{"id":"8E493781-E2CB-48C6-8C07-24BD1F5F3BF0","name":"folder-sync","codepoint":"F0D0B","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"3.3.92"},{"id":"AE853799-5608-4541-BD65-C7AC6AD09256","name":"folder-sync-outline","codepoint":"F0D0C","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"3.3.92"},{"id":"58AC43F6-6A0B-43AC-B681-A68B6714B4F1","name":"folder-table","codepoint":"F12E3","aliases":[],"tags":["Files \/ Folders"],"author":"Simran","version":"4.8.95"},{"id":"1C994AC5-D1CA-457D-8A8C-F6E40821815F","name":"folder-table-outline","codepoint":"F12E4","aliases":[],"tags":["Files \/ Folders"],"author":"Simran","version":"4.8.95"},{"id":"2A24B473-B162-4B0E-9723-6867EEA702A9","name":"folder-text","codepoint":"F0C82","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"3.2.89"},{"id":"D80E4CB4-F5E6-4BA8-A8C9-B24A3C31E56F","name":"folder-text-outline","codepoint":"F0C83","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"3.2.89"},{"id":"9F84EC25-D8C7-4BB0-B39F-E71919F4EE6D","name":"folder-upload","codepoint":"F0259","aliases":[],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"1.5.54"},{"id":"841EF884-AC6E-4930-8DEA-6C87F91BE11F","name":"folder-upload-outline","codepoint":"F10ED","aliases":[],"tags":["Files \/ Folders"],"author":"Michael Richins","version":"4.3.95"},{"id":"1573C575-7FBA-4BCD-A960-02D42043FE6F","name":"folder-zip","codepoint":"F06EB","aliases":["compressed-folder"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"55AE86E1-C6DB-4F41-BC21-1750DB608D23","name":"folder-zip-outline","codepoint":"F07B9","aliases":["compressed-folder-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"2.0.46"},{"id":"0D7EBC60-1884-41C7-B37E-E0EED68E896E","name":"font-awesome","codepoint":"F003A","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"140954DE-20F5-4A8B-BFC3-DB8E49922AF3","name":"food","codepoint":"F025A","aliases":["fast-food","burger","cup","drink","hamburger"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"D5B1A45F-8C43-4E3B-8E75-09EAF1984021","name":"food-apple","codepoint":"F025B","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F1E2E692-7E18-4D28-8F6C-6E6D16161CF2","name":"food-apple-outline","codepoint":"F0C84","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"3.2.89"},{"id":"28363B2E-72C8-481E-B702-7DE52F72717C","name":"food-croissant","codepoint":"F07C8","aliases":[],"tags":["Food \/ Drink"],"author":"Alex Efremo","version":"2.0.46"},{"id":"83BA130B-E603-4455-B7C6-EDE9BE1FCC7E","name":"food-drumstick","codepoint":"F141F","aliases":["chicken-leg","turkey-leg","meat"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"BC4982E1-86E2-48A1-AE1B-8FD95D6BA850","name":"food-drumstick-off","codepoint":"F1468","aliases":["chicken-leg-off","turkey-leg-off","meat-off"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"CC221369-59E9-45B7-9CBD-79AB2828689A","name":"food-drumstick-off-outline","codepoint":"F1469","aliases":["chicken-leg-off-outline","turkey-leg-off-outline","meat-off-outline"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"D60C4F90-EE53-4A92-84F7-076DAC23FD31","name":"food-drumstick-outline","codepoint":"F1420","aliases":["chicken-leg-outline","turkey-leg-outline","meat-outline"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"4CE93EC4-0938-4CB2-AB0E-0DCA0AF27B91","name":"food-fork-drink","codepoint":"F05F2","aliases":["food-fork-cup"],"tags":["Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"F576B145-F06D-49FA-9616-2423C5D322AD","name":"food-halal","codepoint":"F1572","aliases":["food-muslim","dietary-restriction"],"tags":["Food \/ Drink"],"author":"Haley Halcyon","version":"5.5.55"},{"id":"BC887CBF-E298-4E05-8C7D-B13539C4BA15","name":"food-kosher","codepoint":"F1573","aliases":["food-jewish","dietary-restriction"],"tags":["Food \/ Drink"],"author":"Haley Halcyon","version":"5.5.55"},{"id":"3731F58E-CAEA-4B54-87A6-7F4E039F2B31","name":"food-off","codepoint":"F05F3","aliases":["fast-food-off","burger-off","cup-off","drink-off","hamburger-off"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1A357DD0-01F0-4FF9-83D3-41B9AA22E5D1","name":"food-steak","codepoint":"F146A","aliases":["meat","beef"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"A0482E2B-FA1E-4478-BA16-A7EF749920B3","name":"food-steak-off","codepoint":"F146B","aliases":["meat-off","beef-off"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"D5900301-8742-4D92-8E56-525DCDE97E0F","name":"food-turkey","codepoint":"F171C","aliases":["dinner","thanksgiving"],"tags":["Food \/ Drink","Holiday"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"1D25DDEC-2656-4729-BEBD-BB17F972DD09","name":"food-variant","codepoint":"F025C","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C24FE6CB-D1AA-4BAB-BB6B-956307D28D1D","name":"food-variant-off","codepoint":"F13E5","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"5.1.45"},{"id":"DAAA09E2-055A-4D74-BF60-C46DC6019035","name":"foot-print","codepoint":"F0F52","aliases":[],"tags":[],"author":"Contributors","version":"3.9.97"},{"id":"3C0488C6-E807-401D-9689-7770550EC2E7","name":"football","codepoint":"F025D","aliases":["football-american"],"tags":["Sport"],"author":"Austin Andrews","version":"1.5.54"},{"id":"97B1FB51-7C30-4B83-AEED-95700B38F65F","name":"football-australian","codepoint":"F025E","aliases":[],"tags":["Sport"],"author":"Austin Andrews","version":"1.5.54"},{"id":"8F719D4B-9A91-46E1-81B0-00C23AA0D313","name":"football-helmet","codepoint":"F025F","aliases":[],"tags":["Sport"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9CB941AF-8C23-4201-B891-A23521B011CD","name":"forklift","codepoint":"F07C9","aliases":[],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"34C52C66-C35A-470B-A618-303A8B0DBD17","name":"form-dropdown","codepoint":"F1400","aliases":[],"tags":["Form"],"author":"Charlie Davis","version":"5.1.45"},{"id":"09F44862-B3EA-4F67-8C4F-67C830FC8CF3","name":"form-select","codepoint":"F1401","aliases":[],"tags":["Form"],"author":"Charlie Davis","version":"5.1.45"},{"id":"9C901687-3535-4B54-B963-7E92EB9CE229","name":"form-textarea","codepoint":"F1095","aliases":[],"tags":["Form"],"author":"Michael Richins","version":"4.2.95"},{"id":"BB7E18FD-F473-4A80-B6A9-A17D3648E0A4","name":"form-textbox","codepoint":"F060E","aliases":["rename"],"tags":["Form"],"author":"Austin Andrews","version":"1.5.54"},{"id":"32C3C391-9B80-4659-BCB3-6653FE4E5108","name":"form-textbox-lock","codepoint":"F135D","aliases":[],"tags":["Form","Lock"],"author":"Austin Andrews","version":"4.9.95"},{"id":"F35B5B3C-762F-473C-B229-B6818D50E045","name":"form-textbox-password","codepoint":"F07F5","aliases":[],"tags":["Form"],"author":"Michael Richins","version":"2.0.46"},{"id":"CF22AACF-228D-4C3A-9BE7-D5DE853A0139","name":"format-align-bottom","codepoint":"F0753","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.9.32"},{"id":"9B295DCA-8352-407E-84F1-34890975D010","name":"format-align-center","codepoint":"F0260","aliases":["format-align-centre"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"521B67DD-EC96-4B1D-B884-BE155D850F85","name":"format-align-justify","codepoint":"F0261","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"56F0424F-3D53-486E-BC4C-0738457ACBA8","name":"format-align-left","codepoint":"F0262","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"59384E78-B7EF-4BDA-B537-35E537C00130","name":"format-align-middle","codepoint":"F0754","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.9.32"},{"id":"7289388F-3768-4833-B282-0662FD9B9A73","name":"format-align-right","codepoint":"F0263","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"71140AD8-A0A6-45DD-9414-5DB2FBC875F1","name":"format-align-top","codepoint":"F0755","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.9.32"},{"id":"55770606-AFB4-441F-B3AA-2CDE46136F4B","name":"format-annotation-minus","codepoint":"F0ABC","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"591A45AB-511C-4791-957C-303186C666AA","name":"format-annotation-plus","codepoint":"F0646","aliases":["format-annotation-add"],"tags":["Text \/ Content \/ Format"],"author":"Kai Faust","version":"1.6.50"},{"id":"2107C153-0FEC-4171-8602-6549ACABA768","name":"format-bold","codepoint":"F0264","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"D5213C5D-AC53-40A5-BBCC-C8B3F849D6B4","name":"format-clear","codepoint":"F0265","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"C4E2DE69-EC92-490F-814A-5D8A20E7E595","name":"format-color-fill","codepoint":"F0266","aliases":["format-colour-fill","paint","paint-bucket","ink-color","ink-colour"],"tags":["Text \/ Content \/ Format","Color"],"author":"Google","version":"1.5.54"},{"id":"3681D567-0B40-47FF-843A-3258A16F935B","name":"format-color-highlight","codepoint":"F0E31","aliases":["format-colour-highlight"],"tags":["Color","Text \/ Content \/ Format"],"author":"Austin Andrews","version":"3.6.95"},{"id":"C6D32152-B2F3-43D3-A78E-D69CBDC5E054","name":"format-color-marker-cancel","codepoint":"F1313","aliases":["format-color-redact"],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"D28EF658-3CE7-4F5B-99B3-50F60F5B0BA0","name":"format-color-text","codepoint":"F069E","aliases":["format-colour-text"],"tags":["Text \/ Content \/ Format","Color"],"author":"Google","version":"1.7.12"},{"id":"FB93EA15-A9E8-432C-BC34-419DDCE44E3B","name":"format-columns","codepoint":"F08DF","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Peter Noble","version":"2.3.50"},{"id":"3BC78F10-A7C3-4F15-9328-138E35CFC259","name":"format-float-center","codepoint":"F0267","aliases":["format-float-centre"],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"E595D32A-5108-4E9A-BF98-52DEFC1A50EE","name":"format-float-left","codepoint":"F0268","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"22DE1517-7E6C-43B9-B0E1-F3EDAEFE6398","name":"format-float-none","codepoint":"F0269","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"8F5AF64B-3A3D-449C-9FCC-374EAF6D523C","name":"format-float-right","codepoint":"F026A","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"C7D57EF8-207C-48F9-953A-EAFB03308A1E","name":"format-font","codepoint":"F06D6","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Haley Halcyon","version":"1.8.36"},{"id":"4FA696A5-8843-4E3F-B9BF-5BCF5B6C4D2C","name":"format-font-size-decrease","codepoint":"F09F3","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"934DCE7F-D2A8-40F5-B945-A35DBD3F207B","name":"format-font-size-increase","codepoint":"F09F4","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"F64E046B-8690-4ACF-90F7-98896159BB34","name":"format-header-1","codepoint":"F026B","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"00E2A358-A6A9-493C-BFC2-A259AA0092CF","name":"format-header-2","codepoint":"F026C","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"EE76BE9D-B10D-43C8-9B5A-746BE228C344","name":"format-header-3","codepoint":"F026D","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CC669D6C-53AD-43C2-A660-EFF783847D6F","name":"format-header-4","codepoint":"F026E","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FFC1FF08-CEFF-4623-B715-4731CDEF27D4","name":"format-header-5","codepoint":"F026F","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"854D0158-05E0-47A7-8E6E-2F66DCD415EE","name":"format-header-6","codepoint":"F0270","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CF17BB12-9537-4F2E-9E88-3E1DE3D0DCE6","name":"format-header-decrease","codepoint":"F0271","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"99554AA1-419F-420F-9AEB-0826D411B420","name":"format-header-equal","codepoint":"F0272","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"20BCC8DA-F055-46B0-9C27-68791E3BA80E","name":"format-header-increase","codepoint":"F0273","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"C632F7EE-B560-4FAA-802E-968DAB3EA979","name":"format-header-pound","codepoint":"F0274","aliases":["format-header-hash"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"83EE24A9-9D1A-45AA-B4CD-F75F1174F0EB","name":"format-horizontal-align-center","codepoint":"F061E","aliases":["format-horizontal-align-centre"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.6.50"},{"id":"AEA5545F-4C74-4A14-8F9E-92CC258216AD","name":"format-horizontal-align-left","codepoint":"F061F","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.6.50"},{"id":"7EFCB642-F9B5-41C8-B2CF-2566C6AC45C2","name":"format-horizontal-align-right","codepoint":"F0620","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.6.50"},{"id":"148FD97C-E3C6-4E41-87B8-488036159CC6","name":"format-indent-decrease","codepoint":"F0275","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"18B9F49B-7A69-4E93-AEA6-8CB30F22E100","name":"format-indent-increase","codepoint":"F0276","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"F766C5E3-1BBB-4ADE-9D33-170A223DB6F9","name":"format-italic","codepoint":"F0277","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"B9EB5A17-979C-47C5-8F20-E2436511E0C4","name":"format-letter-case","codepoint":"F0B34","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.8.94"},{"id":"79F06165-5718-4618-8056-1BEB689BF7CF","name":"format-letter-case-lower","codepoint":"F0B35","aliases":["format-lowercase"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.8.94"},{"id":"0C748102-1ABB-4762-A407-B64C960618D7","name":"format-letter-case-upper","codepoint":"F0B36","aliases":["format-uppercase"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.8.94"},{"id":"B2B22BA8-6F5A-45F8-9A48-B6CC932DFD62","name":"format-letter-ends-with","codepoint":"F0FB8","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"4.0.96"},{"id":"62D729FA-8643-4FAF-9D2D-176AE4ED3774","name":"format-letter-matches","codepoint":"F0FB9","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"4.0.96"},{"id":"870F391E-A069-461E-9296-904B34308D98","name":"format-letter-starts-with","codepoint":"F0FBA","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"4.0.96"},{"id":"24F69EED-721D-48A1-BA3C-3C1657B65C04","name":"format-line-spacing","codepoint":"F0278","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"2E9CEB4F-7C1F-4572-9A8E-830A3258407A","name":"format-line-style","codepoint":"F05C8","aliases":[],"tags":["Text \/ Content \/ Format","Drawing \/ Art"],"author":"Google","version":"1.5.54"},{"id":"1BA8A6A0-348E-4268-B02B-6708E1E30373","name":"format-line-weight","codepoint":"F05C9","aliases":[],"tags":["Text \/ Content \/ Format","Drawing \/ Art"],"author":"Google","version":"1.5.54"},{"id":"2FBAE8A7-BAC7-44C8-85DC-EB458871BF29","name":"format-list-bulleted","codepoint":"F0279","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"4AA98685-EEBB-4816-801E-3B12DCB4413F","name":"format-list-bulleted-square","codepoint":"F0DD0","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.5.94"},{"id":"C436DF00-A54E-48D1-9A4A-EA21A90E4FF5","name":"format-list-bulleted-triangle","codepoint":"F0EB2","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Richins","version":"3.7.94"},{"id":"535ABAF7-65D8-4CAB-A3B0-D5B732B6C36F","name":"format-list-bulleted-type","codepoint":"F027A","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"45A8DC8E-AD79-4205-AC8B-4BCC17B6F465","name":"format-list-checkbox","codepoint":"F096A","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"2.4.85"},{"id":"2B19EECF-71BF-41F3-B62A-468607BA0B47","name":"format-list-checks","codepoint":"F0756","aliases":["to-do"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.9.32"},{"id":"EFEB4AB3-780B-4C2D-B673-36BB0A4FE0B2","name":"format-list-numbered","codepoint":"F027B","aliases":["format-list-numbers"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"8480FB3F-93B8-4445-BE6D-56A47441D6A6","name":"format-list-numbered-rtl","codepoint":"F0D0D","aliases":["format-list-numbered-right-to-left"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.3.92"},{"id":"5458AB97-471F-4A96-92E0-FB0AE72AFF33","name":"format-list-text","codepoint":"F126F","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"5D87D3E1-C59B-47A2-9ADE-C96FF1C7CA21","name":"format-overline","codepoint":"F0EB3","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Contributors","version":"3.7.94"},{"id":"4C2390EF-6AE7-4868-945B-AACD2E581F46","name":"format-page-break","codepoint":"F06D7","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.8.36"},{"id":"70232BC6-D883-48CD-B992-9EE1DABEBFD7","name":"format-paint","codepoint":"F027C","aliases":[],"tags":["Text \/ Content \/ Format","Color","Drawing \/ Art"],"author":"Google","version":"1.5.54"},{"id":"252574CE-020B-461A-995B-D4BA81741BBC","name":"format-paragraph","codepoint":"F027D","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9AF465C3-5FEF-48E4-8D38-5A5A3D2A9799","name":"format-pilcrow","codepoint":"F06D8","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Richins","version":"1.8.36"},{"id":"0450C081-EE6B-4CB1-A7F7-B6F0F524CA99","name":"format-quote-close","codepoint":"F027E","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"55118B26-26AC-43F3-B85C-1FF22306A77E","name":"format-quote-close-outline","codepoint":"F11A8","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"4.5.95"},{"id":"CF5D126B-7DC1-4BE7-B5A1-E31B715EDBAA","name":"format-quote-open","codepoint":"F0757","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.9.32"},{"id":"B9143BB9-06E0-40A3-8B38-D0687A1BEA69","name":"format-quote-open-outline","codepoint":"F11A7","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"4.5.95"},{"id":"99448D5B-50D3-4F49-8E88-DD75F7DFB231","name":"format-rotate-90","codepoint":"F06AA","aliases":["rotate-90-degrees-ccw","format-rotate-ninety"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.7.12"},{"id":"6F0198AB-0903-4B36-AC27-B72EBC7A8A83","name":"format-section","codepoint":"F069F","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Richins","version":"1.7.12"},{"id":"3F6E54F6-CF3E-46C8-BD72-A9BCF6DCF80C","name":"format-size","codepoint":"F027F","aliases":["font-size"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"0BE83BB5-3D22-478D-AAC2-F586A4E5FA69","name":"format-strikethrough","codepoint":"F0280","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"CB728339-FA66-440F-9E88-8A6FFE827EA1","name":"format-strikethrough-variant","codepoint":"F0281","aliases":["strikethrough-s"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"4765CE92-9095-4C00-9137-1C35761C7B59","name":"format-subscript","codepoint":"F0282","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"41BF2594-97C2-481A-AA66-029CE1BF4C2D","name":"format-superscript","codepoint":"F0283","aliases":["exponent"],"tags":["Text \/ Content \/ Format","Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FE7F03F1-79D3-4113-A35E-088C3F2AB8AD","name":"format-text","codepoint":"F0284","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C40131F3-E8A5-44CB-90A0-E230114C0DC3","name":"format-text-rotation-angle-down","codepoint":"F0FBB","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"4.0.96"},{"id":"9C650D6F-20FE-4496-8973-B19509A47A18","name":"format-text-rotation-angle-up","codepoint":"F0FBC","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"4.0.96"},{"id":"580E85A8-696F-46FE-B141-F13A94078F22","name":"format-text-rotation-down","codepoint":"F0D73","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.4.93"},{"id":"D6CC1545-8778-4A0D-9B2B-7A34DB91ADD9","name":"format-text-rotation-down-vertical","codepoint":"F0FBD","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"D5935D28-A7D0-4F35-9917-625E5A9666CD","name":"format-text-rotation-none","codepoint":"F0D74","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.4.93"},{"id":"2A113842-ED83-4F44-B7DE-A0AFF5DDB452","name":"format-text-rotation-up","codepoint":"F0FBE","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"4.0.96"},{"id":"A8232518-D348-46AF-953C-907F7F0F3D51","name":"format-text-rotation-vertical","codepoint":"F0FBF","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"4.0.96"},{"id":"E79B26A6-CAA3-4CD8-B5C8-1D5797C4C765","name":"format-text-variant","codepoint":"F0E32","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"98078792-391E-4CB0-8C7A-8F76868FA289","name":"format-text-variant-outline","codepoint":"F150F","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Haley Halcyon","version":"5.4.55"},{"id":"DD6BADDA-B656-424C-AF6D-509CB7E382D2","name":"format-text-wrapping-clip","codepoint":"F0D0E","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.3.92"},{"id":"EF57DF3A-9441-45FD-B124-5247DB8E04C2","name":"format-text-wrapping-overflow","codepoint":"F0D0F","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.3.92"},{"id":"AB362496-50E2-4978-BA63-41F90057BB64","name":"format-text-wrapping-wrap","codepoint":"F0D10","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.3.92"},{"id":"8A502343-16E9-4FF5-A0FE-28328B37E7C2","name":"format-textbox","codepoint":"F0D11","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"3.3.92"},{"id":"D6B79C3B-22FB-4B52-90B8-6979AB48C3E8","name":"format-textdirection-l-to-r","codepoint":"F0285","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"C317FCCF-DCDB-4429-B1A7-850FED29F5B3","name":"format-textdirection-r-to-l","codepoint":"F0286","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"4B4B86CC-C989-4629-9B9D-C31243A29DB9","name":"format-title","codepoint":"F05F4","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"DD218F3D-C302-477A-9B9F-482813328DE6","name":"format-underline","codepoint":"F0287","aliases":["format-underlined"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"723F4461-61B3-4D53-A03D-302F5D9401E1","name":"format-vertical-align-bottom","codepoint":"F0621","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.6.50"},{"id":"4C8985BA-B48F-4015-9389-35672ECDE544","name":"format-vertical-align-center","codepoint":"F0622","aliases":["format-vertical-align-centre"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.6.50"},{"id":"06A3A04F-F7F7-4707-86FC-5DEBA497B79E","name":"format-vertical-align-top","codepoint":"F0623","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.6.50"},{"id":"556AFB1F-1857-4CB9-94B8-2E7E8A8DD292","name":"format-wrap-inline","codepoint":"F0288","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"D5787449-1950-4A7C-8CD9-CABC628AFBCE","name":"format-wrap-square","codepoint":"F0289","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"4AA96763-2A6C-4BF0-BA64-32AD08B530F6","name":"format-wrap-tight","codepoint":"F028A","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"0378C7CD-8331-42A0-9C0F-114960FD5966","name":"format-wrap-top-bottom","codepoint":"F028B","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Andreas Gohr","version":"1.5.54"},{"id":"3AC84477-2308-4445-868C-9666AE25B054","name":"forum","codepoint":"F028C","aliases":["message-group","question-answer","chat"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"E6469D88-74CE-4242-8226-85BB8F8EFFB0","name":"forum-outline","codepoint":"F0822","aliases":["chat-outline"],"tags":[],"author":"Google","version":"2.1.19"},{"id":"EAE07425-A6D5-4B33-A9C5-6D7E9E9E1908","name":"forward","codepoint":"F028D","aliases":[],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"A626AD09-C436-4622-905C-9C7E8164CD54","name":"forwardburger","codepoint":"F0D75","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"9267CA84-62FD-4346-BCA8-42B4617CCB43","name":"fountain","codepoint":"F096B","aliases":[],"tags":[],"author":"Augustin Ursu","version":"2.4.85"},{"id":"E7415545-8386-424D-8CF5-933EE43D74CB","name":"fountain-pen","codepoint":"F0D12","aliases":[],"tags":["Drawing \/ Art"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"892B5243-DF37-4511-B4A1-1D688A39ED52","name":"fountain-pen-tip","codepoint":"F0D13","aliases":[],"tags":["Drawing \/ Art"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"54CA035A-3BAB-4349-8FD1-D50A1990D301","name":"freebsd","codepoint":"F08E0","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.3.50"},{"id":"A53E5953-2094-419A-A418-57BE05F751C8","name":"frequently-asked-questions","codepoint":"F0EB4","aliases":["faq"],"tags":[],"author":"Austin Andrews","version":"3.7.94"},{"id":"148520BB-2172-4261-9336-3E85E5131869","name":"fridge","codepoint":"F0290","aliases":["fridge-filled","refrigerator"],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"032BF3C7-46C6-40D8-BBD4-4CDE8CBCC48B","name":"fridge-alert","codepoint":"F11B1","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"9BC979D8-9012-4CB1-A041-7A19ADC8E08D","name":"fridge-alert-outline","codepoint":"F11B2","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"F88B80D0-1521-48F8-BC15-94BA5F14BFC1","name":"fridge-bottom","codepoint":"F0292","aliases":["fridge-filled-top","refrigerator-bottom"],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"48D0CA48-04CB-4C87-8F19-DBD5286A6E7B","name":"fridge-industrial","codepoint":"F15EE","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"3A45CCD3-F520-4A5D-BF83-2F0C28F66337","name":"fridge-industrial-alert","codepoint":"F15EF","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"8AAF0069-BCC9-4922-A32B-C1625C27AF98","name":"fridge-industrial-alert-outline","codepoint":"F15F0","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"6670F529-AA9D-41B4-9D0B-D435209CE045","name":"fridge-industrial-off","codepoint":"F15F1","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"5A046326-A491-45B3-A524-E9CA61BC7255","name":"fridge-industrial-off-outline","codepoint":"F15F2","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"C3B23703-739D-45E6-9FEB-CEB630D638CC","name":"fridge-industrial-outline","codepoint":"F15F3","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"417BCDA5-DCA7-4EFF-B2BF-670E9DD10961","name":"fridge-off","codepoint":"F11AF","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"4430029A-EC83-4078-A287-AD986DE6B2AE","name":"fridge-off-outline","codepoint":"F11B0","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"214668FF-C50D-4D69-B916-AE66E73CB3B0","name":"fridge-outline","codepoint":"F028F","aliases":["kitchen","refrigerator-outline"],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3D6FCDAF-F7F8-42C2-87C6-6DF36EB8C935","name":"fridge-top","codepoint":"F0291","aliases":["fridge-filled-bottom","refrigerator-top"],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"3066672D-30F0-44BF-B396-C0A2E5BCC1FF","name":"fridge-variant","codepoint":"F15F4","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"091DA8FF-AD64-4F13-BF05-E21B39C1E171","name":"fridge-variant-alert","codepoint":"F15F5","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"782A053A-D6FF-4B8E-B3A2-4ADCB6A7BA9A","name":"fridge-variant-alert-outline","codepoint":"F15F6","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"99BB3B9D-0011-4493-B80C-539874638521","name":"fridge-variant-off","codepoint":"F15F7","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"7B4DCE91-4647-4646-A93C-D7542FEAC5AC","name":"fridge-variant-off-outline","codepoint":"F15F8","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"B1E31148-2318-459A-AA91-1C87D306D71A","name":"fridge-variant-outline","codepoint":"F15F9","aliases":[],"tags":["Home Automation"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"11A7EAA3-B398-4F36-80B0-A4C50965E812","name":"fruit-cherries","codepoint":"F1042","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"693BA957-6E56-406A-B061-CCA1B916E408","name":"fruit-cherries-off","codepoint":"F13F8","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"1F2DF3F1-F380-491D-BC09-B3262612DF23","name":"fruit-citrus","codepoint":"F1043","aliases":["fruit-lemon","fruit-lime"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"AA24652D-2BA2-4C09-87A4-9E71C1A18CA9","name":"fruit-citrus-off","codepoint":"F13F9","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"C2A76F16-19FC-4D88-B131-B90E5B3ED517","name":"fruit-grapes","codepoint":"F1044","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"D2E95893-08FB-4C63-9420-AD5C890EBAE6","name":"fruit-grapes-outline","codepoint":"F1045","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"F28FDEF7-E169-45AA-84E7-13DB0A6CA241","name":"fruit-pineapple","codepoint":"F1046","aliases":["fruit-ananas"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"0219370F-F54F-444F-8312-288CB435784E","name":"fruit-watermelon","codepoint":"F1047","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"8E016660-0C3A-46EA-B3A5-8DC490238EC7","name":"fuel","codepoint":"F07CA","aliases":["petrol","gasoline"],"tags":["Automotive"],"author":"Haley Halcyon","version":"2.0.46"},{"id":"A4F7E2E4-704C-4A71-99D5-4BD19AD8E755","name":"fullscreen","codepoint":"F0293","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"CE6DC9C1-A636-4B3E-B838-34069330D3B2","name":"fullscreen-exit","codepoint":"F0294","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"76B75225-53BF-4523-BD48-CB555FFF0C67","name":"function","codepoint":"F0295","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8424F867-9F66-42FB-92D3-91724FB2CA38","name":"function-variant","codepoint":"F0871","aliases":[],"tags":[],"author":"Michael Richins","version":"2.1.99"},{"id":"D9CC1449-7E53-4305-A521-C4E705390012","name":"furigana-horizontal","codepoint":"F1081","aliases":["ruby-horizontal"],"tags":["Text \/ Content \/ Format"],"author":"Haley Halcyon","version":"4.2.95"},{"id":"68042B53-6F94-4EE1-A40D-9415AE0EE14A","name":"furigana-vertical","codepoint":"F1082","aliases":["zhuyin","ruby-vertical"],"tags":["Text \/ Content \/ Format"],"author":"Haley Halcyon","version":"4.2.95"},{"id":"E1A77AA6-9DC6-49C8-8049-89EEE3545A4A","name":"fuse","codepoint":"F0C85","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"EDE0F403-427B-468D-9CCA-75608159964C","name":"fuse-alert","codepoint":"F142D","aliases":[],"tags":["Automotive","Alert \/ Error"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"84BD762F-B0EC-4195-A6E2-7BF1E9386AE6","name":"fuse-blade","codepoint":"F0C86","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"174BB611-F232-474B-B563-DCC770985930","name":"fuse-off","codepoint":"F142C","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"5C29EFA9-0FF3-4101-BC87-C9C15ACBA7AB","name":"gamepad","codepoint":"F0296","aliases":["games"],"tags":["Home Automation","Gaming \/ RPG"],"author":"Google","version":"1.5.54"},{"id":"C2CE3BF5-B623-4170-AD29-CAC89C4EBB93","name":"gamepad-circle","codepoint":"F0E33","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"A7E881F0-76BD-4711-A238-5ECAEA02EAFC","name":"gamepad-circle-down","codepoint":"F0E34","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"AE90913A-5172-4699-98FC-7B935C753E1E","name":"gamepad-circle-left","codepoint":"F0E35","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"D227F063-202F-4B7D-9175-790055F07506","name":"gamepad-circle-outline","codepoint":"F0E36","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"97C7D65D-6073-473D-9D21-7DCB3CA7556D","name":"gamepad-circle-right","codepoint":"F0E37","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"233618F0-A837-4938-AEF8-93DA6A92A70E","name":"gamepad-circle-up","codepoint":"F0E38","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"E007AB79-ED6E-4746-9D55-A35F6BD2C93C","name":"gamepad-down","codepoint":"F0E39","aliases":[],"tags":["Gaming \/ RPG"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"D8A2D400-73A0-467E-9144-581D51735E0F","name":"gamepad-left","codepoint":"F0E3A","aliases":[],"tags":["Gaming \/ RPG"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"D513E54E-6492-4C2A-99E9-3E50C5662B88","name":"gamepad-right","codepoint":"F0E3B","aliases":[],"tags":["Gaming \/ RPG"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"3AD46D54-4369-483C-A0B5-E03D7CF62F3B","name":"gamepad-round","codepoint":"F0E3C","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"ABC572E9-CE00-450F-A1E0-E59BCF0C3DC3","name":"gamepad-round-down","codepoint":"F0E3D","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"07D26BD5-0B09-4FAF-9710-DA1F19C40C39","name":"gamepad-round-left","codepoint":"F0E3E","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"808C141C-877E-49D3-93D6-A69F985A7881","name":"gamepad-round-outline","codepoint":"F0E3F","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"4D10A9D6-5E25-457D-B4ED-25BCC647E62E","name":"gamepad-round-right","codepoint":"F0E40","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"D3C1F57B-FF1A-4CD9-AD39-E3F3AB752779","name":"gamepad-round-up","codepoint":"F0E41","aliases":[],"tags":["Gaming \/ RPG"],"author":"Haley Halcyon","version":"3.6.95"},{"id":"0FE0FB42-286B-4D56-AE93-6D93EA514C4B","name":"gamepad-square","codepoint":"F0EB5","aliases":[],"tags":["Gaming \/ RPG"],"author":"Google","version":"3.7.94"},{"id":"1370B995-F9FF-4B39-9414-055908214152","name":"gamepad-square-outline","codepoint":"F0EB6","aliases":[],"tags":["Gaming \/ RPG"],"author":"Google","version":"3.7.94"},{"id":"56D5F5A6-18F7-4FA5-8D16-48058EBD98D3","name":"gamepad-up","codepoint":"F0E42","aliases":[],"tags":["Gaming \/ RPG"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"A4DB98F5-FFD6-4F36-BB90-1B06AB202096","name":"gamepad-variant","codepoint":"F0297","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"25A261F0-9C5E-4103-88C8-70CEBA27270D","name":"gamepad-variant-outline","codepoint":"F0EB7","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"3.7.94"},{"id":"9D9227EC-5170-4765-832D-CDCF4AD79CAE","name":"gamma","codepoint":"F10EE","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Sascha Wohlgemuth","version":"4.3.95"},{"id":"CB6D190E-D7B6-4B40-804A-B868BE682C4D","name":"gantry-crane","codepoint":"F0DD1","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"FC744BA5-2E98-459F-BBD6-60788B23D93E","name":"garage","codepoint":"F06D9","aliases":[],"tags":["Home Automation"],"author":"Alex Efremo","version":"1.8.36"},{"id":"03ED4E2F-41CE-47D7-ABB4-C8515C202499","name":"garage-alert","codepoint":"F0872","aliases":["garage-warning"],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Richins","version":"2.1.99"},{"id":"25425A4D-48BD-4139-BA72-81D0DAB54020","name":"garage-alert-variant","codepoint":"F12D5","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"6B34986A-5D17-4C64-9840-994B66EC00AB","name":"garage-open","codepoint":"F06DA","aliases":[],"tags":["Home Automation"],"author":"Alex Efremo","version":"1.8.36"},{"id":"8AE7213F-00BD-40D9-A524-2CCB60511BBA","name":"garage-open-variant","codepoint":"F12D4","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"11A3EA2E-E0A4-435D-B53D-55EB0E8A5F10","name":"garage-variant","codepoint":"F12D3","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"7CEC48C5-3A70-4BA2-9FB8-A383387DC4A1","name":"gas-cylinder","codepoint":"F0647","aliases":["tank","oxygen-tank"],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"50E30598-BCD8-4167-BDAC-FF6971E745D7","name":"gas-station","codepoint":"F0298","aliases":["gas-pump","petrol-pump","petrol-station","local-gas-station","fuel-station","fuel-pump"],"tags":["Places","Automotive"],"author":"Google","version":"1.5.54"},{"id":"7ED35A9C-D8FD-4892-84E5-3700C907AE28","name":"gas-station-off","codepoint":"F1409","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.1.45"},{"id":"7C77CE4A-4C13-4853-8F4D-0F6F99EC0248","name":"gas-station-off-outline","codepoint":"F140A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.1.45"},{"id":"E489326F-90B9-43E6-91CF-9123E914E84F","name":"gas-station-outline","codepoint":"F0EB8","aliases":["gas-pump-outline","petrol-pump-outline","petrol-station-outline","fuel-station-outline","fuel-pump-outline"],"tags":[],"author":"Google","version":"3.7.94"},{"id":"340B7941-DB9B-40A2-9968-100AB599F204","name":"gate","codepoint":"F0299","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"01E01742-E5ED-4E63-9F19-48CBE619C7A5","name":"gate-and","codepoint":"F08E1","aliases":["logic-gate-and"],"tags":[],"author":"Nick","version":"2.3.50"},{"id":"314B9DB4-1D98-4394-BAD4-8FA5FB2EA160","name":"gate-arrow-right","codepoint":"F1169","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"4.4.95"},{"id":"FF2BA1EF-7AAE-4271-B799-6A51FE84427E","name":"gate-nand","codepoint":"F08E2","aliases":["logic-gate-nand"],"tags":[],"author":"Nick","version":"2.3.50"},{"id":"9BFED3B5-B327-480D-BFCD-18F9CC52D82A","name":"gate-nor","codepoint":"F08E3","aliases":["logic-gate-nor"],"tags":[],"author":"Nick","version":"2.3.50"},{"id":"3A4475B4-3774-4A2A-B672-59DAF8AE3398","name":"gate-not","codepoint":"F08E4","aliases":["logic-gate-not"],"tags":[],"author":"Nick","version":"2.3.50"},{"id":"F5A29B6C-A003-423D-912A-A23D40E51D3C","name":"gate-open","codepoint":"F116A","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"4.4.95"},{"id":"13B88427-8795-48CF-B647-597997C6C541","name":"gate-or","codepoint":"F08E5","aliases":["logic-gate-or"],"tags":[],"author":"Nick","version":"2.3.50"},{"id":"DA573FDA-7BEE-4B80-90BA-AA04932B43C6","name":"gate-xnor","codepoint":"F08E6","aliases":["logic-gate-xnor"],"tags":[],"author":"Nick","version":"2.3.50"},{"id":"AFA3ABA2-1237-417E-8277-8509C7A58C1C","name":"gate-xor","codepoint":"F08E7","aliases":["logic-gate-xor"],"tags":[],"author":"Nick","version":"2.3.50"},{"id":"2D5D41CF-9332-42E5-B6E9-C3A62E3A8135","name":"gatsby","codepoint":"F0E43","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"3.6.95"},{"id":"EC7B7499-25F1-43D4-9A09-9742F5B6D3F2","name":"gauge","codepoint":"F029A","aliases":["swap-driving-apps-wheel","barometer"],"tags":["Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"2ED34069-D2CE-427F-8E96-C493C3D9DC5D","name":"gauge-empty","codepoint":"F0873","aliases":[],"tags":["Automotive"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"3AA721AB-566F-461F-812B-CC6652E9E800","name":"gauge-full","codepoint":"F0874","aliases":[],"tags":["Automotive"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"BFF1F377-BBAF-4354-A914-D0FD1BC9DA22","name":"gauge-low","codepoint":"F0875","aliases":[],"tags":["Automotive"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"AB600896-534E-4A82-8E7F-99E0F22B54AE","name":"gavel","codepoint":"F029B","aliases":["court-hammer"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0441EBEF-476C-420E-A04E-58367F99BD93","name":"gender-female","codepoint":"F029C","aliases":["venus"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"78C91AE2-F79B-48EF-9CCD-5E6874BA20CA","name":"gender-male","codepoint":"F029D","aliases":["mars"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"9B06F269-893F-4F1C-910D-D26578C6D976","name":"gender-male-female","codepoint":"F029E","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"1599350F-AA11-47A2-8D1C-B60DF1A0A5AD","name":"gender-male-female-variant","codepoint":"F113F","aliases":["mercury"],"tags":[],"author":"Simran","version":"4.4.95"},{"id":"85F577F7-626B-4D2D-A392-2671C979BEF3","name":"gender-non-binary","codepoint":"F1140","aliases":["gender-enby"],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"47F759DA-8ECB-4BAA-8102-A843844EEBB3","name":"gender-transgender","codepoint":"F029F","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D6664050-0082-4C50-B5AD-D6D0D23B842D","name":"gentoo","codepoint":"F08E8","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.3.50"},{"id":"FFC2833D-65AB-47BB-AC7C-8CFA41DF9250","name":"gesture","codepoint":"F07CB","aliases":["freehand-line"],"tags":["Drawing \/ Art"],"author":"Google","version":"2.0.46"},{"id":"D02C7FA0-E8E6-48B7-BEB7-4678B8D9DCA1","name":"gesture-double-tap","codepoint":"F073C","aliases":["interaction-double-tap","hand-double-tap"],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"17A555A5-0518-42D0-87F8-6C332F81DF18","name":"gesture-pinch","codepoint":"F0ABD","aliases":[],"tags":[],"author":"Michael Richins","version":"2.7.94"},{"id":"82C8D8F3-13FE-4B69-A554-1FA74E516480","name":"gesture-spread","codepoint":"F0ABE","aliases":[],"tags":[],"author":"Michael Richins","version":"2.7.94"},{"id":"0C51419E-7710-4BE2-B509-425E4E7E2CC5","name":"gesture-swipe","codepoint":"F0D76","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"92FD3A8C-813E-4AC1-8D0B-85B89747C598","name":"gesture-swipe-down","codepoint":"F073D","aliases":[],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"5032C271-1D07-4318-9FC6-813C3ECA11FF","name":"gesture-swipe-horizontal","codepoint":"F0ABF","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.7.94"},{"id":"D0887CD1-2BF1-4A5A-B573-2BA6FF8A6129","name":"gesture-swipe-left","codepoint":"F073E","aliases":[],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"9B3D3150-CF71-473E-AF65-403C389C308A","name":"gesture-swipe-right","codepoint":"F073F","aliases":[],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"CE26D04A-C6AC-4379-AA25-A702F49F1DC2","name":"gesture-swipe-up","codepoint":"F0740","aliases":[],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"8883FDF0-A6B8-4252-BC2A-D12F99D20501","name":"gesture-swipe-vertical","codepoint":"F0AC0","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.7.94"},{"id":"D881AFBC-7477-46C2-9269-324676F19E51","name":"gesture-tap","codepoint":"F0741","aliases":["interaction-tap","hand-tap"],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"FC2EE3B3-9885-4278-9BCE-491B27B4666E","name":"gesture-tap-box","codepoint":"F12A9","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"51E5488F-71C4-4E08-950D-EAAAB7B22D53","name":"gesture-tap-button","codepoint":"F12A8","aliases":["call-to-action","cta"],"tags":[],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"B502F4A5-5545-42F7-A0B4-E90BF4421D17","name":"gesture-tap-hold","codepoint":"F0D77","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"96C02705-84D1-4677-9DDE-CCDE1D43FE11","name":"gesture-two-double-tap","codepoint":"F0742","aliases":[],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"AA47E759-39DE-4A5C-B3CF-FAEB215EAB91","name":"gesture-two-tap","codepoint":"F0743","aliases":[],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"6B39D7DA-255C-4615-84D4-FFCF34D76A4A","name":"ghost","codepoint":"F02A0","aliases":["inky","blinky","pinky","clyde"],"tags":["Gaming \/ RPG"],"author":"Simran","version":"1.5.54"},{"id":"5322EB23-9081-4E99-9735-7C31003C0167","name":"ghost-off","codepoint":"F09F5","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.5.94"},{"id":"9B371D94-3C53-410F-A4A5-024415B30244","name":"ghost-off-outline","codepoint":"F165C","aliases":[],"tags":["Gaming \/ RPG"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"71BF426E-71FE-4AEC-946A-A2CCAC371C31","name":"ghost-outline","codepoint":"F165D","aliases":[],"tags":["Gaming \/ RPG"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"7FCFB449-8096-408A-88E4-B73343DB201F","name":"gif","codepoint":"F0D78","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"62403C7B-F20E-489B-8835-28F7544D9712","name":"gift","codepoint":"F0E44","aliases":["present","package","donate"],"tags":["Holiday"],"author":"Simran","version":"3.6.95"},{"id":"17729CE1-90B8-4C63-A142-99056CDDC860","name":"gift-off","codepoint":"F16EF","aliases":["present-off","package-off","donate-off"],"tags":["Holiday"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"E1260280-2F0F-4D7D-AA15-0322C8699541","name":"gift-off-outline","codepoint":"F16F0","aliases":["present-off-outline","package-off-outline","donate-off-outline"],"tags":["Holiday"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"04D976AC-875C-42F1-A9F6-B86FDAAD6990","name":"gift-open","codepoint":"F16F1","aliases":["present-open","package-open"],"tags":["Holiday"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"64BCFFC7-8E6B-4644-B14D-5B1F9EF16899","name":"gift-open-outline","codepoint":"F16F2","aliases":["present-open-outline","package-open-outline"],"tags":["Holiday"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"22D0C782-CD05-4FEB-845F-BBA7126C7326","name":"gift-outline","codepoint":"F02A1","aliases":["donate-outline","present-outline","package-outline"],"tags":["Shopping","Holiday"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4CB8AF2D-5373-4247-AB9D-3B28B72EB7BC","name":"git","codepoint":"F02A2","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"5C6175DD-8549-4004-AB77-A545D721A0DE","name":"github","codepoint":"F02A4","aliases":["microsoft-github"],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"6C0EA9E0-8F4F-40CB-A2B2-A2D84C97EE6A","name":"gitlab","codepoint":"F0BA0","aliases":[],"tags":[],"author":"Contributors","version":"3.0.39"},{"id":"9291BDB1-CE57-4802-8CD2-7AD2ED9D9959","name":"glass-cocktail","codepoint":"F0356","aliases":["local-bar","cocktail","martini","alcohol","bar","cup","drink"],"tags":["Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"5CB87909-09B4-47FD-B4BF-EB4A949F3CA2","name":"glass-cocktail-off","codepoint":"F15E6","aliases":[],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"CD1215BB-D889-4A86-8944-AF724C71DF21","name":"glass-flute","codepoint":"F02A5","aliases":["alcohol","cocktail","cup","drink"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9081982B-5EB6-47C1-A1F3-A83A0ED1B609","name":"glass-mug","codepoint":"F02A6","aliases":["pub","bar","beer","alcohol","cup","drink","local-bar"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BEAE85BE-708C-4D0D-82AE-370BB43B3D0D","name":"glass-mug-off","codepoint":"F15E7","aliases":[],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"04D0C33A-12E7-4DC1-96FA-A83A481962D4","name":"glass-mug-variant","codepoint":"F1116","aliases":["pub","bar","beer","drink","alcohol","cup","local-bar"],"tags":["Food \/ Drink"],"author":"Simran","version":"4.3.95"},{"id":"61B2CF99-322E-448E-A1DB-E27B94600BC4","name":"glass-mug-variant-off","codepoint":"F15E8","aliases":[],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"AFF2782E-A558-40EF-9B8C-787BAE055D57","name":"glass-pint-outline","codepoint":"F130D","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"4.8.95"},{"id":"E26942A0-61AE-4D1A-941C-895D92E94C5D","name":"glass-stange","codepoint":"F02A7","aliases":["alcohol","bar","cocktail","cup","drink"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"43E8B624-633D-472F-991E-4AEDB20A5454","name":"glass-tulip","codepoint":"F02A8","aliases":["bar","alcohol","cocktail","cup","drink"],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"0AF778AB-1048-4307-84AD-CB88D259DC02","name":"glass-wine","codepoint":"F0876","aliases":["bar","alcohol","cocktail","cup","drink"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"2.1.99"},{"id":"BE4C1227-C47E-4839-85AA-4EA6928BAAAE","name":"glasses","codepoint":"F02AA","aliases":[],"tags":["Clothing"],"author":"Simran","version":"1.5.54"},{"id":"A498671D-3C09-4874-B7BA-3F371208F4A0","name":"globe-light","codepoint":"F12D7","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"3E5EE2B1-AE6A-4675-BBAB-1D6B70FBFC36","name":"globe-model","codepoint":"F08E9","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"259F5EC9-395F-40C8-9389-6B6A82D9997C","name":"gmail","codepoint":"F02AB","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"2C4AF25A-8EC5-4B3B-BBCD-60F801F553B8","name":"gnome","codepoint":"F02AC","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"9E6D217A-874E-4295-9F85-9490FF14201C","name":"go-kart","codepoint":"F0D79","aliases":["cart"],"tags":["Sport"],"author":"Michael Richins","version":"3.4.93"},{"id":"04D32441-2FD3-4273-8C9A-D5C7BD1F261E","name":"go-kart-track","codepoint":"F0D7A","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"3B6D59D1-6329-4453-A11D-FB1D53B745F9","name":"gog","codepoint":"F0BA1","aliases":["gog-com"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"3.0.39"},{"id":"8B0AC7A2-11DB-43DF-96AF-D6193A2DCEFE","name":"gold","codepoint":"F124F","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.6.95"},{"id":"80A4F47A-3512-4C76-AA10-C0232C57E624","name":"golf","codepoint":"F0823","aliases":["golf-course"],"tags":["Sport"],"author":"Google","version":"2.1.19"},{"id":"70C7E562-43DC-4F7A-BF4C-77162406605A","name":"golf-cart","codepoint":"F11A4","aliases":[],"tags":["Sport","Transportation + Other"],"author":"Michael Richins","version":"4.5.95"},{"id":"A37545D0-964F-4975-A004-8EEF7CE91ED4","name":"golf-tee","codepoint":"F1083","aliases":[],"tags":["Sport"],"author":"Google","version":"4.2.95"},{"id":"9FE486F5-20A0-4CB5-A820-93AD82F52EB6","name":"gondola","codepoint":"F0686","aliases":["cable-car"],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"1.7.12"},{"id":"DECFD1E8-72A4-41F7-AF7F-68ED710AC1AD","name":"goodreads","codepoint":"F0D7B","aliases":[],"tags":[],"author":"Contributors","version":"3.4.93"},{"id":"F787FBCA-3C54-43CC-AE16-E23436AD0720","name":"google","codepoint":"F02AD","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"300B71B3-499A-4998-BA9D-22F2190229AA","name":"google-ads","codepoint":"F0C87","aliases":["google-adwords"],"tags":["Brand \/ Logo"],"author":"Google","version":"3.2.89"},{"id":"B328003D-F2FD-4C31-8171-BD6EB5A81A8A","name":"google-analytics","codepoint":"F07CC","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"2.0.46"},{"id":"3DD7794E-8603-49D0-B34E-DD0939225AAF","name":"google-assistant","codepoint":"F07CD","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"2.0.46"},{"id":"8CC1E909-6274-4738-AF1D-0E2C3239E853","name":"google-cardboard","codepoint":"F02AE","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"0B7D7D86-21E1-4759-8E4D-5D2BB291BB3F","name":"google-chrome","codepoint":"F02AF","aliases":["chromecast"],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"FAF03601-DED3-4AD2-B252-DF739AC96986","name":"google-circles","codepoint":"F02B0","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"073A8D2A-C834-4655-AA4F-792D7ADD7E6E","name":"google-circles-communities","codepoint":"F02B1","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"9ABBC701-54DE-48B3-A579-6FB3503F8929","name":"google-circles-extended","codepoint":"F02B2","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"00CC15EA-653E-4F50-B681-3176664F9B3C","name":"google-circles-group","codepoint":"F02B3","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"432C2FB2-AA01-40F8-AAB1-CB964967D3BD","name":"google-classroom","codepoint":"F02C0","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"14A23373-DFBF-443C-9143-90E6C78D144C","name":"google-cloud","codepoint":"F11F6","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"4.6.95"},{"id":"605CAD46-2EA0-47AE-8A41-953C1F27F9CD","name":"google-controller","codepoint":"F02B4","aliases":[],"tags":["Gaming \/ RPG"],"author":"Google","version":"1.5.54"},{"id":"8C28F332-2037-476E-8FAA-D5E6BC81D8B2","name":"google-controller-off","codepoint":"F02B5","aliases":[],"tags":["Gaming \/ RPG"],"author":"Google","version":"1.5.54"},{"id":"D9285386-5BA5-423A-8F3B-435E7A57363A","name":"google-downasaur","codepoint":"F1362","aliases":["dinosaur-pixel","t-rex","tyrannosaurus-rex"],"tags":["Animal","Gaming \/ RPG"],"author":"Simran","version":"4.9.95"},{"id":"EE98C0AD-0A55-4A6B-BB7A-01CBD3D819A2","name":"google-drive","codepoint":"F02B6","aliases":["attach-drive"],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"8A61F8F2-511B-45E9-9459-27BBD58936F8","name":"google-earth","codepoint":"F02B7","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"0BBD8E67-124A-4788-B44F-9583BC6E7503","name":"google-fit","codepoint":"F096C","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"2.4.85"},{"id":"6A73A89B-2C02-4DB5-89DF-0449750171BC","name":"google-glass","codepoint":"F02B8","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"3EA0D516-133D-4A5E-865B-82B7CC2763D5","name":"google-hangouts","codepoint":"F02C9","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"EEB46F1F-4996-4B65-A1C6-70DC4D38C34E","name":"google-home","codepoint":"F0824","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"2.1.19"},{"id":"73BACA3B-710C-4F23-9730-D88ADA3EA914","name":"google-keep","codepoint":"F06DC","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.8.36"},{"id":"BB7275FF-E0B1-4D63-8EF5-467F23BC5D33","name":"google-lens","codepoint":"F09F6","aliases":[],"tags":[],"author":"Google","version":"2.5.94"},{"id":"21FBF51C-0081-4987-8129-CFB0BB81729F","name":"google-maps","codepoint":"F05F5","aliases":[],"tags":["Navigation","Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"8DBB2A33-94F4-4676-95F2-F81D87C21FE1","name":"google-my-business","codepoint":"F1048","aliases":[],"tags":[],"author":"Google","version":"4.1.95"},{"id":"576EFEB3-D7E0-463F-A783-19A0F97D45EE","name":"google-nearby","codepoint":"F02B9","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A4C7D4DF-2B1F-424B-9502-6618F88C9A65","name":"google-photos","codepoint":"F06DD","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"5FE693A7-2A33-46A5-B502-D42588072E56","name":"google-play","codepoint":"F02BC","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"0D3A668A-E3B7-4512-B22D-10B13362DC2B","name":"google-plus","codepoint":"F02BD","aliases":[],"tags":["Brand \/ Logo","Social Media"],"author":"Google","version":"1.5.54"},{"id":"2C6E6048-97ED-4CA1-B8CE-31CEB31670C3","name":"google-podcast","codepoint":"F0EB9","aliases":[],"tags":[],"author":"Google","version":"3.7.94"},{"id":"837DFB0D-633B-4667-9C40-272186D68351","name":"google-spreadsheet","codepoint":"F09F7","aliases":[],"tags":[],"author":"Google","version":"2.5.94"},{"id":"EC38CB3D-A8A1-48E8-9A71-9BE93D6847FC","name":"google-street-view","codepoint":"F0C88","aliases":["pegman"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"DFF485C3-0A13-4546-A267-7687AF1AB82F","name":"google-translate","codepoint":"F02BF","aliases":["g-translate"],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"F10A05F8-FD09-4BDA-B906-747E9A89AB6E","name":"gradient","codepoint":"F06A0","aliases":[],"tags":[],"author":"Google","version":"1.7.12"},{"id":"D1784DB9-E2F2-44AA-AF8D-E562D8E3CBBC","name":"grain","codepoint":"F0D7C","aliases":[],"tags":["Photography","Video \/ Movie"],"author":"Google","version":"3.4.93"},{"id":"76AC59FA-C58D-4A55-AE8F-A351AF2CD43A","name":"graph","codepoint":"F1049","aliases":["dependency","dependencies"],"tags":[],"author":"Simran","version":"4.1.95"},{"id":"2B8A2BB1-0887-493F-A644-88015BFA507A","name":"graph-outline","codepoint":"F104A","aliases":["dependency","dependencies"],"tags":[],"author":"Simran","version":"4.1.95"},{"id":"50FEA1C7-FB0B-4920-BDA4-D56A87928A75","name":"graphql","codepoint":"F0877","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"8688646A-F06F-421F-83B1-8AA8FABF7BD8","name":"grass","codepoint":"F1510","aliases":["lawn"],"tags":["Nature","Agriculture"],"author":"Google","version":"5.4.55"},{"id":"4986CAC4-4886-4868-8D81-28F00376536A","name":"grave-stone","codepoint":"F0BA2","aliases":["headstone","tombstone","cemetery","graveyard"],"tags":["Holiday"],"author":"Austin Andrews","version":"3.0.39"},{"id":"137F01F1-86AC-4923-A9D7-C72057367BB7","name":"grease-pencil","codepoint":"F0648","aliases":[],"tags":["Drawing \/ Art"],"author":"Google","version":"1.6.50"},{"id":"8E839EA1-A50F-41C5-BB89-14904048B885","name":"greater-than","codepoint":"F096D","aliases":[],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"62C57FBE-8457-442F-AD8D-510CF2080FFF","name":"greater-than-or-equal","codepoint":"F096E","aliases":[],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"8D4C203D-A1F0-42DA-997A-AB7BAC63D97B","name":"grid","codepoint":"F02C1","aliases":["grid-on"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4A3863FA-620C-4564-8A7B-57681117B81D","name":"grid-large","codepoint":"F0758","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"4A8DDCEF-7E60-4864-9CC3-64C9A5B0D6D4","name":"grid-off","codepoint":"F02C2","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"22C8B00E-9BA8-4C66-994B-A2F0B4D369DD","name":"grill","codepoint":"F0E45","aliases":["bbq","barbecue","charcoal"],"tags":["Food \/ Drink"],"author":"Google","version":"3.6.95"},{"id":"36BD13EA-FFEC-48CF-855C-C30831680961","name":"grill-outline","codepoint":"F118A","aliases":["barbecue-outline","bbq-outline","charcoal-outline"],"tags":["Food \/ Drink"],"author":"Google","version":"4.4.95"},{"id":"D1B31666-9F9A-4CAB-843B-4BFEDBCC5347","name":"group","codepoint":"F02C3","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"C4015804-7FF3-4483-94CA-CEB79F7B34BC","name":"guitar-acoustic","codepoint":"F0771","aliases":[],"tags":["Music"],"author":"Haley Halcyon","version":"1.9.32"},{"id":"C2F16EBD-E72B-45E0-9A34-0BAF7ADB87B3","name":"guitar-electric","codepoint":"F02C4","aliases":[],"tags":["Music"],"author":"Haley Halcyon","version":"1.5.54"},{"id":"68377A86-6428-4553-B768-7E9FC306E962","name":"guitar-pick","codepoint":"F02C5","aliases":[],"tags":["Music"],"author":"Gabriel","version":"1.5.54"},{"id":"0FA22632-A0B2-49E0-A779-56022111C9D8","name":"guitar-pick-outline","codepoint":"F02C6","aliases":[],"tags":["Music"],"author":"Gabriel","version":"1.5.54"},{"id":"FDDC802D-37F5-4E15-96DA-8A6D553B1D67","name":"guy-fawkes-mask","codepoint":"F0825","aliases":[],"tags":[],"author":"Augustin Ursu","version":"2.1.19"},{"id":"B4AC04DD-9F29-4F55-ABB6-A4AE4F272EC4","name":"hail","codepoint":"F0AC1","aliases":["hail-taxi","hail-cab"],"tags":["Transportation + Road","Navigation"],"author":"Google","version":"2.7.94"},{"id":"57248AE7-78F7-4493-8909-5EA0A48821ED","name":"hair-dryer","codepoint":"F10EF","aliases":[],"tags":["Health \/ Beauty"],"author":"Michael Richins","version":"4.3.95"},{"id":"AC508D19-C3A8-4EC3-A46B-21F15DB6A8B1","name":"hair-dryer-outline","codepoint":"F10F0","aliases":[],"tags":["Health \/ Beauty"],"author":"Michael Richins","version":"4.3.95"},{"id":"CE482051-152D-4A7F-A696-74D8CD398FEF","name":"halloween","codepoint":"F0BA3","aliases":["pumpkin-face","pumpkin-carved","jack-o-lantern"],"tags":["Holiday"],"author":"Austin Andrews","version":"3.0.39"},{"id":"F5BC2290-D719-4974-9920-DF8E08E5F955","name":"hamburger","codepoint":"F0685","aliases":["burger","fast-food","food"],"tags":["Food \/ Drink"],"author":"Haley Halcyon","version":"1.7.12"},{"id":"A3F55E77-82C2-48F6-B1B1-92C9259C9C26","name":"hammer","codepoint":"F08EA","aliases":[],"tags":["Hardware \/ Tools"],"author":"Google","version":"2.3.50"},{"id":"CDD24BC0-E8F8-4B6E-B160-BC8DABC286A9","name":"hammer-screwdriver","codepoint":"F1322","aliases":["tools"],"tags":["Hardware \/ Tools"],"author":"Google","version":"4.9.95"},{"id":"86D5756B-DE86-4273-A475-4E2D9856B0C3","name":"hammer-wrench","codepoint":"F1323","aliases":["tools"],"tags":["Hardware \/ Tools"],"author":"Google","version":"4.9.95"},{"id":"C30FC465-2DF1-4716-AAC9-F48213F23D65","name":"hand","codepoint":"F0A4F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"5B605565-DBBC-4141-8B07-D8009B74D4E1","name":"hand-heart","codepoint":"F10F1","aliases":["volunteer","love","hope"],"tags":[],"author":"Google","version":"4.3.95"},{"id":"169736D6-CE5B-4143-A4A2-5D95088493F3","name":"hand-heart-outline","codepoint":"F157E","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"D2652D4F-E184-4BCC-A8A3-E53145D27911","name":"hand-left","codepoint":"F0E46","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"F81DD09B-46EB-466D-A0E3-DE4CAEC86793","name":"hand-okay","codepoint":"F0A50","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"19740ECA-C3A2-49D1-B7BA-91C97EA150D7","name":"hand-peace","codepoint":"F0A51","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"1B7E8570-378E-4099-9683-505B4E2744EA","name":"hand-peace-variant","codepoint":"F0A52","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"1D015884-E9B8-401E-8931-E2DA1604BF1B","name":"hand-pointing-down","codepoint":"F0A53","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"26BC12CA-4558-4C45-BBDB-04BE1E13E814","name":"hand-pointing-left","codepoint":"F0A54","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"C18F21E1-2363-42DD-8FFF-3381AC368C23","name":"hand-pointing-right","codepoint":"F02C7","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"457F3CB5-7B39-417F-A1CE-D1DB5A22159D","name":"hand-pointing-up","codepoint":"F0A55","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"35FBF26D-56C0-4699-A2A8-19BC2C37D6AF","name":"hand-right","codepoint":"F0E47","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"A0B645B5-20F6-4682-9E88-96784D8732CF","name":"hand-saw","codepoint":"F0E48","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"4C201756-1101-4C58-9FBE-5F781347F535","name":"hand-wash","codepoint":"F157F","aliases":[],"tags":["Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"C5EA3223-8736-4F38-82A1-B3FC5F206879","name":"hand-wash-outline","codepoint":"F1580","aliases":[],"tags":["Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"C3BBE9FF-7FF7-4C8F-8185-A8F3825F3CAE","name":"hand-water","codepoint":"F139F","aliases":["hand-wash"],"tags":["Medical \/ Hospital"],"author":"Moma Design Studio","version":"5.0.45"},{"id":"845C7000-7198-490F-8043-EC1F61CE4F53","name":"handball","codepoint":"F0F53","aliases":["volleyball"],"tags":["Sport"],"author":"Google","version":"3.9.97"},{"id":"1451F3F4-D421-4A26-A22D-0ED80A815DF6","name":"handcuffs","codepoint":"F113E","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"A41E35E2-6756-46D9-BE48-4DFA705A6A6A","name":"handshake","codepoint":"F1218","aliases":["business","deal","help","partnership"],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"11A33144-9847-4ED2-A429-682B79AAE06F","name":"handshake-outline","codepoint":"F15A1","aliases":["business-outline","deal-outline","help-outline","partnership-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"2FB0994B-BBA8-4F59-93AF-87F2065F34EA","name":"hanger","codepoint":"F02C8","aliases":["coat-hanger","clothes-hanger"],"tags":["Clothing"],"author":"Moma Design Studio","version":"1.5.54"},{"id":"C0F69308-03DA-446D-9B7F-A5B2B5BF1D90","name":"hard-hat","codepoint":"F096F","aliases":["helmet"],"tags":["Hardware \/ Tools","Clothing"],"author":"Michael Richins","version":"2.4.85"},{"id":"6CBB2398-E7ED-4A08-8489-1FFF87D0605C","name":"harddisk","codepoint":"F02CA","aliases":["hdd"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"C4EE3559-8772-4A8D-A549-A1A11DEEC830","name":"harddisk-plus","codepoint":"F104B","aliases":["hdd-plus"],"tags":[],"author":"Michael Richins","version":"4.1.95"},{"id":"07449A81-73AE-484C-8739-E008C38502F1","name":"harddisk-remove","codepoint":"F104C","aliases":["hdd-remove"],"tags":[],"author":"Michael Richins","version":"4.1.95"},{"id":"65EED4C7-8306-4688-83ED-7D1D527B39AB","name":"hat-fedora","codepoint":"F0BA4","aliases":[],"tags":["Clothing"],"author":"Google","version":"3.0.39"},{"id":"AEB30C8D-5159-4897-8D17-6EFB9715D3CD","name":"hazard-lights","codepoint":"F0C89","aliases":["warning-lights"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"81182C14-380B-4F56-AFF9-EF636EC7BF7E","name":"hdr","codepoint":"F0D7D","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"D0ACA2D8-09A4-4C13-81FE-26F7D9C617E5","name":"hdr-off","codepoint":"F0D7E","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"6C83ACD1-95E8-4DE0-837A-4C66E07533DD","name":"head","codepoint":"F135E","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"783B2BB8-1ECA-4E19-8F45-9FCC8D749F99","name":"head-alert","codepoint":"F1338","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"BF11BF96-445C-478B-8A66-ECBD839415EA","name":"head-alert-outline","codepoint":"F1339","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"E10C1F47-D7CB-458A-A374-467CF9462045","name":"head-check","codepoint":"F133A","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"0A0ADE26-77AE-4BC3-8F9D-3D25669197FE","name":"head-check-outline","codepoint":"F133B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"58C540DF-30BA-449B-8426-61AD2C43959D","name":"head-cog","codepoint":"F133C","aliases":["psychology"],"tags":["Settings"],"author":"Google","version":"4.9.95"},{"id":"C4C50873-9844-42F6-A37B-16FE905873D9","name":"head-cog-outline","codepoint":"F133D","aliases":["psychology-outline"],"tags":["Settings"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"DE191219-96D0-4189-8BE1-8F24A5E3E492","name":"head-dots-horizontal","codepoint":"F133E","aliases":["head-thinking"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"E07B33BA-5E14-45A2-AE38-EA80CE0ED909","name":"head-dots-horizontal-outline","codepoint":"F133F","aliases":["head-thinking-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"86AC6B0F-62ED-4691-88DB-A95DF86CBFF9","name":"head-flash","codepoint":"F1340","aliases":["head-ache"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"28D19749-AD74-4017-B4B1-AFA65AA7B47F","name":"head-flash-outline","codepoint":"F1341","aliases":["head-ache-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"619BBE2E-46B1-4FC8-91CF-13FE138FC601","name":"head-heart","codepoint":"F1342","aliases":["head-love"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"0DA85FAF-88F1-4DF1-8DA6-CB3CEFA2A505","name":"head-heart-outline","codepoint":"F1343","aliases":["head-love-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"A94C16AE-DBA8-4DC4-B52E-589D1605C765","name":"head-lightbulb","codepoint":"F1344","aliases":["head-idea","head-bulb"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"A7FCF7AB-00BF-404B-8AF6-B384B034B6F7","name":"head-lightbulb-outline","codepoint":"F1345","aliases":["head-idea-outline","head-bulb-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"ACE0E86B-603A-4B3A-9AF5-D6C2F3B4F121","name":"head-minus","codepoint":"F1346","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"9550EB76-4099-4179-9310-339C2D7B0358","name":"head-minus-outline","codepoint":"F1347","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"FC339D79-C2E3-4F70-BDEE-E8DB99E06050","name":"head-outline","codepoint":"F135F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"84EDC185-89D4-4F6A-9C28-9911ADA41950","name":"head-plus","codepoint":"F1348","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"FDEA8867-C576-4065-87D9-945ADE51C543","name":"head-plus-outline","codepoint":"F1349","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"1E4E72A9-FC83-4971-8B21-4FCACC4DD679","name":"head-question","codepoint":"F134A","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"B396941C-27C0-4386-96AF-D0AB15842EC2","name":"head-question-outline","codepoint":"F134B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"277090C1-C626-4DA8-B620-1A709668E5BA","name":"head-remove","codepoint":"F134C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"7BB28522-3861-439B-A804-D86C580A8FCB","name":"head-remove-outline","codepoint":"F134D","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"9EB1D22F-C7FC-43FB-8689-40AB3FFB98E7","name":"head-snowflake","codepoint":"F134E","aliases":["head-freeze","brain-freeze"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"C7A97A26-B7C3-406A-9087-2463AC624926","name":"head-snowflake-outline","codepoint":"F134F","aliases":["head-freeze-outline","brain-freeze-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"CB0FD2AA-6EA8-4324-8207-6C4FFCCB5143","name":"head-sync","codepoint":"F1350","aliases":["head-reload","head-refresh"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"8EC8806B-0E06-4EA4-915E-C061D4930ECC","name":"head-sync-outline","codepoint":"F1351","aliases":["head-reload-outline","head-refresh-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"51F72F83-1559-4037-8BF9-2D8AE3BCB1A8","name":"headphones","codepoint":"F02CB","aliases":["headset"],"tags":["Audio","Device \/ Tech","Music"],"author":"Google","version":"1.5.54"},{"id":"B14FD2A1-C292-49CC-B0AC-78E22C2BD611","name":"headphones-bluetooth","codepoint":"F0970","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"5B608320-1BEB-499C-9CAB-0897D3A2D2B6","name":"headphones-box","codepoint":"F02CC","aliases":[],"tags":["Audio","Music"],"author":"Google","version":"1.5.54"},{"id":"678F779A-DE83-4DC0-A49D-657CBAF631F0","name":"headphones-off","codepoint":"F07CE","aliases":[],"tags":["Audio","Device \/ Tech","Music"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"54A22337-9D03-4F52-8D3E-B2A0A32147B7","name":"headphones-settings","codepoint":"F02CD","aliases":[],"tags":["Audio","Settings"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AFF98802-E02B-4EC8-8AFF-F0F5373D86C5","name":"headset","codepoint":"F02CE","aliases":["headset-mic"],"tags":["Audio","Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"36F33522-9167-42DD-BA0A-8920F480F38C","name":"headset-dock","codepoint":"F02CF","aliases":[],"tags":["Audio"],"author":"Chris Litherland","version":"1.5.54"},{"id":"E2A86F6D-6E4D-4C61-B54A-85BEDACA052F","name":"headset-off","codepoint":"F02D0","aliases":[],"tags":["Audio","Device \/ Tech"],"author":"Austin Andrews","version":"1.5.54"},{"id":"32B56DB2-B6BF-4B54-AD0C-9444106B1C1D","name":"heart","codepoint":"F02D1","aliases":["favorite","favourite"],"tags":["Shape","Gaming \/ RPG","Medical \/ Hospital"],"author":"Google","version":"1.5.54"},{"id":"558E28AE-47E7-4C95-9846-7653C79CBA33","name":"heart-box","codepoint":"F02D2","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"24811FE6-6C95-4CAB-B708-71862BA40C05","name":"heart-box-outline","codepoint":"F02D3","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"64D15AD4-07A4-4D43-8730-6C9860C89B44","name":"heart-broken","codepoint":"F02D4","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"365602DD-C53F-42AC-AE3E-2058F47B5C53","name":"heart-broken-outline","codepoint":"F0D14","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"2EFEF959-D5E7-4E69-863D-4E12C413A6D9","name":"heart-circle","codepoint":"F0971","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"DD5AC3DA-1CA0-4F53-9A50-C095417D7346","name":"heart-circle-outline","codepoint":"F0972","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"759FA294-1DB6-4B54-BA13-AD852764E3C9","name":"heart-cog","codepoint":"F1663","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"A28DF1A9-5A1F-49AB-959D-249313639228","name":"heart-cog-outline","codepoint":"F1664","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"9B033C3C-210D-4EFD-AD4E-FF9E36E44509","name":"heart-flash","codepoint":"F0EF9","aliases":["aed","defibrillator"],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"1B01BAE0-095E-424E-9552-6ECEF5E4FC62","name":"heart-half","codepoint":"F06DF","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.8.36"},{"id":"0FC24699-3C95-4319-A60B-286B0D328D7A","name":"heart-half-full","codepoint":"F06DE","aliases":[],"tags":["Gaming \/ RPG"],"author":"Case Sandberg","version":"1.8.36"},{"id":"F4384972-741C-4BB6-91BF-9509E75C8AF8","name":"heart-half-outline","codepoint":"F06E0","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.8.36"},{"id":"3FD1EF68-1D57-436E-9EF5-D6721DCCF5CF","name":"heart-minus","codepoint":"F142F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"12C099C0-0232-49B7-A909-F91594FD7FBA","name":"heart-minus-outline","codepoint":"F1432","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"BDAF5217-358E-4673-BF16-FFFBD09EAD8F","name":"heart-multiple","codepoint":"F0A56","aliases":["hearts"],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"A4672312-BF75-4CE0-88FF-C7D3BC724AA0","name":"heart-multiple-outline","codepoint":"F0A57","aliases":["hearts-outline"],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"012A92C0-E5DE-4FB4-9AB1-9BD5F53861E0","name":"heart-off","codepoint":"F0759","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"E84E6A73-A238-4F6D-9A63-658358BB4A06","name":"heart-off-outline","codepoint":"F1434","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"9BCD22D2-7304-4BB3-9C41-3431ED13542A","name":"heart-outline","codepoint":"F02D5","aliases":["favorite-border","favourite-border","favorite-outline","favourite-outline"],"tags":["Shape","Gaming \/ RPG"],"author":"Google","version":"1.5.54"},{"id":"412C8571-A7A4-4029-B5D4-7C67D2B243CC","name":"heart-plus","codepoint":"F142E","aliases":[],"tags":[],"author":"Simran","version":"5.2.45"},{"id":"644CF687-E873-46D4-9595-FF3F1C455861","name":"heart-plus-outline","codepoint":"F1431","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"389486F3-5A73-4C65-8EA6-43D432F6490E","name":"heart-pulse","codepoint":"F05F6","aliases":["heart-vitals"],"tags":["Medical \/ Hospital"],"author":"Google","version":"1.5.54"},{"id":"B01C8EB2-7765-4858-846F-078ADBFDD33B","name":"heart-remove","codepoint":"F1430","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"3FB606F6-D5C4-4036-80D0-EFD3F8A0E06B","name":"heart-remove-outline","codepoint":"F1433","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"E0A4635A-2115-425E-8103-4C88CBDB10F3","name":"heart-settings","codepoint":"F1665","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"9B32C2D5-B2BE-4646-9C41-53F10F7C1628","name":"heart-settings-outline","codepoint":"F1666","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"47397A0C-273D-4D13-A4FD-61572F3E4953","name":"helicopter","codepoint":"F0AC2","aliases":[],"tags":["Transportation + Flying"],"author":"Contributors","version":"2.7.94"},{"id":"62675A10-D453-40EB-8AED-A789A39EEF11","name":"help","codepoint":"F02D6","aliases":["question-mark"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"6EFBBE96-37EA-4372-98CC-9B0D84B92C34","name":"help-box","codepoint":"F078B","aliases":["question-mark-box"],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"49B41103-DD15-4FF4-A18A-44D8586704B6","name":"help-circle","codepoint":"F02D7","aliases":["question-mark-circle"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"60E15D8D-3956-4461-91D8-E8059D02ECE6","name":"help-circle-outline","codepoint":"F0625","aliases":["help-outline","question-mark-circle-outline"],"tags":[],"author":"Google","version":"1.6.50"},{"id":"FE0A3DAC-0D3D-4D49-A869-F78B44B26E35","name":"help-network","codepoint":"F06F5","aliases":["question-network"],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"918BA71B-ED4F-4259-9089-0CF2A1EDCFD1","name":"help-network-outline","codepoint":"F0C8A","aliases":["question-network-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"FC7F2A59-0296-45CC-966D-EF69FB042DD9","name":"help-rhombus","codepoint":"F0BA5","aliases":["question-mark-rhombus"],"tags":[],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"B08F035A-9304-4D3B-AADD-395971E74294","name":"help-rhombus-outline","codepoint":"F0BA6","aliases":["question-mark-rhombus-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"4FB1FDA2-96F8-4983-83B9-470C1526042F","name":"hexadecimal","codepoint":"F12A7","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"229D267D-F77F-4F33-ADD4-325647EC2662","name":"hexagon","codepoint":"F02D8","aliases":[],"tags":["Shape"],"author":"Austin Andrews","version":"1.5.54"},{"id":"60636193-AC27-470B-BCA5-94CEA29719A8","name":"hexagon-multiple","codepoint":"F06E1","aliases":["hexagons"],"tags":["Shape"],"author":"Austin Andrews","version":"1.8.36"},{"id":"D0D73659-5BB0-4109-A7E1-E4B09D31B940","name":"hexagon-multiple-outline","codepoint":"F10F2","aliases":[],"tags":["Nature"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"0A85BE3F-ACF1-4D93-A66B-34C7F29D10A3","name":"hexagon-outline","codepoint":"F02D9","aliases":[],"tags":["Shape"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6FD9B907-A06F-4923-9ABB-C977E8F14D0E","name":"hexagon-slice-1","codepoint":"F0AC3","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"B711E5EB-95CC-4835-A18A-066E1A242DB5","name":"hexagon-slice-2","codepoint":"F0AC4","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"0F1666BA-D919-4230-96C9-6DD64A82EB3D","name":"hexagon-slice-3","codepoint":"F0AC5","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"4AD333BE-32D1-4EA2-BA76-05896A9D2698","name":"hexagon-slice-4","codepoint":"F0AC6","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"4DE91E6B-4F94-40E8-BB70-2B54105C67D0","name":"hexagon-slice-5","codepoint":"F0AC7","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"0EE5E66B-A73E-455F-BF0B-5FEBC93A58E9","name":"hexagon-slice-6","codepoint":"F0AC8","aliases":[],"tags":[],"author":"SarinManS","version":"2.7.94"},{"id":"A965D069-BF40-4F96-B64D-6C1C93F0E2E3","name":"hexagram","codepoint":"F0AC9","aliases":["star"],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"C1F53791-B46C-4327-B355-AF3175766CB8","name":"hexagram-outline","codepoint":"F0ACA","aliases":["star-outline"],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"8FC812E7-2B7B-412B-9114-1899203DECC4","name":"high-definition","codepoint":"F07CF","aliases":["hd"],"tags":["Video \/ Movie"],"author":"Austin Andrews","version":"2.0.46"},{"id":"BD1F0404-AA98-4FCF-8947-D0589C91A610","name":"high-definition-box","codepoint":"F0878","aliases":["hd-box","hd"],"tags":["Video \/ Movie"],"author":"Google","version":"2.1.99"},{"id":"81E5D79D-2ECD-4040-9B07-3A0C19792348","name":"highway","codepoint":"F05F7","aliases":["autobahn","motorway"],"tags":["Transportation + Road"],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"DA3D64F2-C874-420A-917A-0F66C9854D84","name":"hiking","codepoint":"F0D7F","aliases":[],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"F1EE1708-7EAF-4929-97AA-D4BAC093D157","name":"hinduism","codepoint":"F0973","aliases":["religion-hindu","om"],"tags":["Religion"],"author":"Nick","version":"2.4.85"},{"id":"55AF2D53-7FAD-4A1D-8440-10301C95D3B8","name":"history","codepoint":"F02DA","aliases":["recent","latest","clock-arrow","counterclockwise","restore-clock"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"7A41C6CC-578B-4125-9647-548A298D5B3C","name":"hockey-puck","codepoint":"F0879","aliases":[],"tags":["Sport"],"author":"Nick","version":"2.1.99"},{"id":"1D4E526E-EA07-4493-AF7D-C9B62B4CBC77","name":"hockey-sticks","codepoint":"F087A","aliases":[],"tags":["Sport"],"author":"Nick","version":"2.1.99"},{"id":"826E9B16-2A0D-4E8C-9C3A-BBBE3319AE4D","name":"hololens","codepoint":"F02DB","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5D085274-15B9-42EC-8CCE-2F94C5EC039C","name":"home","codepoint":"F02DC","aliases":["house"],"tags":["Home Automation","Places"],"author":"Google","version":"1.5.54"},{"id":"9A7BCD6C-B4FB-4AE5-B22F-C5B8E2FB3B66","name":"home-account","codepoint":"F0826","aliases":["home-user"],"tags":["Account \/ User","Home Automation"],"author":"GreenTurtwig","version":"2.1.19"},{"id":"A13368F4-66F6-4014-968E-7A7B2D99F038","name":"home-alert","codepoint":"F087B","aliases":["home-warning"],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Richins","version":"2.1.99"},{"id":"0A46973B-0029-4BCF-9728-F3E13DC9FE91","name":"home-alert-outline","codepoint":"F15D0","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"381A61B9-0D73-4CB8-B525-C67697443F43","name":"home-analytics","codepoint":"F0EBA","aliases":["chart-home","home-chart"],"tags":["Home Automation"],"author":"Michael Richins","version":"3.7.94"},{"id":"80923357-29F3-429E-A186-F3561451398C","name":"home-assistant","codepoint":"F07D0","aliases":[],"tags":["Brand \/ Logo","Home Automation"],"author":"Contributors","version":"2.0.46"},{"id":"FD2567BF-09EC-4871-B3E8-DAE9CDCF3A38","name":"home-automation","codepoint":"F07D1","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"59CB69E0-6F23-4572-90C7-9B360121C266","name":"home-circle","codepoint":"F07D2","aliases":["house-circle"],"tags":["Home Automation"],"author":"Contributors","version":"2.0.46"},{"id":"2AD26260-A0C1-42BE-99A2-889F460EF25D","name":"home-circle-outline","codepoint":"F104D","aliases":["house-circle-outline"],"tags":["Home Automation"],"author":"Terren","version":"4.1.95"},{"id":"4D49A420-B80E-48FA-A331-A556002EA46F","name":"home-city","codepoint":"F0D15","aliases":["house-city"],"tags":[],"author":"Google","version":"3.3.92"},{"id":"69A854BB-0CC9-4E1B-855E-FD26E9E6D119","name":"home-city-outline","codepoint":"F0D16","aliases":["house-city-outline"],"tags":[],"author":"Google","version":"3.3.92"},{"id":"21C7383B-5839-4F3E-A4EC-81A9980F531B","name":"home-currency-usd","codepoint":"F08AF","aliases":[],"tags":["Banking"],"author":"Nick","version":"2.2.43","deprecated":true},{"id":"6D381D99-24F0-46B5-AD04-F527B97830AE","name":"home-edit","codepoint":"F1159","aliases":[],"tags":["Home Automation","Edit \/ Modify"],"author":"Simran","version":"4.4.95"},{"id":"B56AB73F-0A3C-4562-88DF-ED70B51877DE","name":"home-edit-outline","codepoint":"F115A","aliases":[],"tags":["Home Automation","Edit \/ Modify"],"author":"Simran","version":"4.4.95"},{"id":"6D0FFE6B-65D9-4D72-9743-C2537F3E6307","name":"home-export-outline","codepoint":"F0F9B","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"AC4506FC-3368-416C-8E9A-BADD6F66E7D5","name":"home-flood","codepoint":"F0EFA","aliases":[],"tags":["Weather","Home Automation"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"6732D314-97CA-4433-9CB5-260359AC131F","name":"home-floor-0","codepoint":"F0DD2","aliases":["house-floor-0","home-floor-zero","house-floor-zero"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"B83F1FBD-0D66-4CEE-91FC-640B78AABF4E","name":"home-floor-1","codepoint":"F0D80","aliases":["house-floor-1","home-floor-one","house-floor-one","home-floor-first","house-floor-first"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.4.93"},{"id":"FB09500A-A871-409C-B7D4-B18BDF0D8511","name":"home-floor-2","codepoint":"F0D81","aliases":["house-floor-2","home-floor-two","house-floor-two","home-floor-second","house-floor-second"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.4.93"},{"id":"E7714A6B-EE3B-4819-81B8-1E9FF342598F","name":"home-floor-3","codepoint":"F0D82","aliases":["house-floor-3","home-floor-three","house-floor-three","home-floor-third","house-floor-third"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.4.93"},{"id":"5A227D09-2828-4606-81B8-7622D7C8724C","name":"home-floor-a","codepoint":"F0D83","aliases":["home-floor-attic","house-floor-a","house-floor-attic"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.4.93"},{"id":"004E747A-FD00-4B6E-8AEF-2031D217D035","name":"home-floor-b","codepoint":"F0D84","aliases":["home-floor-basement","house-floor-b","house-floor-basement"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.4.93"},{"id":"B2D19D07-ACC6-462B-BD11-50CC805E104B","name":"home-floor-g","codepoint":"F0D85","aliases":["home-floor-ground","house-floor-g","house-floor-ground"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.4.93"},{"id":"D6B418D4-1B34-4E5C-B406-0E27B72DC0AC","name":"home-floor-l","codepoint":"F0D86","aliases":["home-floor-loft","home-floor-lower","house-floor-l","house-floor-loft","house-floor-lower"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.4.93"},{"id":"8809DA4E-CB12-48C9-AA91-8E377701862F","name":"home-floor-negative-1","codepoint":"F0DD3","aliases":["house-floor-negative-1","home-floor-negative-one","home-floor-minus-1","home-floor-minus-one","house-floor-negative-one","house-floor-minus-1","house-floor-minus-one"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"B4E54DBF-164E-41D3-8C9F-D7E67C9F9B10","name":"home-group","codepoint":"F0DD4","aliases":["house-group","neighbourhood","estate","housing-estate"],"tags":["Home Automation"],"author":"Michael Richins","version":"3.5.94"},{"id":"513D2CF1-31F5-4F3B-8543-2499ABB20924","name":"home-heart","codepoint":"F0827","aliases":["family"],"tags":["Home Automation","People \/ Family"],"author":"Google","version":"2.1.19"},{"id":"041C4C4F-6D85-4F8B-90CC-FB17E9202862","name":"home-import-outline","codepoint":"F0F9C","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"06C5C86B-2918-4501-B247-890B18874E8E","name":"home-lightbulb","codepoint":"F1251","aliases":["home-bulb"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.6.95"},{"id":"5F0E0727-76E9-4793-9406-FD513FF7CB58","name":"home-lightbulb-outline","codepoint":"F1252","aliases":["home-bulb-outline"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.6.95"},{"id":"ECB8FF23-47EC-4038-9673-1A3A1619C071","name":"home-lock","codepoint":"F08EB","aliases":[],"tags":["Home Automation","Lock"],"author":"Nick","version":"2.3.50"},{"id":"0E63785D-BB37-4A60-B09D-F985DC4FAD5F","name":"home-lock-open","codepoint":"F08EC","aliases":[],"tags":["Home Automation","Lock"],"author":"Nick","version":"2.3.50"},{"id":"D543BDC6-BC40-4A36-B2F0-60313D8F4EEB","name":"home-map-marker","codepoint":"F05F8","aliases":["house-map-marker"],"tags":["Home Automation","Navigation"],"author":"Simran","version":"1.5.54"},{"id":"825AF439-6839-48DA-A6D4-B62BB2710103","name":"home-minus","codepoint":"F0974","aliases":[],"tags":["Home Automation"],"author":"Peter Noble","version":"2.4.85"},{"id":"8DB9C230-99DF-4137-9A32-2D1058D824EA","name":"home-minus-outline","codepoint":"F13D5","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"6949FE9A-5B8C-4EDF-B74E-E0268A4F69F1","name":"home-modern","codepoint":"F02DD","aliases":["house-modern"],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B4E2287E-8872-48AD-B765-83D82AF66CA3","name":"home-outline","codepoint":"F06A1","aliases":["house-outline"],"tags":["Home Automation"],"author":"Google","version":"1.7.12"},{"id":"E844FA32-E45E-4D71-B74C-34DFAD7F6830","name":"home-plus","codepoint":"F0975","aliases":["home-add"],"tags":["Home Automation"],"author":"Peter Noble","version":"2.4.85"},{"id":"CDAF170C-BB2C-4217-9B96-D99EE9B725F9","name":"home-plus-outline","codepoint":"F13D6","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"FEF8AC85-F9E6-4C9B-B0C2-A5158AAD8A8B","name":"home-remove","codepoint":"F1247","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"CD3129FD-EDCB-4B65-85F8-900E59E308B7","name":"home-remove-outline","codepoint":"F13D7","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"32EF139A-14EB-4767-ADDD-08120FB530A0","name":"home-roof","codepoint":"F112B","aliases":["home-chimney"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"156F3CF1-D7CD-487B-AF83-4A7270413A62","name":"home-search","codepoint":"F13B0","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.0.45"},{"id":"D261AFB1-2C65-41D6-AE5A-E25D2FC120ED","name":"home-search-outline","codepoint":"F13B1","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.0.45"},{"id":"833E3484-3C40-4F98-96CB-537FB6225711","name":"home-thermometer","codepoint":"F0F54","aliases":["home-climate","home-temperature"],"tags":["Home Automation"],"author":"Contributors","version":"3.9.97"},{"id":"2782AA6E-C46A-4CEC-B753-35768CA30163","name":"home-thermometer-outline","codepoint":"F0F55","aliases":["home-climate-outline","home-temperature-outline"],"tags":["Home Automation"],"author":"Contributors","version":"3.9.97"},{"id":"7AFA8EEF-6A41-4A7D-97D2-F9F03DB24DB0","name":"home-variant","codepoint":"F02DE","aliases":["house-variant"],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"5DF1214D-79EC-4EA0-B435-CB73B877DCA9","name":"home-variant-outline","codepoint":"F0BA7","aliases":["house-variant-outline"],"tags":["Home Automation"],"author":"Google","version":"3.0.39"},{"id":"8A2A8364-B33C-4931-BF78-EB171C569D5F","name":"hook","codepoint":"F06E2","aliases":[],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"984487C2-EBB2-474C-8914-046E6BDC6EC6","name":"hook-off","codepoint":"F06E3","aliases":[],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"E82A026A-DD54-4C5F-8961-A7C97754CF04","name":"hops","codepoint":"F02DF","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"7B242778-9748-4E06-8738-E3325EE88F08","name":"horizontal-rotate-clockwise","codepoint":"F10F3","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"C6DC8E07-B9BA-4F4E-B415-40AAD8AE17A4","name":"horizontal-rotate-counterclockwise","codepoint":"F10F4","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"EA8A87CE-C2FE-4C05-8CD0-32C9716737D4","name":"horse","codepoint":"F15BF","aliases":[],"tags":["Transportation + Other","Animal"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"784CE1E7-3523-4E04-910C-3E969FEA4E55","name":"horse-human","codepoint":"F15C0","aliases":["horseback-riding","horse-riding","equestrian"],"tags":["Transportation + Other"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"359CB8BA-79AF-43F7-AE85-562432388C2E","name":"horse-variant","codepoint":"F15C1","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"1955609E-8F53-41B3-9C71-0A71E4FBEED3","name":"horseshoe","codepoint":"F0A58","aliases":["luck"],"tags":["Sport"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"D7402851-FBF5-4861-8B6E-D141EBBDBB70","name":"hospital","codepoint":"F0FF6","aliases":["swiss-cross","dispensary"],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"83D0E9E7-B196-4515-A9C8-6E6FEB03ADD1","name":"hospital-box","codepoint":"F02E0","aliases":["local-hospital","swiss-cross-box","dispensary-box"],"tags":["Medical \/ Hospital"],"author":"Google","version":"1.5.54"},{"id":"2D50B6E0-C01B-4EDE-BA85-A14757A27D54","name":"hospital-box-outline","codepoint":"F0FF7","aliases":["swiss-cross-box-outline","dispensary-box-outline"],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"D4FAA416-4429-451F-B4EE-647CCABDF3EB","name":"hospital-building","codepoint":"F02E1","aliases":[],"tags":["Places","Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FA30BC13-BE77-44F6-BEB1-942749E019A7","name":"hospital-marker","codepoint":"F02E2","aliases":[],"tags":["Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"832FBA55-F65E-4706-93B1-9018D651CAA3","name":"hot-tub","codepoint":"F0828","aliases":[],"tags":[],"author":"Google","version":"2.1.19"},{"id":"0AAC6125-3343-4D4A-AF22-69BC930FA96F","name":"hours-24","codepoint":"F1478","aliases":[],"tags":["Date \/ Time"],"author":"Haley Halcyon","version":"5.2.45"},{"id":"04125F27-F2CB-4304-8C9D-81E4D72A0B6E","name":"hubspot","codepoint":"F0D17","aliases":[],"tags":[],"author":"Contributors","version":"3.3.92"},{"id":"788D7C34-3E50-468B-A205-D953D844F1B7","name":"hulu","codepoint":"F0829","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.19"},{"id":"B05E458D-886A-491D-9969-156562C52105","name":"human","codepoint":"F02E6","aliases":["accessibility"],"tags":["People \/ Family"],"author":"Google","version":"1.5.54"},{"id":"CF40C1CD-0F3A-4BC7-A1D7-7C33C8EFD307","name":"human-baby-changing-table","codepoint":"F138B","aliases":[],"tags":["People \/ Family","Medical \/ Hospital"],"author":"Moma Design Studio","version":"5.0.45"},{"id":"40DD914F-1089-4A7B-AA3D-630C643E8FFF","name":"human-cane","codepoint":"F1581","aliases":["elderly"],"tags":["Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"98227CA7-A56F-4C3F-85FC-0FAD616B9762","name":"human-capacity-decrease","codepoint":"F159B","aliases":["human-capacity-reduce"],"tags":["Account \/ User","Transportation + Other","People \/ Family"],"author":"Google","version":"5.5.55"},{"id":"AFFFC442-E5B7-4D2C-9B87-81D2AD52997A","name":"human-capacity-increase","codepoint":"F159C","aliases":[],"tags":["Account \/ User","Transportation + Other","People \/ Family"],"author":"Simran","version":"5.5.55"},{"id":"ABBC3761-B437-4800-9C57-BCBE5AC8FA31","name":"human-child","codepoint":"F02E7","aliases":[],"tags":["People \/ Family"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1B83707C-D3DF-4181-93D5-5B513B649E1C","name":"human-edit","codepoint":"F14E8","aliases":[],"tags":["People \/ Family","Edit \/ Modify"],"author":"Austin Andrews","version":"5.4.55"},{"id":"059421A9-4F27-493A-8835-4B49B5286366","name":"human-female","codepoint":"F0649","aliases":["woman"],"tags":["People \/ Family"],"author":"Google","version":"1.6.50"},{"id":"6FAD3199-1AC7-4265-84B0-E72818AD2447","name":"human-female-boy","codepoint":"F0A59","aliases":["mother","mom","woman-child","mum"],"tags":["People \/ Family"],"author":"Henrique C\u00e9sar Madeira","version":"2.6.95"},{"id":"DCBC03CA-8A3A-41FD-9C96-BA738EDA9F05","name":"human-female-dance","codepoint":"F15C9","aliases":["ballet"],"tags":[],"author":"Michael Richins","version":"5.6.55"},{"id":"63BC56A3-B593-4789-BEAE-2696E6DC2CB6","name":"human-female-female","codepoint":"F0A5A","aliases":["woman-woman","women"],"tags":["People \/ Family"],"author":"Henrique C\u00e9sar Madeira","version":"2.6.95"},{"id":"0F41B01E-9981-4BF8-8CC9-A44593ECB3BA","name":"human-female-girl","codepoint":"F0A5B","aliases":["mother","mom","woman-child","mum"],"tags":["People \/ Family"],"author":"Henrique C\u00e9sar Madeira","version":"2.6.95"},{"id":"1C9856E1-6945-464E-85E7-A46C4A974C9D","name":"human-greeting","codepoint":"F064A","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"1.6.50"},{"id":"200F7489-F20F-4506-A27A-081A0CA8A312","name":"human-greeting-proximity","codepoint":"F159D","aliases":["connect-without-contact"],"tags":["Account \/ User","People \/ Family"],"author":"Google","version":"5.5.55"},{"id":"10E7CAB4-7B15-4F73-82B1-E42562B9103C","name":"human-handsdown","codepoint":"F064B","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"1.6.50"},{"id":"FA427178-750A-425C-81F2-B46DDC061771","name":"human-handsup","codepoint":"F064C","aliases":[],"tags":["People \/ Family"],"author":"Google","version":"1.6.50"},{"id":"1369FF9C-0E57-4644-BE89-7B5EED0131B0","name":"human-male","codepoint":"F064D","aliases":["man"],"tags":["People \/ Family"],"author":"Google","version":"1.6.50"},{"id":"07AB2970-AE77-417B-BEB3-8B6FDEF43EDE","name":"human-male-boy","codepoint":"F0A5C","aliases":["father","dad","man-child"],"tags":["People \/ Family"],"author":"Henrique C\u00e9sar Madeira","version":"2.6.95"},{"id":"4FDB5D5D-02F8-4B99-AA54-C9344F1DB02D","name":"human-male-child","codepoint":"F138C","aliases":[],"tags":["People \/ Family"],"author":"Moma Design Studio","version":"5.0.45"},{"id":"0FC16450-7A7E-43C5-AED4-E27C4A6BFF99","name":"human-male-female","codepoint":"F02E8","aliases":["wc","man-woman"],"tags":["People \/ Family"],"author":"Google","version":"1.5.54"},{"id":"764B2DA8-53A8-4D7D-A156-D73CDA4F0C63","name":"human-male-girl","codepoint":"F0A5D","aliases":["father","dad","man-child"],"tags":["People \/ Family"],"author":"Henrique C\u00e9sar Madeira","version":"2.6.95"},{"id":"38807077-1E35-4599-83CA-110DA473794A","name":"human-male-height","codepoint":"F0EFB","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Richins","version":"3.8.95"},{"id":"51DB457C-C26A-4579-8C34-9ED95D270EA4","name":"human-male-height-variant","codepoint":"F0EFC","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Richins","version":"3.8.95"},{"id":"AB5B56A8-CB56-4502-B388-BA02ECEB2D1A","name":"human-male-male","codepoint":"F0A5E","aliases":["man-man","men"],"tags":["People \/ Family"],"author":"Henrique C\u00e9sar Madeira","version":"2.6.95"},{"id":"05DB88BC-FA28-4DF1-8308-541E338E0234","name":"human-pregnant","codepoint":"F05CF","aliases":["pregnant-woman"],"tags":["People \/ Family"],"author":"Google","version":"1.5.54"},{"id":"FAD84EF2-E1C0-4834-8FFD-677E424F2693","name":"human-queue","codepoint":"F1571","aliases":["human-line"],"tags":["People \/ Family"],"author":"Haley Halcyon","version":"5.5.55"},{"id":"08B3209B-7D10-4C1C-9962-E4DAC71DD06F","name":"human-scooter","codepoint":"F11E9","aliases":[],"tags":["Sport","Transportation + Other"],"author":"Google","version":"4.5.95"},{"id":"B0529853-AE3D-475C-94EB-0C775E934806","name":"human-wheelchair","codepoint":"F138D","aliases":[],"tags":["People \/ Family"],"author":"Moma Design Studio","version":"5.0.45"},{"id":"9A2A1178-7E30-49E7-A639-2D16464EA7EA","name":"humble-bundle","codepoint":"F0744","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.9.32"},{"id":"EE07113F-BD81-424C-B228-7EC802F7CFB2","name":"hvac","codepoint":"F1352","aliases":["heating","ventilation","air-conditioning"],"tags":["Home Automation"],"author":"Google","version":"4.9.95"},{"id":"30019019-F955-40EE-B811-C634718E6FAD","name":"hvac-off","codepoint":"F159E","aliases":["heating-off","ventilation-off","air-conditioning-off"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"FBFEC6FC-C311-4B53-8445-18B604AA7C12","name":"hydraulic-oil-level","codepoint":"F1324","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"54AC2207-9F8D-4A1D-B8B4-ED626D0C8C38","name":"hydraulic-oil-temperature","codepoint":"F1325","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"97D5D644-DB37-4DA8-8B37-444B242A88EF","name":"hydro-power","codepoint":"F12E5","aliases":["hydraulic-turbine","water-turbine","watermill"],"tags":["Device \/ Tech"],"author":"Contributors","version":"4.8.95"},{"id":"C8D5186F-BF39-40DA-9F7A-747DB166EABD","name":"ice-cream","codepoint":"F082A","aliases":[],"tags":["Food \/ Drink"],"author":"Google","version":"2.1.19"},{"id":"9620A768-2570-423E-8D3C-D65C9CACA7EC","name":"ice-cream-off","codepoint":"F0E52","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"3.6.95"},{"id":"58AA127F-3523-4B91-AFED-018FA36D0876","name":"ice-pop","codepoint":"F0EFD","aliases":["popsicle"],"tags":["Food \/ Drink"],"author":"Contributors","version":"3.8.95"},{"id":"44423F53-F28B-49F5-86F1-D71FAC4B4C07","name":"id-card","codepoint":"F0FC0","aliases":[],"tags":[],"author":"Simran","version":"4.0.96"},{"id":"58048473-346E-4473-A18D-36C29B789322","name":"identifier","codepoint":"F0EFE","aliases":["key"],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"3.8.95"},{"id":"86B5194A-AB94-4C20-8110-FA463B705B39","name":"ideogram-cjk","codepoint":"F1331","aliases":["ideogram-chinese-japanese-korean","writing-system-cjk"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"1D315F53-EBD0-42C7-89D6-5E682B756B22","name":"ideogram-cjk-variant","codepoint":"F1332","aliases":["ideogram-chinese-japanese-korean-variant","writing-system-cjk-variant"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"86A1CD17-B112-46F8-A076-424D528A25AA","name":"iframe","codepoint":"F0C8B","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Richins","version":"3.2.89"},{"id":"B5216901-ECCB-41B3-8F35-BFA701ECDDBC","name":"iframe-array","codepoint":"F10F5","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"D07A9442-941E-47BB-8B31-F2EB41DE069E","name":"iframe-array-outline","codepoint":"F10F6","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"6453ED46-EC58-4FE8-94C3-1AC170E42152","name":"iframe-braces","codepoint":"F10F7","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"3727A772-B282-4785-B291-A7C7EBCB25A8","name":"iframe-braces-outline","codepoint":"F10F8","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"87F83807-58BE-49C5-981B-CBDFD8EABE4A","name":"iframe-outline","codepoint":"F0C8C","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Richins","version":"3.2.89"},{"id":"2A524868-FBD4-442F-8E4C-413A1C8DDDEE","name":"iframe-parentheses","codepoint":"F10F9","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"9FA63D08-5057-4AA3-9FD0-367B8AE55352","name":"iframe-parentheses-outline","codepoint":"F10FA","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"A42EE2E1-D139-426F-9B59-C21E8C185DA7","name":"iframe-variable","codepoint":"F10FB","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"DF02C215-E96B-40CA-B372-9767965F11D3","name":"iframe-variable-outline","codepoint":"F10FC","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"3238BA72-FEE8-4C90-A440-AD701359A7BC","name":"image","codepoint":"F02E9","aliases":["insert-photo"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DD2262AA-A145-4788-899D-46D807B4FC0D","name":"image-album","codepoint":"F02EA","aliases":["photo-album","book-image"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D23B9039-C6D4-45F8-B625-EEDE883FF5BD","name":"image-area","codepoint":"F02EB","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"3BE3AA75-C604-45F3-9DD3-5E8731201F08","name":"image-area-close","codepoint":"F02EC","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"F528B8DF-1FE3-47C0-B406-70FAC5718CE1","name":"image-auto-adjust","codepoint":"F0FC1","aliases":[],"tags":["Photography"],"author":"Google","version":"4.0.96"},{"id":"40DCC37F-8A3F-4C15-97E8-2AB88B4DC756","name":"image-broken","codepoint":"F02ED","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D243B11E-D824-4185-B14F-B1C53DB11C24","name":"image-broken-variant","codepoint":"F02EE","aliases":["broken-image"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"3E168631-4E4A-47D7-839A-CEB6B4640510","name":"image-edit","codepoint":"F11E3","aliases":[],"tags":["Edit \/ Modify"],"author":"frankgrinaert","version":"4.5.95"},{"id":"DD3FFC3D-A4AF-4F1D-8239-8F5195BC4C29","name":"image-edit-outline","codepoint":"F11E4","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"7D3932BA-9061-40D7-B624-044EE7A7B445","name":"image-filter-black-white","codepoint":"F02F0","aliases":["filter-b-and-w"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"E3745997-1AD2-4D79-83FE-72ADE96E3C69","name":"image-filter-center-focus","codepoint":"F02F1","aliases":["image-filter-centre-focus"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"3A8D45DA-5897-4B18-BDA5-951967BD4CF8","name":"image-filter-center-focus-strong","codepoint":"F0EFF","aliases":[],"tags":["Photography"],"author":"Google","version":"3.8.95"},{"id":"0012643E-5753-42C0-A1CF-E4FBB5D5E311","name":"image-filter-center-focus-strong-outline","codepoint":"F0F00","aliases":[],"tags":["Photography"],"author":"Google","version":"3.8.95"},{"id":"50F3F396-4286-4D09-B726-4F626649BC04","name":"image-filter-center-focus-weak","codepoint":"F02F2","aliases":["image-filter-centre-focus-weak"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"882F82B8-EDF8-4F1A-A6BA-9C6DAEDBB259","name":"image-filter-drama","codepoint":"F02F3","aliases":[],"tags":["Photography","Nature"],"author":"Google","version":"1.5.54"},{"id":"8EC8847F-E96F-4D14-BF88-F4BE47856865","name":"image-filter-frames","codepoint":"F02F4","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"999CF81E-71B7-48E1-8B8F-70FDE391F647","name":"image-filter-hdr","codepoint":"F02F5","aliases":["mountain","landscape"],"tags":["Photography","Nature"],"author":"Google","version":"1.5.54"},{"id":"56164312-7555-4017-8A1A-48954BE7F7C5","name":"image-filter-none","codepoint":"F02F6","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"368537EA-9261-4097-A1FA-D33EE48A7D59","name":"image-filter-tilt-shift","codepoint":"F02F7","aliases":[],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"0E6F8B1C-14D2-4A98-9414-FFC4B2146748","name":"image-filter-vintage","codepoint":"F02F8","aliases":[],"tags":["Photography","Nature"],"author":"Google","version":"1.5.54"},{"id":"27E31ADA-EF15-4A4E-A17A-45F4C032256F","name":"image-frame","codepoint":"F0E49","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"ED40AC55-00BA-4086-8906-1FA1EDA65839","name":"image-minus","codepoint":"F1419","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"4E0C0467-BF17-4C60-8834-4627DE6D79D5","name":"image-move","codepoint":"F09F8","aliases":[],"tags":[],"author":"Michael Richins","version":"2.5.94"},{"id":"E7CA4672-9863-4015-B3C5-D2C8DEBD2F2F","name":"image-multiple","codepoint":"F02F9","aliases":["collections","photo-library","images"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BCCF75AE-F73D-4B7A-BDFD-9E767DED0B28","name":"image-multiple-outline","codepoint":"F02EF","aliases":["image-filter","images-outline"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"73924BC5-DB17-49B2-BB88-E40C1E45E010","name":"image-off","codepoint":"F082B","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.1.19"},{"id":"8C0E595D-8D0E-4D1E-8E62-850DB25103B3","name":"image-off-outline","codepoint":"F11D1","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.5.95"},{"id":"F6A782BB-5FAB-4FC4-A61B-A0F399A0A5AC","name":"image-outline","codepoint":"F0976","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"8D6FECF2-E4C4-4858-81E2-502104BE2E55","name":"image-plus","codepoint":"F087C","aliases":["image-add"],"tags":[],"author":"GreenTurtwig","version":"2.1.99"},{"id":"95B5A056-E7FE-4C3F-95A6-1E826DD80076","name":"image-remove","codepoint":"F1418","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"F00F5E5A-AD8A-440B-9B31-00D266A538A8","name":"image-search","codepoint":"F0977","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"A36A87C1-E35B-4BCA-AD53-700F6F937EE8","name":"image-search-outline","codepoint":"F0978","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"84644CCB-31DB-471C-AF2C-6E8AD1DE94CA","name":"image-size-select-actual","codepoint":"F0C8D","aliases":[],"tags":[],"author":"Google","version":"3.2.89"},{"id":"58C0E0A5-F760-4893-99C4-3C1E92DBC6DB","name":"image-size-select-large","codepoint":"F0C8E","aliases":[],"tags":[],"author":"Google","version":"3.2.89"},{"id":"A0771C0A-E46B-4985-98D8-C6EC748D03A2","name":"image-size-select-small","codepoint":"F0C8F","aliases":[],"tags":[],"author":"Google","version":"3.2.89"},{"id":"E404BB7C-724B-4390-9DE4-D08DA29B151A","name":"image-text","codepoint":"F160D","aliases":["image-description"],"tags":[],"author":"Google","version":"5.6.55"},{"id":"FB8BEE36-EF77-4820-92B3-5B4C4291D751","name":"import","codepoint":"F02FA","aliases":["input"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"4DDB79C2-C3AE-41DC-B560-AFBF3F689E86","name":"inbox","codepoint":"F0687","aliases":[],"tags":[],"author":"Google","version":"1.7.12"},{"id":"A20D1ABC-DD99-404B-8BEE-967BB1C636B0","name":"inbox-arrow-down","codepoint":"F02FB","aliases":["move-to-inbox"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B7B431BB-E448-47F4-A7DC-03CCCA93C3D1","name":"inbox-arrow-down-outline","codepoint":"F1270","aliases":[],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"5317ED5A-9D37-4C50-AA7D-83491547D214","name":"inbox-arrow-up","codepoint":"F03D1","aliases":["move-from-inbox"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B84765D3-091A-483D-A788-C0269238CF6D","name":"inbox-arrow-up-outline","codepoint":"F1271","aliases":[],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"1CB38744-AE8F-4B42-ACED-10749BBF81F5","name":"inbox-full","codepoint":"F1272","aliases":[],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"BD7DE99A-F6EC-46CF-BE18-8371E6BCD9CA","name":"inbox-full-outline","codepoint":"F1273","aliases":[],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"6FF18A17-48D4-4173-9CBD-8DB77F5A6E2A","name":"inbox-multiple","codepoint":"F08B0","aliases":["inboxes"],"tags":[],"author":"Google","version":"2.2.43"},{"id":"AA22D582-9319-4AB0-BBF8-08824D7605B8","name":"inbox-multiple-outline","codepoint":"F0BA8","aliases":["inboxes-outline"],"tags":[],"author":"Google","version":"3.0.39"},{"id":"7082C01E-4FF9-489E-BD05-53140FCD382A","name":"inbox-outline","codepoint":"F1274","aliases":[],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"2166DBC6-19EC-4A1D-BE92-8366CEE53B8F","name":"inbox-remove","codepoint":"F159F","aliases":[],"tags":[],"author":"Terren","version":"5.5.55"},{"id":"628C4376-372F-4880-875B-DE838A6B4B70","name":"inbox-remove-outline","codepoint":"F15A0","aliases":[],"tags":[],"author":"Terren","version":"5.5.55"},{"id":"1350E7BA-9354-4F62-9B21-0238E3DF4D81","name":"incognito","codepoint":"F05F9","aliases":["anonymous","spy"],"tags":[],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"80DE3C45-2A19-412F-9FA2-DCFB853F60ED","name":"incognito-circle","codepoint":"F1421","aliases":["anonymous-circle","spy-circle"],"tags":[],"author":"Google","version":"5.2.45"},{"id":"3F362E64-C60F-416B-834D-E5C2A88ED23F","name":"incognito-circle-off","codepoint":"F1422","aliases":["anonymous-circle-off","spy-circle-off"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"26B94EEC-5090-4DF4-99FC-C4A90830720A","name":"incognito-off","codepoint":"F0075","aliases":["spy-off","anonymous-off"],"tags":[],"author":"nilsfast","version":"1.5.54"},{"id":"8C4EBD04-376D-41AC-86D3-2BBDD56768C7","name":"infinity","codepoint":"F06E4","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.8.36"},{"id":"2BC4A4B6-119B-4637-BF3D-1FB9394E1F38","name":"information","codepoint":"F02FC","aliases":["about","information-circle","info-circle","about-circle"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"F7C01A96-16E0-44C0-A261-2CF22D056A7F","name":"information-outline","codepoint":"F02FD","aliases":["info-outline","about-outline","information-circle-outline","info-circle-outline","about-circle-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D991D5FA-BD60-48E1-979D-A103D005725A","name":"information-variant","codepoint":"F064E","aliases":["info-variant","about-variant"],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"2AA07220-461B-4070-AA95-17DEFE501444","name":"instagram","codepoint":"F02FE","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"7A8E4735-E738-4ECE-8386-889694014C22","name":"instrument-triangle","codepoint":"F104E","aliases":["dinner-bell"],"tags":["Music"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"2B0100AC-D0EB-4B85-A9AB-EB921C9A65AC","name":"invert-colors","codepoint":"F0301","aliases":["invert-colours"],"tags":["Color"],"author":"Google","version":"1.5.54"},{"id":"B3F155FA-57B1-4781-AC45-98A1A47673DC","name":"invert-colors-off","codepoint":"F0E4A","aliases":["invert-colours-off"],"tags":["Color"],"author":"Google","version":"3.6.95"},{"id":"A360D72F-7DC7-4E24-B7F0-1856C918CB8A","name":"iobroker","codepoint":"F12E8","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"4.8.95"},{"id":"4560EF32-158B-40B1-829E-A078219A808A","name":"ip","codepoint":"F0A5F","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"54CCA164-149B-4050-9747-529EF134460A","name":"ip-network","codepoint":"F0A60","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"BB20E65D-DA61-4A5E-8B2E-52CB92DE3771","name":"ip-network-outline","codepoint":"F0C90","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"63BFCC93-117D-45ED-8E42-4019C6D7B970","name":"ipod","codepoint":"F0C91","aliases":["apple-ipod"],"tags":[],"author":"GreenTurtwig","version":"3.2.89"},{"id":"94C88D65-EE50-4DC5-920D-FA4181DE0413","name":"islam","codepoint":"F0979","aliases":["religion-islamic","star-and-crescent","religion-muslim"],"tags":["Religion"],"author":"Nick","version":"2.4.85"},{"id":"A39024B8-5991-409C-8E68-DC9562D52F86","name":"island","codepoint":"F104F","aliases":[],"tags":["Places"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"0921F3AE-3BFF-4913-BB68-CB48587D14E4","name":"iv-bag","codepoint":"F10B9","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"5F75012D-D248-4275-B274-6D6AB3B95F3B","name":"jabber","codepoint":"F0DD5","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"3.5.94"},{"id":"2C0278A5-D43D-4B8B-8870-878BEAF6BE17","name":"jeepney","codepoint":"F0302","aliases":[],"tags":["Transportation + Road"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2F73C05F-4D6E-49B3-B41B-BCDA372E1774","name":"jellyfish","codepoint":"F0F01","aliases":[],"tags":["Animal"],"author":"Simran","version":"3.8.95"},{"id":"4F49A0D7-8E63-411E-97E0-7CA054831A38","name":"jellyfish-outline","codepoint":"F0F02","aliases":[],"tags":["Animal"],"author":"Simran","version":"3.8.95"},{"id":"2F0CB359-6C54-4723-9E8D-94481F0A8E30","name":"jira","codepoint":"F0303","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"3A14C142-9D2F-44BC-882E-333745FACAA3","name":"jquery","codepoint":"F087D","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"B6B10BEF-B1E3-43D7-AAAA-85566157B30B","name":"jsfiddle","codepoint":"F0304","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"7EF95029-012C-456C-A1E8-BB96961071FD","name":"judaism","codepoint":"F097A","aliases":["jewish","religion-judaic","star-of-david","magen-david"],"tags":["Religion"],"author":"Nick","version":"2.4.85"},{"id":"FC2D912E-451A-4AE8-8399-67F116ED12D9","name":"jump-rope","codepoint":"F12FF","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"24CB8442-6875-4A22-A265-0C625118C7E7","name":"kabaddi","codepoint":"F0D87","aliases":["wrestling"],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"70EC6F3B-31E9-4F1A-8E48-408CEB706FB8","name":"kangaroo","codepoint":"F1558","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"85144563-B019-4B8A-AB76-3DE0797D517E","name":"karate","codepoint":"F082C","aliases":["martial-arts","kickboxing"],"tags":["Sport"],"author":"Michael Richins","version":"2.1.19"},{"id":"EEF9C07A-019A-49B4-805D-0DF8601F09DF","name":"keg","codepoint":"F0305","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C4476901-9B29-410C-BCA7-67814F5421B4","name":"kettle","codepoint":"F05FA","aliases":["tea-kettle","kettle-full","tea-kettle-full"],"tags":["Home Automation","Food \/ Drink"],"author":"Simran","version":"1.5.54"},{"id":"123DA4E5-7243-4495-8CE4-2CDA32A65C01","name":"kettle-alert","codepoint":"F1317","aliases":["tea-kettle-alert","kettle-full-alert","tea-kettle-full-alert"],"tags":["Home Automation","Alert \/ Error","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"4F1F1AC0-68D1-4C74-8F03-DF6EBC2C8B29","name":"kettle-alert-outline","codepoint":"F1318","aliases":["tea-kettle-alert-outline","kettle-empty-alert","tea-kettle-empty-alert"],"tags":["Home Automation","Alert \/ Error","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"A28C7FA8-2D3A-482A-ADC8-46391CF201E1","name":"kettle-off","codepoint":"F131B","aliases":["tea-kettle-off","tea-kettle-full-off","kettle-full-off"],"tags":["Home Automation","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"15C6F7FE-65D4-4116-AF5C-7A171407E460","name":"kettle-off-outline","codepoint":"F131C","aliases":["tea-kettle-off-outline","kettle-empty-off","tea-kettle-empty-off"],"tags":["Home Automation","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"FCE0A2B1-414F-4E9F-AF73-F878AE890F38","name":"kettle-outline","codepoint":"F0F56","aliases":["tea-kettle-outline","kettle-empty","tea-kettle-empty"],"tags":["Food \/ Drink","Home Automation"],"author":"Nick","version":"3.9.97"},{"id":"30064882-D796-4A8E-8BD1-CAED8C9A49DA","name":"kettle-pour-over","codepoint":"F173C","aliases":[],"tags":[],"author":"nilsfast","version":"5.9.55"},{"id":"B976C4B0-D50C-49ED-B072-CD8E8A38A4AF","name":"kettle-steam","codepoint":"F1319","aliases":["tea-kettle-steam","kettle-full-steam","tea-kettle-full-steam"],"tags":["Home Automation","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"6D9BDFFF-63EE-45DE-A6F5-712B0EE12534","name":"kettle-steam-outline","codepoint":"F131A","aliases":["tea-kettle-steam-outline","kettle-empty-steam","tea-kettle-empty-steam"],"tags":["Home Automation","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"E3220479-E885-4EDD-9678-E60F670DFBAA","name":"kettlebell","codepoint":"F1300","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"D6208581-CF7F-438A-8578-B6ADEE462212","name":"key","codepoint":"F0306","aliases":["vpn-key"],"tags":["Automotive"],"author":"Google","version":"1.5.54"},{"id":"7A79C7BB-6669-46CA-8AB0-E3B537D83EA2","name":"key-arrow-right","codepoint":"F1312","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"80B6B5A5-0FE3-4CA0-924C-05311090832D","name":"key-chain","codepoint":"F1574","aliases":[],"tags":["Automotive"],"author":"Contributors","version":"5.5.55"},{"id":"01B0561A-56B4-4215-A811-1572D35331F6","name":"key-chain-variant","codepoint":"F1575","aliases":[],"tags":["Automotive"],"author":"Contributors","version":"5.5.55"},{"id":"FEEA71CA-4810-46DD-B459-6D9327720D17","name":"key-change","codepoint":"F0307","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"08C0F709-4E1C-4BFD-8CC6-BC12FE5CDD9B","name":"key-link","codepoint":"F119F","aliases":["foreign-key","sql-foreign-key"],"tags":[],"author":"Haley Halcyon","version":"4.4.95"},{"id":"F58302B9-82F4-46AC-9A60-4640CFCE33B2","name":"key-minus","codepoint":"F0308","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"83238148-C76D-4C83-904D-911A9E9C2715","name":"key-outline","codepoint":"F0DD6","aliases":[],"tags":[],"author":"Google","version":"3.5.94"},{"id":"000AAEC6-5E6C-40F4-B589-AE85920E7EC2","name":"key-plus","codepoint":"F0309","aliases":["key-add"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"5A1609F7-424E-417F-B1C4-7EDA3051A4BA","name":"key-remove","codepoint":"F030A","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"7C312A2D-A502-4F06-89D4-0783EADC3B3F","name":"key-star","codepoint":"F119E","aliases":["primary-key","sql-primary-key"],"tags":[],"author":"Haley Halcyon","version":"4.4.95"},{"id":"967692C3-B061-425E-A0E4-FF1F580275E5","name":"key-variant","codepoint":"F030B","aliases":[],"tags":["Automotive"],"author":"Austin Andrews","version":"1.5.54"},{"id":"196889AF-CD00-44BC-BAD3-932B936E4EAE","name":"key-wireless","codepoint":"F0FC2","aliases":[],"tags":[],"author":"Michael Richins","version":"4.0.96"},{"id":"520C8488-DD34-43E1-AEA0-A188B2DE6B01","name":"keyboard","codepoint":"F030C","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"21C8B558-8398-43E8-A79A-8BA99BE693D6","name":"keyboard-backspace","codepoint":"F030D","aliases":["keyboard-clear","keyboard-erase"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"0F441009-7A1F-45BF-A239-B9591B0A5404","name":"keyboard-caps","codepoint":"F030E","aliases":["keyboard-capslock"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8545C0A1-5625-422F-AF38-624FB54237D3","name":"keyboard-close","codepoint":"F030F","aliases":["keyboard-hide"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"3EB07099-2309-466E-8BC0-EA835C273E37","name":"keyboard-esc","codepoint":"F12B7","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"512A5D44-18A8-4644-AA17-E8E026E0F1B0","name":"keyboard-f1","codepoint":"F12AB","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"29296B9C-9A28-4F04-A2AD-550CB1EC89E1","name":"keyboard-f10","codepoint":"F12B4","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"DDF92650-C04B-4826-BD5A-FB12B06F7E6E","name":"keyboard-f11","codepoint":"F12B5","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"7C97B45E-8039-41C4-A188-A21475A4FB3F","name":"keyboard-f12","codepoint":"F12B6","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"3DFC5B29-C785-4D97-A04D-E63FAD987C25","name":"keyboard-f2","codepoint":"F12AC","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"7776F4B4-2F61-47FF-83F5-A768239E3F80","name":"keyboard-f3","codepoint":"F12AD","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"C227FD26-6801-4545-AC74-66C63B56807A","name":"keyboard-f4","codepoint":"F12AE","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"C50601AF-7AD6-4677-B8B3-181B978613A8","name":"keyboard-f5","codepoint":"F12AF","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"9B4318C8-A2CC-43A9-8706-C9D3DDF33D5E","name":"keyboard-f6","codepoint":"F12B0","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"DDE4A6E4-BDE8-4E63-8F77-E3D06BF29BF1","name":"keyboard-f7","codepoint":"F12B1","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"3392982E-1464-49EF-B22F-EE0FBA421D4E","name":"keyboard-f8","codepoint":"F12B2","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"BBFF3508-533C-4378-B9FC-60EC20CAB214","name":"keyboard-f9","codepoint":"F12B3","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"A7DFF78C-C6DD-4BB6-BBFA-A88242516A74","name":"keyboard-off","codepoint":"F0310","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"4DC89B68-BD60-4D89-BD32-F15C0CFCEF79","name":"keyboard-off-outline","codepoint":"F0E4B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"6E751B9F-72AD-4554-8C62-24E457B80FDB","name":"keyboard-outline","codepoint":"F097B","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"7816CE91-EBD1-4136-8523-CF47F677F4C6","name":"keyboard-return","codepoint":"F0311","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4894BA3C-C713-4ACA-9918-1AF74B5E5427","name":"keyboard-settings","codepoint":"F09F9","aliases":[],"tags":["Settings"],"author":"Michael Richins","version":"2.5.94"},{"id":"7D765BD9-7B7E-4288-89E5-4A74E72E1083","name":"keyboard-settings-outline","codepoint":"F09FA","aliases":[],"tags":["Settings"],"author":"Michael Richins","version":"2.5.94"},{"id":"803E5E8E-04C6-41E1-9EE0-B8C3C723D507","name":"keyboard-space","codepoint":"F1050","aliases":[],"tags":[],"author":"Michael Richins","version":"4.1.95"},{"id":"D7C0D37A-BF75-4542-8AFF-614FA0EC498C","name":"keyboard-tab","codepoint":"F0312","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BCAA42FF-BF36-42D8-B8FD-5DE2968162D8","name":"keyboard-variant","codepoint":"F0313","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"8F5B2685-A656-45ED-89C2-032E76322358","name":"khanda","codepoint":"F10FD","aliases":["sikh"],"tags":["Religion"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"D881D589-79F0-4255-B050-13E396293D1F","name":"kickstarter","codepoint":"F0745","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.9.32"},{"id":"1A131BAA-CFEE-41F3-9B15-01A4A9F1B341","name":"klingon","codepoint":"F135B","aliases":[],"tags":[],"author":"Contributors","version":"4.9.95"},{"id":"AF35DB46-1B52-4721-8475-F3CD107325B4","name":"knife","codepoint":"F09FB","aliases":[],"tags":[],"author":"Augustin Ursu","version":"2.5.94"},{"id":"D31C18C1-776C-4444-9A12-F2BD366CF929","name":"knife-military","codepoint":"F09FC","aliases":["dagger"],"tags":["Gaming \/ RPG"],"author":"Simran","version":"2.5.94"},{"id":"180CACBF-4272-4D07-B9A0-63A5625DCB0C","name":"koala","codepoint":"F173F","aliases":[],"tags":[],"author":"Contributors","version":"5.9.55"},{"id":"AD953D07-5F33-439B-895F-7AD5615EA14A","name":"kodi","codepoint":"F0314","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"9823C48B-5D2E-4058-9836-F2C6DCACAB71","name":"kubernetes","codepoint":"F10FE","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.3.95"},{"id":"C749E06B-E75E-4D9B-97A6-47E9399D01FC","name":"label","codepoint":"F0315","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"9373446C-95C3-4160-9CBC-FF1DEF5C9F28","name":"label-multiple","codepoint":"F1375","aliases":[],"tags":[],"author":"nilsfast","version":"4.9.95"},{"id":"D504ED4D-5F02-4501-A223-59BF2D4CD9EB","name":"label-multiple-outline","codepoint":"F1376","aliases":[],"tags":[],"author":"nilsfast","version":"4.9.95"},{"id":"BCBB111E-0DF2-4498-831D-E547AE9EE0FB","name":"label-off","codepoint":"F0ACB","aliases":[],"tags":[],"author":"Google","version":"2.7.94"},{"id":"94A3D797-3936-4FBE-A6B5-6C88934B40BD","name":"label-off-outline","codepoint":"F0ACC","aliases":[],"tags":[],"author":"Google","version":"2.7.94"},{"id":"91C2FA0C-2273-42F9-ACBF-BD418B8F970D","name":"label-outline","codepoint":"F0316","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"62FCE66D-4003-4B22-8C47-501947EA4CC8","name":"label-percent","codepoint":"F12EA","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"7EBE7C17-4905-43F9-A084-0756FBB3905D","name":"label-percent-outline","codepoint":"F12EB","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"3A54255E-EDE1-4622-87F4-9FCB31B1B688","name":"label-variant","codepoint":"F0ACD","aliases":[],"tags":[],"author":"Google","version":"2.7.94"},{"id":"75106002-9EFE-4771-8B68-C60B60589C42","name":"label-variant-outline","codepoint":"F0ACE","aliases":[],"tags":[],"author":"Google","version":"2.7.94"},{"id":"F2C62DAD-9011-4495-B542-87407FFB7EA1","name":"ladder","codepoint":"F15A2","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"97AFF594-E421-4757-BE72-1D6C428E27AE","name":"ladybug","codepoint":"F082D","aliases":["bugfood","ladybird"],"tags":["Nature"],"author":"Google","version":"2.1.19"},{"id":"1815038E-B466-4F5F-91D9-9D03DDA6A9DA","name":"lambda","codepoint":"F0627","aliases":[],"tags":["Gaming \/ RPG","Math"],"author":"Austin Andrews","version":"1.6.50"},{"id":"A39CC0FD-32DA-4AB2-8483-9E4C4F03D220","name":"lamp","codepoint":"F06B5","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"1.7.22"},{"id":"9AC5919E-2271-42D0-A5FA-ACB9BE022547","name":"lamps","codepoint":"F1576","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"A20B1B0B-DC60-4ED1-A7E6-F390BA31D613","name":"lan","codepoint":"F0317","aliases":["local-area-network"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"9DF15E25-DE45-4D9B-8E3B-EA6D643EA0CC","name":"lan-check","codepoint":"F12AA","aliases":[],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"B52D6944-3AC2-4113-A91C-199C0CD577A6","name":"lan-connect","codepoint":"F0318","aliases":["local-area-network-connect"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"10DCD7DC-998B-4631-B8A6-A0D8C93412A3","name":"lan-disconnect","codepoint":"F0319","aliases":["local-area-network-disconnect"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"B5E302E3-DF81-430E-AAE0-4CAF44AFAD00","name":"lan-pending","codepoint":"F031A","aliases":["local-area-network-pending"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"082F25B3-8413-4CC7-B908-8BBD40BB32D8","name":"language-c","codepoint":"F0671","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.6.50"},{"id":"74446CD2-562D-44E7-AAC1-62D4CCDB9F43","name":"language-cpp","codepoint":"F0672","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.6.50"},{"id":"EFF1E516-3470-456C-AC79-0F9C82C79391","name":"language-csharp","codepoint":"F031B","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.5.54"},{"id":"DA72E30D-C562-4E93-B8C8-CAFA686A1D23","name":"language-css3","codepoint":"F031C","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.5.54"},{"id":"F1DEF74B-8116-4E0E-98BE-97A699812E5A","name":"language-fortran","codepoint":"F121A","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"ACAFCF05-E04D-4212-AB53-C72BD8DB5768","name":"language-go","codepoint":"F07D3","aliases":[],"tags":["Developer \/ Languages"],"author":"Google","version":"2.0.46"},{"id":"87E5CF33-FA30-4CCA-8FAD-AAD3D7C17904","name":"language-haskell","codepoint":"F0C92","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"3.2.89"},{"id":"98D9A5A1-626A-4273-B895-4C838936613C","name":"language-html5","codepoint":"F031D","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.5.54"},{"id":"CF5C2532-318B-4866-B8CE-319601ADD95E","name":"language-java","codepoint":"F0B37","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"2.8.94"},{"id":"9D3ED5EB-8951-4E75-A623-EEF618ED4172","name":"language-javascript","codepoint":"F031E","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.5.54"},{"id":"D3EC3384-B91D-46C9-8D43-7D333DB2273D","name":"language-kotlin","codepoint":"F1219","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"0B0DE3A6-7ED1-497C-BAF4-CDAA3F9713C9","name":"language-lua","codepoint":"F08B1","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"2.2.43"},{"id":"42875A08-46EC-4077-95A9-86D16888F2D4","name":"language-markdown","codepoint":"F0354","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A8970A35-C4F5-452B-B8CA-13BACF5C29F5","name":"language-markdown-outline","codepoint":"F0F5B","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"3.9.97"},{"id":"2A153653-6727-4DE1-95DC-AC6801A7DC01","name":"language-php","codepoint":"F031F","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.5.54"},{"id":"4E453C2B-40D4-4D60-8EAF-750091283FAC","name":"language-python","codepoint":"F0320","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2F197131-0666-4F07-8BDE-B6FB3C4BB39B","name":"language-r","codepoint":"F07D4","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"2.0.46"},{"id":"2BC47DF3-B959-44C0-BE1A-8D1EB0B18FEF","name":"language-ruby","codepoint":"F0D2D","aliases":[],"tags":[],"author":"Contributors","version":"3.3.92"},{"id":"6898147E-618C-4A16-A06B-5270C63AAB2B","name":"language-ruby-on-rails","codepoint":"F0ACF","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"2.7.94"},{"id":"D88C59AC-3310-4AA7-8432-BFA51BF2DCE4","name":"language-rust","codepoint":"F1617","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"5.6.55"},{"id":"9F060254-CB0B-4DD9-87C5-BADAE8F2F8C4","name":"language-swift","codepoint":"F06E5","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.8.36"},{"id":"BFE7B3A3-4B61-4583-B22D-395E1FCE1A07","name":"language-typescript","codepoint":"F06E6","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"1.8.36"},{"id":"1AC4596D-76B2-4F11-AF23-157736CABB86","name":"language-xaml","codepoint":"F0673","aliases":["xaml","microsoft-xaml"],"tags":[],"author":"Contributors","version":"1.6.50"},{"id":"A8B6481F-EE91-4F90-81AC-DEB8A096F45A","name":"laptop","codepoint":"F0322","aliases":["computer"],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"70793340-E8F2-43A0-8AB1-0DAB70CC8B9A","name":"laptop-chromebook","codepoint":"F0323","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54","deprecated":true},{"id":"DC51467E-30C0-4144-9AE6-80762ACA972C","name":"laptop-mac","codepoint":"F0324","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54","deprecated":true},{"id":"C9A08F85-B996-498D-ADDC-20A9B77B5489","name":"laptop-off","codepoint":"F06E7","aliases":[],"tags":["Device \/ Tech"],"author":"Michael Richins","version":"1.8.36"},{"id":"CFF782E5-F36B-4F80-B105-68E6B4B91C64","name":"laptop-windows","codepoint":"F0325","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54","deprecated":true},{"id":"B8CF1F73-D020-43C3-83CB-34DB20820628","name":"laravel","codepoint":"F0AD0","aliases":[],"tags":[],"author":"Contributors","version":"2.7.94"},{"id":"D202901C-7C33-48DF-925A-BB3506158E99","name":"laser-pointer","codepoint":"F1484","aliases":[],"tags":[],"author":"Google","version":"5.3.45"},{"id":"5A1E325C-36BD-4BAC-BF4F-E349D9016B28","name":"lasso","codepoint":"F0F03","aliases":[],"tags":[],"author":"Louistwee","version":"3.8.95"},{"id":"65AC32C4-911E-4005-8BD1-663AE0000988","name":"lastpass","codepoint":"F0446","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"E72ED7A1-8133-4E0F-8EC6-28F053DF51B1","name":"latitude","codepoint":"F0F57","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Richins","version":"3.9.97"},{"id":"ED8AF9CE-E555-49C9-8E7E-F9B85CD94CDF","name":"launch","codepoint":"F0327","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B1E2F856-253B-465C-861A-40C5C7D6C8DB","name":"lava-lamp","codepoint":"F07D5","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"36A9B462-C487-458E-BFB6-2415739BC968","name":"layers","codepoint":"F0328","aliases":[],"tags":["Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"E72B7CB5-1A02-49C0-AC64-DF2559F026F1","name":"layers-minus","codepoint":"F0E4C","aliases":[],"tags":["Geographic Information System"],"author":"Austin Andrews","version":"3.6.95"},{"id":"1ADB303D-B8D9-49EF-8EB0-C02AFD269F02","name":"layers-off","codepoint":"F0329","aliases":["layers-clear"],"tags":["Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"FAC5EA16-5C62-49FA-8BE4-7D797604A425","name":"layers-off-outline","codepoint":"F09FD","aliases":[],"tags":["Geographic Information System"],"author":"Google","version":"2.5.94"},{"id":"9026C3EC-9903-40FE-B3DF-EDB7FE10191A","name":"layers-outline","codepoint":"F09FE","aliases":[],"tags":["Geographic Information System"],"author":"Google","version":"2.5.94"},{"id":"74FE9D86-D461-4C92-8981-E5A67954D6FA","name":"layers-plus","codepoint":"F0E4D","aliases":[],"tags":["Geographic Information System"],"author":"Austin Andrews","version":"3.6.95"},{"id":"4FE9D22C-A632-4B2E-8257-D6789764B1F6","name":"layers-remove","codepoint":"F0E4E","aliases":[],"tags":["Geographic Information System"],"author":"Austin Andrews","version":"3.6.95"},{"id":"8502BBC1-8C93-4D63-97C6-1BA163C1DDC0","name":"layers-search","codepoint":"F1206","aliases":[],"tags":["Geographic Information System"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"6EC54CC3-3FAD-4692-B123-9FA5A8F3D80E","name":"layers-search-outline","codepoint":"F1207","aliases":[],"tags":["Geographic Information System"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"E13ACA71-A398-4E3F-A1DF-ED7E4A1E1A84","name":"layers-triple","codepoint":"F0F58","aliases":[],"tags":[],"author":"GreenTurtwig","version":"3.9.97"},{"id":"B5AC4711-8218-4B94-9372-628616C5CBD8","name":"layers-triple-outline","codepoint":"F0F59","aliases":[],"tags":[],"author":"GreenTurtwig","version":"3.9.97"},{"id":"5EB00CD5-91CA-438E-B569-2D680E6102D6","name":"lead-pencil","codepoint":"F064F","aliases":[],"tags":["Drawing \/ Art"],"author":"Google","version":"1.6.50"},{"id":"30AC82B4-6073-462B-B63E-0F64706AAC2F","name":"leaf","codepoint":"F032A","aliases":[],"tags":["Nature","Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C7FF59F8-8D2F-4866-B8D3-27ED83C324F0","name":"leaf-maple","codepoint":"F0C93","aliases":[],"tags":["Nature"],"author":"Michael Richins","version":"3.2.89"},{"id":"D1DE0E7A-928A-430D-BD2B-B80C9FA2D2F4","name":"leaf-maple-off","codepoint":"F12DA","aliases":[],"tags":["Nature"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"96F48C59-4C64-4584-9E07-73AAD3533FAA","name":"leaf-off","codepoint":"F12D9","aliases":[],"tags":["Nature","Food \/ Drink"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"D648ECFA-B185-4041-8B54-6D1C125CD08E","name":"leak","codepoint":"F0DD7","aliases":["proximity-sensor"],"tags":[],"author":"Google","version":"3.5.94"},{"id":"EDA0BABB-A354-481B-8E60-108E3B20D64C","name":"leak-off","codepoint":"F0DD8","aliases":["proximity-sensor-off"],"tags":[],"author":"Google","version":"3.5.94"},{"id":"8A29D85F-1BAD-4610-AF2F-B4AF0F0D2755","name":"led-off","codepoint":"F032B","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"5DACA128-6BEE-424D-83BA-8C94E01F5C0A","name":"led-on","codepoint":"F032C","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"423F2C55-8E79-441A-A987-45A97FAA3F53","name":"led-outline","codepoint":"F032D","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"F301BDB9-027C-40D0-A21F-3111A7AB218F","name":"led-strip","codepoint":"F07D6","aliases":["light-strip"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"E4D78AC1-63FD-4BF0-89CD-91D80CCAAE40","name":"led-strip-variant","codepoint":"F1051","aliases":["light-strip-variant"],"tags":["Home Automation"],"author":"Borre Haugen","version":"4.1.95"},{"id":"BBDD4244-D5C9-4150-9936-31C775AA463F","name":"led-variant-off","codepoint":"F032E","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"9929F712-7241-468C-B10B-5739356EC85C","name":"led-variant-on","codepoint":"F032F","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"AEACBB35-5466-4C5B-8AA5-B366D0322A27","name":"led-variant-outline","codepoint":"F0330","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"48662A59-F777-4513-9023-17D826B11F5C","name":"leek","codepoint":"F117D","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"4.4.95"},{"id":"098E9BF3-3E1F-43E3-ACFF-2D35123A3186","name":"less-than","codepoint":"F097C","aliases":[],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"9CA22101-6F3D-4EE1-B9F1-C64CE0EFC911","name":"less-than-or-equal","codepoint":"F097D","aliases":[],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"45FA5A9C-DFF1-4D7E-B683-DB7DE2BAEFC7","name":"library","codepoint":"F0331","aliases":["local-library"],"tags":["Places"],"author":"Google","version":"1.5.54"},{"id":"282A591C-4D91-4AAF-B401-00F3AE4B73F2","name":"library-shelves","codepoint":"F0BA9","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"8398466C-F905-444F-81E6-B5B2103BD873","name":"license","codepoint":"F0FC3","aliases":["ribbon","prize","award","seal"],"tags":[],"author":"Google","version":"4.0.96"},{"id":"7936EB1E-FCE1-4501-A339-C5EB7E4301E9","name":"lifebuoy","codepoint":"F087E","aliases":["life-preserver","support","help","overboard"],"tags":["Transportation + Water"],"author":"Simran","version":"2.1.99"},{"id":"647E0001-A60B-4D74-B127-BF522712922F","name":"light-switch","codepoint":"F097E","aliases":[],"tags":["Home Automation"],"author":"Google","version":"2.4.85"},{"id":"ECC94305-DFA6-4D9B-85C8-CC79F3F05FB5","name":"lightbulb","codepoint":"F0335","aliases":["idea","bulb"],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"7D6FF098-D459-4B89-A13C-C9145A1EB992","name":"lightbulb-cfl","codepoint":"F1208","aliases":["bulb-cfl"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"4.6.95"},{"id":"9E3FA5DD-7C93-4283-A7BD-30AE71ACD2C6","name":"lightbulb-cfl-off","codepoint":"F1209","aliases":["bulb-cfl-off"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"0F61D2EB-5321-4D49-B9DD-4F205DA010A2","name":"lightbulb-cfl-spiral","codepoint":"F1275","aliases":["bulb-cfl-spiral"],"tags":["Home Automation"],"author":"Contributors","version":"4.7.95"},{"id":"49D60773-F400-491A-AD3F-B50110089F63","name":"lightbulb-cfl-spiral-off","codepoint":"F12C3","aliases":["bulb-cfl-spiral-off"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"DB267C0E-F298-4380-99C8-E18FA8E06554","name":"lightbulb-group","codepoint":"F1253","aliases":["bulb-group"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.6.95"},{"id":"CA2B5020-40AD-44C1-8868-F14927FCD535","name":"lightbulb-group-off","codepoint":"F12CD","aliases":["bulb-group-off"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"54E68537-16C8-48C4-82F8-4A1000DA605D","name":"lightbulb-group-off-outline","codepoint":"F12CE","aliases":["bulb-group-off-outline"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"C4751630-A657-4A0B-89C5-6FD3037A8CD6","name":"lightbulb-group-outline","codepoint":"F1254","aliases":["bulb-group-outline"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.6.95"},{"id":"33D321D2-E427-469E-9646-D5758B4D5038","name":"lightbulb-multiple","codepoint":"F1255","aliases":["lightbulbs","bulb-multiple","bulbs"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.6.95"},{"id":"B336C5E4-48AB-4620-9DA4-DB1144885F7C","name":"lightbulb-multiple-off","codepoint":"F12CF","aliases":["lightbulbs-off","bulb-multiple-off","bulbs-off"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"827B8418-9667-4429-A4D3-7C0553D1946E","name":"lightbulb-multiple-off-outline","codepoint":"F12D0","aliases":["lightbulbs-off-outline","bulb-multiple-off-outline","bulbs-off-outline"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"7AAEC297-D587-4D13-9397-50C8C93B48C8","name":"lightbulb-multiple-outline","codepoint":"F1256","aliases":["lightbulbs-outline","bulb-multiple-outline","bulbs-outline"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.6.95"},{"id":"14D09F5A-C467-428B-9C5A-F2B3939D1678","name":"lightbulb-off","codepoint":"F0E4F","aliases":["bulb-off"],"tags":["Home Automation"],"author":"Contributors","version":"3.6.95"},{"id":"02757DC7-3D66-4244-B115-C69A74D24B66","name":"lightbulb-off-outline","codepoint":"F0E50","aliases":["bulb-off-outline"],"tags":["Home Automation"],"author":"Contributors","version":"3.6.95"},{"id":"4B3F67C4-02C3-4083-B47A-645AD24992FA","name":"lightbulb-on","codepoint":"F06E8","aliases":["idea","bulb-on"],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.8.36"},{"id":"1FDA626F-5858-43AE-92A0-9CCE7168F08F","name":"lightbulb-on-outline","codepoint":"F06E9","aliases":["idea","bulb-on-outline"],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.8.36"},{"id":"BF6C3B65-0795-43E0-B373-058414FDD485","name":"lightbulb-outline","codepoint":"F0336","aliases":["idea","bulb-outline"],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"95534506-8ECD-49B3-9F87-64D52CC874BA","name":"lighthouse","codepoint":"F09FF","aliases":["beacon"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"85B287CF-D036-4E36-934F-B6FA28892D9C","name":"lighthouse-on","codepoint":"F0A00","aliases":["beacon"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"A4A9C031-02B0-45C7-B9C8-EA1541DB9A38","name":"lightning-bolt","codepoint":"F140B","aliases":[],"tags":[],"author":"Brooke Clifton","version":"5.1.45"},{"id":"908D1C1F-8D3A-4316-8CF5-ABDF16747DA1","name":"lightning-bolt-outline","codepoint":"F140C","aliases":[],"tags":[],"author":"Brooke Clifton","version":"5.1.45"},{"id":"F718A4A1-9D7B-45E5-B0AD-50FDA06BA3C3","name":"lingerie","codepoint":"F1476","aliases":["underwear","bra","panties"],"tags":["Clothing"],"author":"Contributors","version":"5.2.45"},{"id":"462769C2-0A30-4B31-B66C-55168B10D705","name":"link","codepoint":"F0337","aliases":["insert-link"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A1FC74FE-BCA4-447F-AA0D-837A8E33C945","name":"link-box","codepoint":"F0D1A","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"7CBB0F91-4D15-414D-8623-EB84F13AFA75","name":"link-box-outline","codepoint":"F0D1B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"76AB74B7-D753-4AE9-9FDD-5A0C2B8AB823","name":"link-box-variant","codepoint":"F0D1C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"8BEB1816-449A-43E8-8A08-0030E1D4DB93","name":"link-box-variant-outline","codepoint":"F0D1D","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"CDEA2CC8-FD08-49E6-AC29-A5DD70956C35","name":"link-lock","codepoint":"F10BA","aliases":["block-chain"],"tags":["Lock"],"author":"Michael Richins","version":"4.2.95"},{"id":"0DACA19D-EFEB-4D22-BE20-9E8FB8C1BBEB","name":"link-off","codepoint":"F0338","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"0436D77E-F53E-4A1E-A402-916D7D90A1BE","name":"link-plus","codepoint":"F0C94","aliases":["link-add"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"4D09DDBE-9716-4162-9DA9-B50892241E15","name":"link-variant","codepoint":"F0339","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"1D8C8A91-65E7-4FED-B4C6-C29550080C43","name":"link-variant-minus","codepoint":"F10FF","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"BC8F07E8-9157-49BB-B8DF-CCCDB19C5467","name":"link-variant-off","codepoint":"F033A","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"9132A003-2D40-49A6-9D8B-F2AD2EC98788","name":"link-variant-plus","codepoint":"F1100","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"E1733CFB-12E3-436F-A0EC-F75AE38BAEDB","name":"link-variant-remove","codepoint":"F1101","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"248F9A0F-7732-4FC9-8E64-2E4B47BBFDCD","name":"linkedin","codepoint":"F033B","aliases":[],"tags":["Brand \/ Logo","Social Media"],"author":"Contributors","version":"1.5.54"},{"id":"A58FE3A3-BC2C-48A4-8146-0D15F1B80128","name":"linux","codepoint":"F033D","aliases":["tux"],"tags":["Animal","Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"608E356A-A5F0-4992-BE8D-E99CCC533FC7","name":"linux-mint","codepoint":"F08ED","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.3.50"},{"id":"95390315-999E-4E82-8D89-CDF89AE6478F","name":"lipstick","codepoint":"F13B5","aliases":[],"tags":["Health \/ Beauty"],"author":"Contributors","version":"5.0.45"},{"id":"CC9CEDB3-55DE-4CCA-B31F-888383F6C69E","name":"list-status","codepoint":"F15AB","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"5.5.55"},{"id":"1EB3C314-463F-488D-9DC6-3589C661984E","name":"litecoin","codepoint":"F0A61","aliases":[],"tags":["Banking","Brand \/ Logo","Currency"],"author":"Contributors","version":"2.6.95"},{"id":"205A2FF1-8827-4D3D-8580-FF7FFCD5232C","name":"loading","codepoint":"F0772","aliases":[],"tags":[],"author":"Kateryna Porshnieva","version":"1.9.32"},{"id":"2D8B2899-C765-48CF-9AEA-64327CB14542","name":"location-enter","codepoint":"F0FC4","aliases":["presence-enter"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.0.96"},{"id":"83A1C782-63D7-476B-8A6D-A694F29AE3A9","name":"location-exit","codepoint":"F0FC5","aliases":["presence-exit"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.0.96"},{"id":"D711AFDE-2B8D-4932-82AC-A04E7B2810AE","name":"lock","codepoint":"F033E","aliases":["https","password","secure","protected","encryption"],"tags":["Lock","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"6AFF2FDC-D4F8-41F6-8B80-908D1AB87424","name":"lock-alert","codepoint":"F08EE","aliases":["lock-warning","password-alert","encryption-alert","password-warning","encryption-warning"],"tags":["Lock","Alert \/ Error","Home Automation"],"author":"Simran","version":"2.3.50"},{"id":"6DE0B795-B0C1-4CFC-A47E-0D1C3A203248","name":"lock-alert-outline","codepoint":"F15D1","aliases":["lock-warning-outline","password-alert-outline","encryption-alert-outline","password-warning-outline","encryption-warning-outline"],"tags":["Home Automation","Alert \/ Error","Lock"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"CA254138-2001-4A37-8D52-E65D608E0E10","name":"lock-check","codepoint":"F139A","aliases":["password-check","password-secure","encryption-check","encryption-secure","password-verified","encryption-verified"],"tags":["Lock"],"author":"Fran\u00e7ois Risoud","version":"5.0.45"},{"id":"4A17CD48-4EFA-41A5-9A40-4BF9C01F2B18","name":"lock-check-outline","codepoint":"F16A8","aliases":["password-check-outline","password-secure-outline","encryption-check-outline","encryption-secure-outline","password-verified-outline","encryption-verified-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"C16C2563-9EA4-4545-9CF4-56C5EA9FD9F9","name":"lock-clock","codepoint":"F097F","aliases":["confidential-mode","password-clock","password-expiration","encryption-expiration"],"tags":["Lock","Date \/ Time"],"author":"Google","version":"2.4.85"},{"id":"1C00C37C-183D-41D7-ACEF-18ACFF70DE80","name":"lock-minus","codepoint":"F16A9","aliases":["password-minus","encryption-minus"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"073A5F44-B5D1-4112-AD20-1F86F94ADF60","name":"lock-minus-outline","codepoint":"F16AA","aliases":["password-minus-outline","encryption-minus"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"481E2C2A-E70D-4323-867E-5632966B9555","name":"lock-off","codepoint":"F1671","aliases":["password-off","not-protected","unsecure","encryption-off"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"AAC1BB51-BA46-4FB6-B901-F602E7C55351","name":"lock-off-outline","codepoint":"F1672","aliases":["password-off-outline","unsecure-outline","not-protected-outline","encryption-off-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"E357D5CD-7E42-463B-899A-7D7B038A3E31","name":"lock-open","codepoint":"F033F","aliases":["unlocked","decrypted"],"tags":["Lock","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"D8707612-8DFB-4F83-9FAE-2058254A651F","name":"lock-open-alert","codepoint":"F139B","aliases":["unlocked-alert","decrypted-alert","lock-open-warning","unlocked-warning","decrypted-warning"],"tags":["Alert \/ Error","Home Automation","Lock"],"author":"Fran\u00e7ois Risoud","version":"5.0.45"},{"id":"47EFC7F8-698E-4466-8EDE-DB6334FE6C18","name":"lock-open-alert-outline","codepoint":"F15D2","aliases":["unlocked-alert-outline","lock-open-warning-outline","decrypted-alert-outline","unlocked-warning-outline","decrypted-warning-outline"],"tags":["Home Automation","Alert \/ Error","Lock"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"5ED06AF8-75C7-4AC3-962E-F742236AFDA6","name":"lock-open-check","codepoint":"F139C","aliases":["unlocked-check","decrypted-check"],"tags":["Lock"],"author":"Fran\u00e7ois Risoud","version":"5.0.45"},{"id":"FA8CFB4F-319F-42BE-8615-B4FECDA27719","name":"lock-open-check-outline","codepoint":"F16AB","aliases":["unlocked-check-outline","decrypted-check-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"5487A862-47C1-445A-B6F4-16AAAD6D058B","name":"lock-open-minus","codepoint":"F16AC","aliases":["unlocked-minus","decrypted-minus"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"A268FC79-9328-4B33-A734-9A4614BB3776","name":"lock-open-minus-outline","codepoint":"F16AD","aliases":["unlocked-minus-outline","decrypted-minus-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"DCE8B967-BCDE-4130-8BF3-DDA78A78326F","name":"lock-open-outline","codepoint":"F0340","aliases":["unlocked-outline","decrypted-outline"],"tags":["Lock","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"8062D7E8-C9C1-42E1-B42F-E5A9618F1DCD","name":"lock-open-plus","codepoint":"F16AE","aliases":["unlocked-plus","decrypted-plus","lock-open-add","unlocked-add","decrypted-add"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"804F39C9-F4EB-4663-8EA6-67F668C8CCDF","name":"lock-open-plus-outline","codepoint":"F16AF","aliases":["unlocked-plus-outline","lock-open-add-outline","unlocked-add-outline","decrypted-plus-outline","decrypted-add-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"DBA50293-BCD6-4CC6-81E7-E63AF1EB56AE","name":"lock-open-remove","codepoint":"F16B0","aliases":["unlocked-remove","decrypted-remove"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"73C80D40-9B24-42A8-A22A-94DDE61DDCFC","name":"lock-open-remove-outline","codepoint":"F16B1","aliases":["unlocked-remove-outline","decrypted-remove-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"4171E1EE-CA1A-4885-B41B-3EAE135BA8FE","name":"lock-open-variant","codepoint":"F0FC6","aliases":["unlocked-variant","decrypted-variant"],"tags":["Lock","Home Automation"],"author":"GreenTurtwig","version":"4.0.96"},{"id":"D3253799-FA57-4E62-967B-088FD6F1BF62","name":"lock-open-variant-outline","codepoint":"F0FC7","aliases":["unlocked-variant-outline","decrypted-variant-outline"],"tags":["Lock","Home Automation"],"author":"GreenTurtwig","version":"4.0.96"},{"id":"86AD97CA-6028-45C2-8C9A-8C4A562A8E49","name":"lock-outline","codepoint":"F0341","aliases":["password-outline","secure-outline","https-outline","protected-outline","encryption-outline"],"tags":["Lock","Home Automation","Automotive"],"author":"Google","version":"1.5.54"},{"id":"6921C166-7D1E-44E4-90B9-ADF6668DDFB9","name":"lock-pattern","codepoint":"F06EA","aliases":[],"tags":[],"author":"Haley Halcyon","version":"1.8.36"},{"id":"BA4D2E1E-2BCB-4B17-AC02-52C8F34FAEAE","name":"lock-plus","codepoint":"F05FB","aliases":["enhanced-encryption","lock-add","encryption-add","password-add","password-plus","encryption-plus"],"tags":["Lock"],"author":"Colton Wiscombe","version":"1.5.54"},{"id":"A4B343ED-8C07-4BD5-9F01-B360F971D23C","name":"lock-plus-outline","codepoint":"F16B2","aliases":["lock-add-outline","password-plus-outline","password-add-outline","encryption-plus-outline","encryption-add-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"390C2479-98DD-46FB-AA39-CD816E7982C8","name":"lock-question","codepoint":"F08EF","aliases":["forgot-password","password-question","encryption-question"],"tags":["Lock"],"author":"Simran","version":"2.3.50"},{"id":"201B2126-8481-413A-884F-BE6C8C62D531","name":"lock-remove","codepoint":"F16B3","aliases":["password-remove","encryption-remove"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"D5069461-8385-4424-8E19-CE2BEF2C1BAC","name":"lock-remove-outline","codepoint":"F16B4","aliases":["password-remove-outline","encryption-remove-outline"],"tags":["Lock"],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"82312B48-E128-494E-9D84-DAACB41986F4","name":"lock-reset","codepoint":"F0773","aliases":["password-reset","encryption-reset"],"tags":["Lock"],"author":"Google","version":"1.9.32"},{"id":"1D8C9A6B-26F4-45E1-B922-E0BAED0A5FBD","name":"lock-smart","codepoint":"F08B2","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.2.43"},{"id":"B8B0EAF4-369F-412A-A092-4AA85BBE77FD","name":"locker","codepoint":"F07D7","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"4A5533A8-402C-45F2-9D7A-A8949C22C33B","name":"locker-multiple","codepoint":"F07D8","aliases":["lockers"],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"63D8BFA5-7AE4-4002-A4C2-C464638C38FC","name":"login","codepoint":"F0342","aliases":["log-in","sign-in"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B590AA80-D315-4344-8036-8FBC25C87D2C","name":"login-variant","codepoint":"F05FC","aliases":["log-in-variant","sign-in-variant"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"47DF41F2-49C7-4081-8419-F49C7894E7F1","name":"logout","codepoint":"F0343","aliases":["log-out","sign-out"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"FD2A4CE0-AD1F-45D4-B487-BB6E57F2143F","name":"logout-variant","codepoint":"F05FD","aliases":["log-out-variant","sign-out-variant"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"F4604109-DEBB-424C-9972-9ACFF76BBEC7","name":"longitude","codepoint":"F0F5A","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Richins","version":"3.9.97"},{"id":"3633613A-B8A7-49D0-8C1B-5415EC76F426","name":"looks","codepoint":"F0344","aliases":["rainbow"],"tags":["Weather","Color"],"author":"Google","version":"1.5.54"},{"id":"8DD7B5D3-1361-460A-8029-6948337CC153","name":"lotion","codepoint":"F1582","aliases":[],"tags":["Medical \/ Hospital","Health \/ Beauty"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"DB23DCE8-81D6-449E-B6C2-E29804FFF3BD","name":"lotion-outline","codepoint":"F1583","aliases":[],"tags":["Medical \/ Hospital","Health \/ Beauty"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"74C0DC3D-4DE3-4E67-9100-0B59F2B9A6B2","name":"lotion-plus","codepoint":"F1584","aliases":["hand-sanitizer"],"tags":["Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"85DF6891-1BE0-4D66-8728-553846F98B1F","name":"lotion-plus-outline","codepoint":"F1585","aliases":["hand-sanitizer-outline"],"tags":["Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"DB75FD27-01F6-4232-AA23-86C115751A0C","name":"loupe","codepoint":"F0345","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"235EF258-40BB-47C3-9D5F-1497A7FD34D9","name":"lumx","codepoint":"F0346","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"6E54F325-2998-4301-9062-8770A4868453","name":"lungs","codepoint":"F1084","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"65B3A914-578A-468F-95C1-9C2B6D0C3A52","name":"magnet","codepoint":"F0347","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"3A386A5A-35AC-4760-9384-33A9A43CF584","name":"magnet-on","codepoint":"F0348","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"C2889545-7F08-4AE1-9142-ECF9B79957E1","name":"magnify","codepoint":"F0349","aliases":["search"],"tags":["Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"C48FDEBE-952C-4B4A-9EB8-47A18186EB0B","name":"magnify-close","codepoint":"F0980","aliases":[],"tags":[],"author":"Michael Richins","version":"2.4.85"},{"id":"36D3966F-BFA2-407B-BF36-D21FBA930930","name":"magnify-minus","codepoint":"F034A","aliases":["zoom-out","search-minus"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"616EA8BF-F84A-41BC-A933-5A4AF1E4E793","name":"magnify-minus-cursor","codepoint":"F0A62","aliases":["zoom-out-cursor"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"9E259697-7035-4E17-82D6-431C74215E67","name":"magnify-minus-outline","codepoint":"F06EC","aliases":["zoom-out-outline","search-minus-outline"],"tags":["Geographic Information System"],"author":"Google","version":"1.8.36"},{"id":"798F7C9D-2EC7-47EF-8729-845B4E2DDD16","name":"magnify-plus","codepoint":"F034B","aliases":["zoom-in","magnify-add","search-plus","search-add"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"950E718A-089B-4266-AAFA-B9FA8BB0D3B3","name":"magnify-plus-cursor","codepoint":"F0A63","aliases":["zoom-in-cursor","magnify-add-cursor"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"521EC414-ECAD-435D-BAE3-4CF772659845","name":"magnify-plus-outline","codepoint":"F06ED","aliases":["zoom-in-outline","magnify-add-outline","search-plus-outline","search-add-outline"],"tags":["Geographic Information System"],"author":"Google","version":"1.8.36"},{"id":"845BBEA5-F20E-4E1B-AB42-FE7BF45FCDAB","name":"magnify-remove-cursor","codepoint":"F120C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"1465D0D4-32FE-4495-B137-CFE49A390474","name":"magnify-remove-outline","codepoint":"F120D","aliases":[],"tags":["Geographic Information System"],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"DF9ACF3F-5AF0-4F55-845C-569018942B95","name":"magnify-scan","codepoint":"F1276","aliases":[],"tags":[],"author":"Sascha Wohlgemuth","version":"4.7.95"},{"id":"269E49C3-261D-42CD-8EFA-FD76C0BA7B7C","name":"mail","codepoint":"F0EBB","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"CCEA599C-8CED-4D49-83FB-7AC452AADFA0","name":"mailbox","codepoint":"F06EE","aliases":[],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"E1072975-827C-4320-A7D9-AEEADA1BCAD9","name":"mailbox-open","codepoint":"F0D88","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"B5D3F2A9-4CF7-4030-8909-482E23D3A8DC","name":"mailbox-open-outline","codepoint":"F0D89","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"01EC4EC7-B90D-4E1E-B3CF-E9B2E9C16077","name":"mailbox-open-up","codepoint":"F0D8A","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"793AC378-1C34-4882-B3A7-6ACA108ACE76","name":"mailbox-open-up-outline","codepoint":"F0D8B","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"69A2883B-C904-4769-898E-8BAEB8F8309C","name":"mailbox-outline","codepoint":"F0D8C","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"C378F407-C2C4-48CD-9AA3-22B6C4C0E0AF","name":"mailbox-up","codepoint":"F0D8D","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"D9ECA2BA-AFCB-46C8-9EC4-3155063670CC","name":"mailbox-up-outline","codepoint":"F0D8E","aliases":[],"tags":[],"author":"Michael Richins","version":"3.4.93"},{"id":"75EE1BFB-90E7-4500-A7E1-72E898059E16","name":"manjaro","codepoint":"F160A","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"5.6.55"},{"id":"99738FF8-01AE-420D-8481-8B9E1402255B","name":"map","codepoint":"F034D","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"39D94D7A-D161-409F-8FFC-889474A4DCE9","name":"map-check","codepoint":"F0EBC","aliases":["map-tick"],"tags":["Navigation","Geographic Information System"],"author":"Contributors","version":"3.7.94"},{"id":"8EF339C7-1106-40FC-B2CC-3387F915824E","name":"map-check-outline","codepoint":"F0EBD","aliases":["map-tick-outline"],"tags":["Navigation","Geographic Information System"],"author":"Contributors","version":"3.7.94"},{"id":"A3A8668B-BEF0-48CC-AEB1-ACC765D10CC0","name":"map-clock","codepoint":"F0D1E","aliases":["timezone"],"tags":["Navigation","Geographic Information System","Date \/ Time"],"author":"Augustin Ursu","version":"3.3.92"},{"id":"EEB984B2-6639-452D-AD56-06A8EC862EE4","name":"map-clock-outline","codepoint":"F0D1F","aliases":["timezone-outline"],"tags":["Navigation","Geographic Information System","Date \/ Time"],"author":"Augustin Ursu","version":"3.3.92"},{"id":"69651FB0-089C-4D57-8465-46716D86DBCA","name":"map-legend","codepoint":"F0A01","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Perth Totty","version":"2.5.94"},{"id":"379B9D93-434B-46E7-9ABC-CAFAB694B209","name":"map-marker","codepoint":"F034E","aliases":["location","address-marker","location-on","place","room"],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"DE87F14C-101D-47F2-87C5-118BE76F7C58","name":"map-marker-alert","codepoint":"F0F05","aliases":[],"tags":["Navigation","Alert \/ Error","Geographic Information System"],"author":"Fran\u00e7ois Risoud","version":"3.8.95"},{"id":"65B4F317-EB12-4BD4-8E9B-C6D3A153B868","name":"map-marker-alert-outline","codepoint":"F0F06","aliases":[],"tags":["Navigation","Alert \/ Error","Geographic Information System"],"author":"Fran\u00e7ois Risoud","version":"3.8.95"},{"id":"FA10B579-AC1E-48F7-BF8C-AB7F1380F3F9","name":"map-marker-check","codepoint":"F0C95","aliases":["map-marker-tick","where-to-vote"],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"3.2.89"},{"id":"76C82A3D-F79E-46D9-8234-456F39A35567","name":"map-marker-check-outline","codepoint":"F12FB","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"03F79839-314C-4F29-B3E3-43B97D7F7FA6","name":"map-marker-circle","codepoint":"F034F","aliases":["explore-nearby"],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"B2FF0F5A-4B2C-480C-9022-D84AD78E72ED","name":"map-marker-distance","codepoint":"F08F0","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Richins","version":"2.3.50"},{"id":"6E4368BF-7150-40D2-861B-375421A7774B","name":"map-marker-down","codepoint":"F1102","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Fran\u00e7ois Risoud","version":"4.3.95"},{"id":"5FFC5505-B029-4487-A68E-EDE4B708E5B9","name":"map-marker-left","codepoint":"F12DB","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"0283CCF3-BC73-4642-92FA-38E62D635368","name":"map-marker-left-outline","codepoint":"F12DD","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"34DD1168-3875-4F77-9C0B-5BCFFB80FBBD","name":"map-marker-minus","codepoint":"F0650","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Simran","version":"1.6.50"},{"id":"21A7EBBF-D884-4A4E-B722-01600B89FFB4","name":"map-marker-minus-outline","codepoint":"F12F9","aliases":[],"tags":["Geographic Information System","Navigation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"6283577D-6B31-4297-8747-4F466580E79A","name":"map-marker-multiple","codepoint":"F0350","aliases":["map-markers"],"tags":["Navigation","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"360866E5-D407-4E54-9470-7ECF6759F941","name":"map-marker-multiple-outline","codepoint":"F1277","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Austin Andrews","version":"4.7.95"},{"id":"92410469-09D9-4C29-AC79-CD0DF882D05F","name":"map-marker-off","codepoint":"F0351","aliases":["location-off"],"tags":["Navigation","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"48218DC3-F2A6-4C4B-9B5E-0648815B8864","name":"map-marker-off-outline","codepoint":"F12FD","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"DE8F4623-A6D4-4DD4-B61A-5936A0538FD2","name":"map-marker-outline","codepoint":"F07D9","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"2.0.46"},{"id":"A20F1915-26FB-41BD-A407-B73A90936E76","name":"map-marker-path","codepoint":"F0D20","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Austin Andrews","version":"3.3.92"},{"id":"40CBD1A1-11E1-44A6-8627-6F7C658F5E0F","name":"map-marker-plus","codepoint":"F0651","aliases":["add-location"],"tags":["Navigation","Geographic Information System"],"author":"Simran","version":"1.6.50"},{"id":"C1F80E9D-2408-46FC-9E92-AE61A8D5C650","name":"map-marker-plus-outline","codepoint":"F12F8","aliases":[],"tags":["Geographic Information System","Navigation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"C9930FE9-E831-4194-A4FA-905CE141CFEA","name":"map-marker-question","codepoint":"F0F07","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"3.8.95"},{"id":"0F3F436D-95BF-4578-A209-CF8B26DEDA15","name":"map-marker-question-outline","codepoint":"F0F08","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"3.8.95"},{"id":"8F346B27-607A-4C98-B83E-C32E921D0468","name":"map-marker-radius","codepoint":"F0352","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"865AB612-D546-431D-85A8-52C305B263F8","name":"map-marker-radius-outline","codepoint":"F12FC","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"8BC7ABEC-FE5F-4C2F-889C-8C8804DD12E4","name":"map-marker-remove","codepoint":"F0F09","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"GreenTurtwig","version":"3.8.95"},{"id":"75FDE93C-EB66-4824-9F96-1B4212BDA785","name":"map-marker-remove-outline","codepoint":"F12FA","aliases":[],"tags":["Geographic Information System","Navigation"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"D19361A0-41AB-4E11-B4D4-AE50D42B3B2C","name":"map-marker-remove-variant","codepoint":"F0F0A","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"GreenTurtwig","version":"3.8.95"},{"id":"445C4B6D-5A56-42F3-845F-92C22A11BB64","name":"map-marker-right","codepoint":"F12DC","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"9456009F-0387-4A76-8B0F-22CCBBA53071","name":"map-marker-right-outline","codepoint":"F12DE","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"B4FB6A62-C598-4E96-8E09-C6A2145EE24C","name":"map-marker-star","codepoint":"F1608","aliases":["map-marker-favorite"],"tags":["Navigation"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"9B256D01-4CB0-4736-BBB7-6D44417DD02B","name":"map-marker-star-outline","codepoint":"F1609","aliases":["map-marker-favorite-outline"],"tags":["Navigation"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"0C1B9015-C0F4-4710-87D2-BA7B710943F2","name":"map-marker-up","codepoint":"F1103","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Fran\u00e7ois Risoud","version":"4.3.95"},{"id":"3C2F6429-F2F9-49A9-AF23-DD33413D2619","name":"map-minus","codepoint":"F0981","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Peter Noble","version":"2.4.85"},{"id":"164AE88B-F990-471C-8663-EFDC05BA14F0","name":"map-outline","codepoint":"F0982","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"Google","version":"2.4.85"},{"id":"3D7A000E-3E94-4B9B-8CAB-2F6923D425B7","name":"map-plus","codepoint":"F0983","aliases":["map-add"],"tags":["Navigation","Geographic Information System"],"author":"Peter Noble","version":"2.4.85"},{"id":"6FB911AA-DE27-441D-8C62-CD97ECB99DA7","name":"map-search","codepoint":"F0984","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"4EDC2B6E-3E09-41BF-B08C-EB75CEBFFB96","name":"map-search-outline","codepoint":"F0985","aliases":[],"tags":["Navigation","Geographic Information System"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"061C11C7-55DC-4F79-989C-81756790342A","name":"mapbox","codepoint":"F0BAA","aliases":[],"tags":[],"author":"Contributors","version":"3.0.39"},{"id":"4A7710D4-41B8-4D98-A5B9-591943C3B3EF","name":"margin","codepoint":"F0353","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"71E6D8F0-A3D2-43CB-8940-16AA4E1D9825","name":"marker","codepoint":"F0652","aliases":["highlighter"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.6.50"},{"id":"CFB791C3-6476-418F-80D4-7B8C5A6D1350","name":"marker-cancel","codepoint":"F0DD9","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"74C5E15E-D227-4272-94E6-EDFDD0F66C9A","name":"marker-check","codepoint":"F0355","aliases":["beenhere","marker-tick"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"7DA03280-B018-4813-973A-9CBC0F6C462B","name":"mastodon","codepoint":"F0AD1","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.7.94"},{"id":"224604D9-8F3D-454A-B11F-D4C00231B15B","name":"material-design","codepoint":"F0986","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"878C7F4D-DAD0-4334-A3AA-695FD3AD5391","name":"material-ui","codepoint":"F0357","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"10E7FA7C-8451-44B9-979F-1916AAC7FE28","name":"math-compass","codepoint":"F0358","aliases":["maths-compass"],"tags":["Math","Drawing \/ Art"],"author":"Gabriel","version":"1.5.54"},{"id":"6C00C0F3-F537-4591-B7BA-752A1CCD7E38","name":"math-cos","codepoint":"F0C96","aliases":["math-cosine","maths-cos"],"tags":["Math"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"E911AE3C-8505-42CD-889B-0EE3BEDC3B0D","name":"math-integral","codepoint":"F0FC8","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"0C6E8DE8-731B-451C-809A-22BFF1DADE36","name":"math-integral-box","codepoint":"F0FC9","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"DD9D199B-D026-4771-8028-A813A3893CDE","name":"math-log","codepoint":"F1085","aliases":[],"tags":["Math"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"6C9569E6-55F1-48AF-A11C-2284315D0CE6","name":"math-norm","codepoint":"F0FCA","aliases":["code-or","parallel"],"tags":["Math","Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"4FBD0287-AD44-452B-A97A-E5FDD3542A1F","name":"math-norm-box","codepoint":"F0FCB","aliases":["code-or-box","parallel-box"],"tags":["Math","Developer \/ Languages"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"CB473E87-BD2F-4416-A36E-6C4C12194D14","name":"math-sin","codepoint":"F0C97","aliases":["math-sine","maths-sin"],"tags":["Math"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"47194CCD-AF78-430F-AD95-4D564D6E1D18","name":"math-tan","codepoint":"F0C98","aliases":["math-tangent","maths-tan"],"tags":["Math"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"5D5ED3F2-71BD-44B6-B4BB-61D73211335F","name":"matrix","codepoint":"F0628","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"626FA95C-E655-44A6-BA6A-4B60CED44B6D","name":"medal","codepoint":"F0987","aliases":["award"],"tags":["Gaming \/ RPG","Sport"],"author":"Michael Richins","version":"2.4.85"},{"id":"22F9B575-7D95-46A3-BA55-625B12E75AC2","name":"medal-outline","codepoint":"F1326","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"4.9.95"},{"id":"7F6DF58A-C9A3-4CE7-9664-28C04218C628","name":"medical-bag","codepoint":"F06EF","aliases":["first-aid-kit","medicine"],"tags":["Medical \/ Hospital"],"author":"Thomas Hunsaker","version":"1.8.36"},{"id":"B68AA118-B8B5-4A2A-BCA2-A12C8C119319","name":"meditation","codepoint":"F117B","aliases":[],"tags":["Sport"],"author":"Google","version":"4.4.95"},{"id":"E404434E-17DB-4E90-9D97-5355258E1FCF","name":"memory","codepoint":"F035B","aliases":["chip"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"0BD2CD08-CCFB-4EC3-B96D-08B0B8230A91","name":"menu","codepoint":"F035C","aliases":["hamburger-menu"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"624A47B1-947E-45AD-A34F-D5DCC1143C5A","name":"menu-down","codepoint":"F035D","aliases":["arrow-drop-down","caret-down"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"EE6F8AAE-7856-4E4C-AC01-3589A2C66D98","name":"menu-down-outline","codepoint":"F06B6","aliases":["caret-down-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.7.22"},{"id":"91F83E23-FD44-4277-BD91-037B3D7EB72E","name":"menu-left","codepoint":"F035E","aliases":["arrow-left"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BC54AA3D-A450-4079-B40C-457FAE2211D5","name":"menu-left-outline","codepoint":"F0A02","aliases":[],"tags":[],"author":"Peter Noble","version":"2.5.94"},{"id":"AEB414A7-E7A2-46D6-BAA3-CAFA4E06DA38","name":"menu-open","codepoint":"F0BAB","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"51157881-5A20-4D7D-8E5F-FB0E815C9B3D","name":"menu-right","codepoint":"F035F","aliases":["arrow-right"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DFE8FD81-B967-4E07-A1C9-44A608613E26","name":"menu-right-outline","codepoint":"F0A03","aliases":[],"tags":[],"author":"Peter Noble","version":"2.5.94"},{"id":"6B937FF1-FF63-4829-8BAE-D5E4D1EB64A0","name":"menu-swap","codepoint":"F0A64","aliases":[],"tags":["Arrow"],"author":"GreenTurtwig","version":"2.6.95"},{"id":"AAADBDE7-CC0D-4F69-A795-B38C0B00DC62","name":"menu-swap-outline","codepoint":"F0A65","aliases":[],"tags":["Arrow"],"author":"GreenTurtwig","version":"2.6.95"},{"id":"A526C6AC-3E29-49D1-91FA-07F95B470626","name":"menu-up","codepoint":"F0360","aliases":["arrow-drop-up","caret-up"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"33B1FB6B-D4F4-4B76-820C-4A2B075DB1B3","name":"menu-up-outline","codepoint":"F06B7","aliases":["caret-up-outline"],"tags":["Arrow"],"author":"Austin Andrews","version":"1.7.22"},{"id":"0D0E7E15-9615-4A66-8933-8BC98675AE3D","name":"merge","codepoint":"F0F5C","aliases":[],"tags":[],"author":"Google","version":"3.9.97"},{"id":"99DA4752-8C79-44D8-8286-6EBD696F0B45","name":"message","codepoint":"F0361","aliases":["chat-bubble"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"213A797A-41C0-4804-A5B1-A841898CCC11","name":"message-alert","codepoint":"F0362","aliases":["feedback","message-warning","announcement","sms-failed"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"3487FE3E-2B9B-4C69-B64C-B3E699E9EC8C","name":"message-alert-outline","codepoint":"F0A04","aliases":["announcement-outline","feedback-outline","message-warning-outline","sms-failed-outline"],"tags":["Alert \/ Error"],"author":"Colton Wiscombe","version":"2.5.94"},{"id":"F359CA31-2575-4648-B1E1-466A757F2184","name":"message-arrow-left","codepoint":"F12F2","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"EAF47F59-C768-4B46-841F-1D8C216D15F2","name":"message-arrow-left-outline","codepoint":"F12F3","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"3292CBC5-7E1D-405F-A8CD-BAB528B88D45","name":"message-arrow-right","codepoint":"F12F4","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"BEDCDC33-9EAE-46D2-B380-80A6B47B400C","name":"message-arrow-right-outline","codepoint":"F12F5","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"80D7EBEA-4C3B-43B9-8181-BEEE728D5D90","name":"message-bookmark","codepoint":"F15AC","aliases":[],"tags":[],"author":"Google","version":"5.5.55"},{"id":"94793E49-C5C4-47A8-87FD-215A923ACA2A","name":"message-bookmark-outline","codepoint":"F15AD","aliases":[],"tags":[],"author":"Google","version":"5.5.55"},{"id":"1EC9427A-2A02-4F74-9C1B-C4EC5E62B793","name":"message-bulleted","codepoint":"F06A2","aliases":["speaker-notes"],"tags":[],"author":"Google","version":"1.7.12"},{"id":"5AAB267C-9A9C-4966-862D-A2AC910494E5","name":"message-bulleted-off","codepoint":"F06A3","aliases":["speaker-notes-off"],"tags":[],"author":"Google","version":"1.7.12"},{"id":"F0F27B00-3C37-4AC0-B8D7-DB2554894079","name":"message-cog","codepoint":"F06F1","aliases":[],"tags":["Settings"],"author":"Michael Richins","version":"1.8.36"},{"id":"B4FCC7EE-5464-4713-A4F4-8C0CA0E9472E","name":"message-cog-outline","codepoint":"F1172","aliases":[],"tags":["Settings"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"6434A4B3-F803-4C8B-A03C-BE39E947166B","name":"message-draw","codepoint":"F0363","aliases":["rate-review"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A9181976-10D1-4CB7-993E-AE8B7DEDEC64","name":"message-flash","codepoint":"F15A9","aliases":["message-quick"],"tags":[],"author":"Google","version":"5.5.55"},{"id":"DA7B2430-9A55-42D5-AE19-92E108303E79","name":"message-flash-outline","codepoint":"F15AA","aliases":["message-quick-outline"],"tags":[],"author":"Google","version":"5.5.55"},{"id":"C4C9B194-78C3-47FB-ABF6-5129230527AC","name":"message-image","codepoint":"F0364","aliases":["mms"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"9C0BC648-202E-476E-A034-48C03F7554BF","name":"message-image-outline","codepoint":"F116C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"953DF020-3B6E-44ED-B858-A220EC7BE82A","name":"message-lock","codepoint":"F0FCC","aliases":["message-secure"],"tags":["Lock"],"author":"Simran","version":"4.0.96"},{"id":"D7D6AAFB-1292-4EA1-A067-728532693834","name":"message-lock-outline","codepoint":"F116D","aliases":[],"tags":["Lock"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"CF8F9CE5-0B38-4412-A3DD-F9E333C23EF6","name":"message-minus","codepoint":"F116E","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"B5CAE2E8-8D8A-4E7C-AAD3-F5EFDE92A8F7","name":"message-minus-outline","codepoint":"F116F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"1F9E05D2-75B6-4039-B0A8-9EF2B647882E","name":"message-off","codepoint":"F164D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"2B210400-A3CE-4EE4-8A9B-A88ACDF47061","name":"message-off-outline","codepoint":"F164E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"2AE3707D-5DE3-41E6-968B-A56D3D9ADD40","name":"message-outline","codepoint":"F0365","aliases":["chat-bubble-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"C0B4CC94-B6B5-462F-93C2-98F07093614C","name":"message-plus","codepoint":"F0653","aliases":["message-add"],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"47A1A8D9-33C6-4EF4-9F8B-C327A7F45F65","name":"message-plus-outline","codepoint":"F10BB","aliases":[],"tags":[],"author":"Contributors","version":"4.2.95"},{"id":"602EE454-C61C-4608-919E-FCCF3B58DE65","name":"message-processing","codepoint":"F0366","aliases":["sms","textsms"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"21EDB8E6-9829-4028-9A40-F03BF23C14DA","name":"message-processing-outline","codepoint":"F1170","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"088D1765-3A4B-4BCB-A17B-B07970B3DDAA","name":"message-question","codepoint":"F173A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"32AA3ACF-FADE-4ECB-8A16-DECB4CB9ECB9","name":"message-question-outline","codepoint":"F173B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"6657779A-7238-4686-B3D5-1244862D7B2C","name":"message-reply","codepoint":"F0367","aliases":["mode-comment"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"9B0263DD-74DB-4AC6-BF1C-0C7C0170C845","name":"message-reply-outline","codepoint":"F173D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"FF34C5A8-4433-4B47-A9E5-EB836CFFCEC9","name":"message-reply-text","codepoint":"F0368","aliases":["comment","insert-comment"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"56D756E1-57CB-4EA5-9AC3-409D0046C643","name":"message-reply-text-outline","codepoint":"F173E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"4B15BF16-CD96-4427-9EA4-5A8B09F3A2B6","name":"message-settings","codepoint":"F06F0","aliases":[],"tags":["Settings"],"author":"Michael Richins","version":"1.8.36"},{"id":"28C31415-ECC5-4192-A04A-C3C1F810019B","name":"message-settings-outline","codepoint":"F1171","aliases":[],"tags":["Settings"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"D2AFF074-2CE4-442D-AF1A-64B168BC622A","name":"message-text","codepoint":"F0369","aliases":["chat"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BF83F7B1-BA68-4443-9FD1-FB0A9C8D9D60","name":"message-text-clock","codepoint":"F1173","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"461285B8-FAB1-46BA-95C5-611476333EE4","name":"message-text-clock-outline","codepoint":"F1174","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"362401F1-947F-45FD-8047-F515CB2F7C44","name":"message-text-lock","codepoint":"F0FCD","aliases":["message-text-secure"],"tags":["Lock"],"author":"Simran","version":"4.0.96"},{"id":"223FE0D4-F0C4-426A-8784-72F28455AB67","name":"message-text-lock-outline","codepoint":"F1175","aliases":[],"tags":["Lock"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"E8C7D2D2-5B78-40E9-A3E6-51B9C31A43F8","name":"message-text-outline","codepoint":"F036A","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"7AEB07C3-0EFC-4D74-BB5B-2EB1288DC27D","name":"message-video","codepoint":"F036B","aliases":["voice-chat"],"tags":["Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"78644A46-55EA-4208-B3DC-89C79B5F96A5","name":"meteor","codepoint":"F0629","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.6.50"},{"id":"13256CBF-E284-4229-AAB9-5612FBADD060","name":"metronome","codepoint":"F07DA","aliases":["tempo","bpm","beats-per-minute"],"tags":["Music"],"author":"Haley Halcyon","version":"2.0.46"},{"id":"43A2B10E-F7DF-4181-B607-EC2039AFFA0D","name":"metronome-tick","codepoint":"F07DB","aliases":["tempo-tick","bpm-tick","beats-per-minute-tick"],"tags":["Music"],"author":"Haley Halcyon","version":"2.0.46"},{"id":"6A3136A3-62AD-4DE6-A783-D9D69AAD8919","name":"micro-sd","codepoint":"F07DC","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.0.46"},{"id":"18C99959-2A0E-4095-BAEA-F5B266377648","name":"microphone","codepoint":"F036C","aliases":["keyboard-voice"],"tags":["Music"],"author":"Google","version":"1.5.54"},{"id":"FFAA9F2E-96F9-43A3-BC4E-F7562703E6A1","name":"microphone-minus","codepoint":"F08B3","aliases":["microphone-remove"],"tags":[],"author":"Michael Richins","version":"2.2.43"},{"id":"90AD0141-2243-49F0-8B84-FF909244D237","name":"microphone-off","codepoint":"F036D","aliases":["mic-off"],"tags":["Music"],"author":"Google","version":"1.5.54"},{"id":"E152DB47-F7EE-42A5-A01B-DC5E54A525D8","name":"microphone-outline","codepoint":"F036E","aliases":["mic-none"],"tags":["Music"],"author":"Google","version":"1.5.54"},{"id":"61F84878-9DAD-45D9-8A79-65143EA32F37","name":"microphone-plus","codepoint":"F08B4","aliases":["microphone-add"],"tags":[],"author":"Michael Richins","version":"2.2.43"},{"id":"E8F70177-01CF-4C20-9956-DCA7B331FED6","name":"microphone-settings","codepoint":"F036F","aliases":["settings-voice"],"tags":["Settings"],"author":"Google","version":"1.5.54"},{"id":"5824EE2F-01BA-42E7-A943-B0D1C569B2C5","name":"microphone-variant","codepoint":"F0370","aliases":[],"tags":["Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B0811263-2D40-44D9-945D-13393A170311","name":"microphone-variant-off","codepoint":"F0371","aliases":[],"tags":["Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CFCFD9FE-AFF3-4D4F-A7C6-A40E0886B064","name":"microscope","codepoint":"F0654","aliases":[],"tags":["Science"],"author":"Simran","version":"1.6.50"},{"id":"4636AAFF-A0E5-494C-8630-31142B4A2F48","name":"microsoft","codepoint":"F0372","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"94560EAB-E027-4462-BBD8-C6921D90CC07","name":"microsoft-access","codepoint":"F138E","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"5.0.45"},{"id":"7701BECC-343D-4BE8-B33A-B88ABACA8F26","name":"microsoft-azure","codepoint":"F0805","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.19"},{"id":"67025D74-AB54-43B5-82EE-085CCDA019E6","name":"microsoft-azure-devops","codepoint":"F0FD5","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"4.2.95"},{"id":"CB038F2A-85DE-4F59-B694-D4805D66322B","name":"microsoft-bing","codepoint":"F00A4","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"9846C329-0B20-40A4-9362-D350C063F53C","name":"microsoft-dynamics-365","codepoint":"F0988","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.4.85"},{"id":"C2D33448-5C6E-41D9-89B4-65184FF5EE15","name":"microsoft-edge","codepoint":"F01E9","aliases":["microsoft-edge"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"F2B4075E-3226-40CB-9165-2C66A4BB4BBD","name":"microsoft-edge-legacy","codepoint":"F1250","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"4.6.95"},{"id":"ACD47746-F44B-496D-990B-58FC729F372E","name":"microsoft-excel","codepoint":"F138F","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"5.0.45"},{"id":"255BB365-7B2F-46C7-B85E-EFDAD527BB54","name":"microsoft-internet-explorer","codepoint":"F0300","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"7E2456A3-891B-43F4-B233-AA0D890815CF","name":"microsoft-office","codepoint":"F03C6","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"455893F6-D0C4-4257-ABE4-85B1D68F60FF","name":"microsoft-onedrive","codepoint":"F03CA","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"E95EC3DF-2A48-4167-9F22-F4E735D4F298","name":"microsoft-onenote","codepoint":"F0747","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.9.32"},{"id":"0AE81D55-4520-4975-B406-145C74ECF033","name":"microsoft-outlook","codepoint":"F0D22","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"3.3.92"},{"id":"6EA8C442-3C67-4AC3-89F9-C628942CA8E0","name":"microsoft-powerpoint","codepoint":"F1390","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"5.0.45"},{"id":"D4F99553-AAF4-406A-8C02-71850F75E07E","name":"microsoft-sharepoint","codepoint":"F1391","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"5.0.45"},{"id":"390FC04F-F2A9-44F5-9808-6370A647BAF0","name":"microsoft-teams","codepoint":"F02BB","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"E009DA08-136C-465C-8481-308E99BCA3BF","name":"microsoft-visual-studio","codepoint":"F0610","aliases":["visualstudio"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"6D1D5836-B731-41C4-A829-86E5741A0784","name":"microsoft-visual-studio-code","codepoint":"F0A1E","aliases":["vs-code"],"tags":[],"author":"Contributors","version":"2.5.94"},{"id":"6E06B49E-5127-4D5A-9C8B-F58BA8943BC4","name":"microsoft-windows","codepoint":"F05B3","aliases":["microsoft-windows"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.5.54"},{"id":"AD21ACB2-11A5-4C30-907B-FFF1A5904738","name":"microsoft-windows-classic","codepoint":"F0A21","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.5.94"},{"id":"BBB336AA-A225-44EE-B8AA-14AB109C505D","name":"microsoft-word","codepoint":"F1392","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"5.0.45"},{"id":"B7B4ECD9-2895-4E36-88A9-5F3AC5D6C264","name":"microsoft-xbox","codepoint":"F05B9","aliases":["xbox-live","microsoft"],"tags":["Social Media","Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.5.54"},{"id":"74BB58AC-EF8B-447C-A15D-C444F1F67D93","name":"microsoft-xbox-controller","codepoint":"F05BA","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"57F11EDC-2759-4D62-BDD2-C7C3F5199623","name":"microsoft-xbox-controller-battery-alert","codepoint":"F074B","aliases":["xbox-controller-battery-warning"],"tags":["Battery","Gaming \/ RPG","Alert \/ Error"],"author":"Austin Andrews","version":"1.9.32"},{"id":"738FB781-E590-444B-85B8-1773DDC814E9","name":"microsoft-xbox-controller-battery-charging","codepoint":"F0A22","aliases":[],"tags":["Gaming \/ RPG","Battery"],"author":"Contributors","version":"2.5.94"},{"id":"51BB7455-5893-4F47-92D1-B3FD408C2ADC","name":"microsoft-xbox-controller-battery-empty","codepoint":"F074C","aliases":[],"tags":["Battery","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.9.32"},{"id":"CC73B4E7-6B14-459D-AED5-35E50655C05C","name":"microsoft-xbox-controller-battery-full","codepoint":"F074D","aliases":[],"tags":["Battery","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.9.32"},{"id":"B65873D1-4808-4C3C-8AD6-A242D61B1985","name":"microsoft-xbox-controller-battery-low","codepoint":"F074E","aliases":[],"tags":["Battery","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.9.32"},{"id":"2B434E26-4ECE-4654-BBDC-4FE13CCCEE3E","name":"microsoft-xbox-controller-battery-medium","codepoint":"F074F","aliases":[],"tags":["Battery","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.9.32"},{"id":"9CC18C3C-57B6-470C-9F09-80B62ECFABD7","name":"microsoft-xbox-controller-battery-unknown","codepoint":"F0750","aliases":[],"tags":["Battery","Gaming \/ RPG"],"author":"Austin Andrews","version":"1.9.32"},{"id":"03720A4C-EA6B-4D58-B7D8-5A8DA745B125","name":"microsoft-xbox-controller-menu","codepoint":"F0E6F","aliases":[],"tags":["Gaming \/ RPG"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"F73FF165-CE6C-4E27-B492-93F3B82C70EE","name":"microsoft-xbox-controller-off","codepoint":"F05BB","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"38E0BCE2-2A91-4D68-B921-9854E18FFB20","name":"microsoft-xbox-controller-view","codepoint":"F0E70","aliases":[],"tags":["Gaming \/ RPG"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"B74213B2-B220-4D15-AFA5-CAE0E40D6CFE","name":"microsoft-yammer","codepoint":"F0789","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.9.32"},{"id":"62F69C7A-4CBA-444A-8BFE-E5B7A891CF5D","name":"microwave","codepoint":"F0C99","aliases":["microwave-oven"],"tags":["Home Automation","Food \/ Drink"],"author":"GreenTurtwig","version":"3.2.89"},{"id":"8A96C224-F70E-4DBC-996C-57B8591A0D85","name":"microwave-off","codepoint":"F1423","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"EF5AA157-F8E2-47FB-9A9C-8ACC66A9C2FB","name":"middleware","codepoint":"F0F5D","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"3.9.97"},{"id":"3F74E489-26F5-4BC9-8567-8935E8E8559A","name":"middleware-outline","codepoint":"F0F5E","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"3.9.97"},{"id":"57B4C4BB-A8D9-409D-A3A4-E512A4E50CA2","name":"midi","codepoint":"F08F1","aliases":[],"tags":["Brand \/ Logo","Music"],"author":"Contributors","version":"2.3.50"},{"id":"9AA75C8F-4091-4C92-81A9-DA58CC95E794","name":"midi-port","codepoint":"F08F2","aliases":[],"tags":["Music"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"F1D9E59B-F221-46E3-91E9-1D98C478CBF3","name":"mine","codepoint":"F0DDA","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"84402452-AA4A-43D6-A26C-A0946B48310C","name":"minecraft","codepoint":"F0373","aliases":["microsoft-minecraft"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"A2E311D2-225E-4AD7-948D-D27AD0362D9F","name":"mini-sd","codepoint":"F0A05","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"1BFCC4B4-5BA5-4E64-889D-D64B61EA8D81","name":"minidisc","codepoint":"F0A06","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"2CEA6B7B-E7C9-4D52-9D9D-286E50001B70","name":"minus","codepoint":"F0374","aliases":["remove","horizontal-line"],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"6BFAE994-AF2D-4B04-965D-9734631D5F0D","name":"minus-box","codepoint":"F0375","aliases":["indeterminate-check-box"],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"8B150753-A2AC-4750-B6EC-686D213805DE","name":"minus-box-multiple","codepoint":"F1141","aliases":["library-minus"],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"FCAD03B0-9332-41AF-9992-AF53DDDF6BBA","name":"minus-box-multiple-outline","codepoint":"F1142","aliases":["library-minus-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"D37AECEA-5BC3-4C57-8886-BC6C1A86987D","name":"minus-box-outline","codepoint":"F06F2","aliases":["checkbox-indeterminate-outline"],"tags":["Math"],"author":"Google","version":"1.8.36"},{"id":"DDEB98E7-E016-44CA-8DE7-A31969C2CC04","name":"minus-circle","codepoint":"F0376","aliases":["do-not-disturb-on","remove-circle","do-not-enter","pill-tablet","medicine","pharmaceutical"],"tags":["Transportation + Road","Medical \/ Hospital"],"author":"Google","version":"1.5.54"},{"id":"C7561067-F057-4E26-B8F1-791BD24E0A2C","name":"minus-circle-multiple","codepoint":"F035A","aliases":["coins-minus"],"tags":[],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"313B60B3-A740-4F5B-A63E-A5772C20AC0D","name":"minus-circle-multiple-outline","codepoint":"F0AD3","aliases":["coins-minus-outline"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"6A57F7D9-D5F6-42B2-A5E2-D160F7E0DB4B","name":"minus-circle-off","codepoint":"F1459","aliases":["do-not-disturb-off","remove-circle-off","do-not-enter-off"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"2A82D040-8856-437D-B478-DF448C7BE6A6","name":"minus-circle-off-outline","codepoint":"F145A","aliases":["do-not-disturb-off-outline","remove-circle-off-outline","do-not-enter-off-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"E1568BA6-EA0E-478F-933F-102F76996D6C","name":"minus-circle-outline","codepoint":"F0377","aliases":["remove-circle-outline","do-not-enter-outline","do-not-disturb-outline","pill-tablet-outline","medicine-outline","pharmaceutical"],"tags":["Transportation + Road","Medical \/ Hospital"],"author":"Google","version":"1.5.54"},{"id":"F48994C7-4A76-43B8-B851-F7389F8B2B59","name":"minus-network","codepoint":"F0378","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"27A3D3DC-42D9-43CF-B783-8B779BE9AEE6","name":"minus-network-outline","codepoint":"F0C9A","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"7761450F-6D9D-452D-B604-1853124C09E2","name":"minus-thick","codepoint":"F1639","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"AB90BAF0-E671-4418-9CBB-74C3F03A94DB","name":"mirror","codepoint":"F11FD","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"4.6.95"},{"id":"BF0B21D2-7266-4639-B2C4-24199863849D","name":"mixed-martial-arts","codepoint":"F0D8F","aliases":["mma","glove"],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"5E441030-6DAA-42F9-AF03-A4EB86AF0A51","name":"mixed-reality","codepoint":"F087F","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.1.99"},{"id":"9DD7B3EE-91B8-4D42-A781-2B12B0343C0B","name":"molecule","codepoint":"F0BAC","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"3.0.39"},{"id":"F3FDFD25-C4F6-4ECF-8F8B-C460E4C6BD7C","name":"molecule-co","codepoint":"F12FE","aliases":["carbon-monoxide","gas-co"],"tags":["Home Automation","Science"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"6F7A0011-054A-4805-A970-A48BEAA9454B","name":"molecule-co2","codepoint":"F07E4","aliases":["periodic-table-carbon-dioxide","gas-co2"],"tags":["Science","Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"35091AEB-2AF7-4F92-A249-2955F01404A3","name":"monitor","codepoint":"F0379","aliases":["desktop-windows"],"tags":["Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"B2A9CF60-30E4-46DC-9116-ED206912B156","name":"monitor-cellphone","codepoint":"F0989","aliases":["monitor-mobile-phone","monitor-smartphone"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"6665F86B-B97E-4AB8-8476-06B045706183","name":"monitor-cellphone-star","codepoint":"F098A","aliases":["important-devices","monitor-mobile-phone-star","monitor-smartphone-star"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"E02B1C8D-DA14-4AF2-8EB3-397AD9DAF1AB","name":"monitor-clean","codepoint":"F1104","aliases":[],"tags":["Device \/ Tech"],"author":"Contributors","version":"4.3.95"},{"id":"B4B96C77-6C5D-40A5-83E4-548E48CBECED","name":"monitor-dashboard","codepoint":"F0A07","aliases":[],"tags":["Device \/ Tech"],"author":"Austin Andrews","version":"2.5.94"},{"id":"E04B6974-751D-4A55-9309-02336DDB5070","name":"monitor-edit","codepoint":"F12C6","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Richins","version":"4.8.95"},{"id":"598E13C9-CC60-4FAF-A13A-024B1B4CF1EE","name":"monitor-eye","codepoint":"F13B4","aliases":[],"tags":[],"author":"Contributors","version":"5.0.45"},{"id":"59544B54-B690-47F4-AE30-4A9D9FE08FD1","name":"monitor-lock","codepoint":"F0DDB","aliases":[],"tags":["Device \/ Tech","Lock"],"author":"Austin Andrews","version":"3.5.94"},{"id":"7768BF7B-0A52-4492-88BD-5A482E4D61C3","name":"monitor-multiple","codepoint":"F037A","aliases":["monitors"],"tags":["Device \/ Tech"],"author":"Chris Litherland","version":"1.5.54"},{"id":"73F67174-7800-44CB-9850-61A01F9DAD34","name":"monitor-off","codepoint":"F0D90","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"3.4.93"},{"id":"9211237F-8920-49C2-90A6-63D97045F5EB","name":"monitor-screenshot","codepoint":"F0E51","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"3.6.95"},{"id":"905C2321-6A99-46C7-8EE7-D7193A95E5E7","name":"monitor-share","codepoint":"F1483","aliases":[],"tags":[],"author":"Google","version":"5.3.45"},{"id":"0D49AB2B-17E4-43B8-B72E-05C4A11500F6","name":"monitor-speaker","codepoint":"F0F5F","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"3.9.97"},{"id":"56879DCE-4616-45D0-A1C2-B9262776840B","name":"monitor-speaker-off","codepoint":"F0F60","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"3.9.97"},{"id":"6E372D46-ECFB-4275-B058-036C89A3413B","name":"monitor-star","codepoint":"F0DDC","aliases":[],"tags":["Device \/ Tech"],"author":"Austin Andrews","version":"3.5.94"},{"id":"F9A81054-5651-47DE-9507-E0743AE78E77","name":"moon-first-quarter","codepoint":"F0F61","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"536FA8E5-13DF-49A6-9C43-9874847AA01A","name":"moon-full","codepoint":"F0F62","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"690C3986-7EEB-4DD2-87EE-BEB93A917B14","name":"moon-last-quarter","codepoint":"F0F63","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"1F3CFDCC-7391-4AA6-994C-DCC6F3D28A46","name":"moon-new","codepoint":"F0F64","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"B324215D-A609-4B93-A859-1A0A24391C01","name":"moon-waning-crescent","codepoint":"F0F65","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"B03A16BE-0679-4635-B2F7-6553C3761211","name":"moon-waning-gibbous","codepoint":"F0F66","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"FAE0DF65-BA66-4F45-B246-35EFD1DF6FF2","name":"moon-waxing-crescent","codepoint":"F0F67","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"6DF419CE-770C-4662-8681-5D8ADE9C789E","name":"moon-waxing-gibbous","codepoint":"F0F68","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"DC294862-E625-444E-83A4-7D5F2255EE0C","name":"moped","codepoint":"F1086","aliases":["scooter","vespa","delivery-dining"],"tags":["Transportation + Road","Transportation + Other"],"author":"Google","version":"4.2.95"},{"id":"5DA43EA9-3DE7-49D8-8884-BB4D8ED31305","name":"moped-electric","codepoint":"F15B7","aliases":["scooter-electric","vespa-electric","delivery-dining-electric"],"tags":["Transportation + Road"],"author":"Google","version":"5.6.55"},{"id":"FF5A5D35-99C8-475C-B672-362AF0FA9FC6","name":"moped-electric-outline","codepoint":"F15B8","aliases":["scooter-electric-outline","vespa-electric-outline","delivery-dining-electric-outline"],"tags":["Transportation + Road"],"author":"Google","version":"5.6.55"},{"id":"2C84B4E2-F872-423E-B9E2-918DD013E131","name":"moped-outline","codepoint":"F15B9","aliases":["scooter-outline","vespa-outline","delivery-dining-outline"],"tags":["Transportation + Road"],"author":"Google","version":"5.6.55"},{"id":"6284690E-A12C-4209-A779-18284E241DE3","name":"more","codepoint":"F037B","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"12E07384-2645-4F67-9A4F-4DA26FA1F75C","name":"mother-heart","codepoint":"F1314","aliases":[],"tags":["People \/ Family"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"ACE8B129-F064-47BF-9FD5-AB472736ED43","name":"mother-nurse","codepoint":"F0D21","aliases":["breast-feed"],"tags":["Medical \/ Hospital","People \/ Family"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"D5136ED4-FC45-44D8-9DE4-C266844D5131","name":"motion","codepoint":"F15B2","aliases":[],"tags":[],"author":"Google","version":"5.5.55"},{"id":"0D1E834E-0B33-49ED-B02B-1EA0E966ADE1","name":"motion-outline","codepoint":"F15B3","aliases":[],"tags":[],"author":"Google","version":"5.5.55"},{"id":"B0DBB2D0-8C87-4DD3-AB7A-4BF35A9BFC6C","name":"motion-pause","codepoint":"F1590","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"5.5.55"},{"id":"DE3F5084-9C1D-459E-B3EC-514C040A9C22","name":"motion-pause-outline","codepoint":"F1592","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"5.5.55"},{"id":"04CF9E56-DAFA-474B-8405-2F554F66AEEC","name":"motion-play","codepoint":"F158F","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"5.5.55"},{"id":"520E825E-1F91-4EFA-B16F-488E61C02091","name":"motion-play-outline","codepoint":"F1591","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"5.5.55"},{"id":"2607909D-AA27-448A-B0E5-E5898790414A","name":"motion-sensor","codepoint":"F0D91","aliases":["motion-detector"],"tags":["Home Automation"],"author":"Simran","version":"3.4.93"},{"id":"94EEC5E7-5BF7-456E-8A9C-970E3CD46F55","name":"motion-sensor-off","codepoint":"F1435","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"D6AADAF8-D44E-44C0-8647-E578B277441D","name":"motorbike","codepoint":"F037C","aliases":["motorcycle"],"tags":["Transportation + Road","Sport"],"author":"Google","version":"1.5.54"},{"id":"91B25A35-38AC-497B-A0D8-82053E09E43A","name":"motorbike-electric","codepoint":"F15BA","aliases":["motorcycle-electric"],"tags":["Transportation + Road"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"965CDBD7-9E52-4169-B363-E0428C75C19D","name":"mouse","codepoint":"F037D","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"82AF407C-1290-4636-9299-E4FBA02EC25F","name":"mouse-bluetooth","codepoint":"F098B","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.4.85"},{"id":"63EB8966-D3A4-40C1-BC5C-BD4B34069D17","name":"mouse-move-down","codepoint":"F1550","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"63B2417B-4DCD-4DE3-A899-10851795B46F","name":"mouse-move-up","codepoint":"F1551","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"FD9503DC-1ADF-4E78-B0E9-DC3831C6B849","name":"mouse-move-vertical","codepoint":"F1552","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"2FB92E91-9B25-46BF-85D2-BC0A2DB877B1","name":"mouse-off","codepoint":"F037E","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"2E7ADC17-384C-4763-9D52-31AFF16BC864","name":"mouse-variant","codepoint":"F037F","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"7542DE09-B799-4ED5-8ADB-AE809808FAE1","name":"mouse-variant-off","codepoint":"F0380","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"4E3B74C0-3E85-4A50-B5FF-3D6AED1CF016","name":"move-resize","codepoint":"F0655","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"7A5B3547-16C4-4000-9082-E13A9139C737","name":"move-resize-variant","codepoint":"F0656","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"122C53AA-C8BC-41B3-89B2-B9A9F8BB56DC","name":"movie","codepoint":"F0381","aliases":["slate","clapperboard","film","movie-creation"],"tags":["Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"8B5A9F9F-D0F3-4B9A-844F-D6EE34154837","name":"movie-check","codepoint":"F16F3","aliases":["slate-check","clapperboard-check","film-check"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"74A2D617-040C-4313-9D9B-CDB2FFDCC0D7","name":"movie-check-outline","codepoint":"F16F4","aliases":["slate-check-outline","clapperboard-check-outline","film-check-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"B06E7709-247C-4F57-BFA6-345C1ABAE8C3","name":"movie-cog","codepoint":"F16F5","aliases":["slate-cog","clapperboard-cog","film-cog"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"388C5417-3BC7-491F-B708-AD81DCB237C8","name":"movie-cog-outline","codepoint":"F16F6","aliases":["slate-cog-outline","clapperboard-cog-outline","film-cog-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"EBABD564-B269-4D31-995B-062C7EBEFC15","name":"movie-edit","codepoint":"F1122","aliases":["slate-edit","clapperboard-edit","film-edit"],"tags":["Video \/ Movie","Edit \/ Modify"],"author":"Christopher Schreiner","version":"4.3.95"},{"id":"16912257-3D89-4630-9CC5-1FB0EB4A112C","name":"movie-edit-outline","codepoint":"F1123","aliases":["slate-edit-outline","clapperboard-edit-outline","film-edit-outline"],"tags":["Video \/ Movie","Edit \/ Modify"],"author":"Christopher Schreiner","version":"4.3.95"},{"id":"89C25EF5-4F0B-43A3-9B70-8B87E71FAB8A","name":"movie-filter","codepoint":"F1124","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"4.3.95"},{"id":"90E11F43-169D-46A2-868F-3EE7B8238371","name":"movie-filter-outline","codepoint":"F1125","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"4.3.95"},{"id":"8437938B-8D4E-4CE9-BE88-D5BBBC39140A","name":"movie-minus","codepoint":"F16F7","aliases":["slate-minus","clapperboard-minus","film-minus"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"44B3B4FB-C569-4D4D-A463-C2F6B87A584C","name":"movie-minus-outline","codepoint":"F16F8","aliases":["slate-minus-outline","clapperboard-minus-outline","film-minus-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"2260571C-D9DD-4720-AFB7-C54A32585767","name":"movie-off","codepoint":"F16F9","aliases":["slate-off","clapperboard-off","film-off"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"6E94BD0C-39BF-4D74-99BB-738062232A19","name":"movie-off-outline","codepoint":"F16FA","aliases":["slate-off-outline","clapperboard-off-outline","film-off-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"F23718ED-A1EE-42D7-84B2-773E110AAB63","name":"movie-open","codepoint":"F0FCE","aliases":["slate-open","clapperboard-open","film-open","movie-creation"],"tags":["Video \/ Movie"],"author":"GreenTurtwig","version":"4.0.96"},{"id":"C3078403-9C18-4F30-983B-E755B9CBA37B","name":"movie-open-check","codepoint":"F16FB","aliases":["slate-open-check","clapperboard-open-check","film-open-check"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"3CA87DEB-5A40-4DAF-960B-2AA9A4385F1D","name":"movie-open-check-outline","codepoint":"F16FC","aliases":["slate-open-check-outline","clapperboard-open-check-outline","film-open-check-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"20ADB8D7-DA55-463B-A523-9FA0377A1C74","name":"movie-open-cog","codepoint":"F16FD","aliases":["slate-open-cog","clapperboard-open-cog","film-open-cog"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"F4936EA7-C151-4D41-84CC-4E02BCA4E01B","name":"movie-open-cog-outline","codepoint":"F16FE","aliases":["slate-open-cog-outline","clapperboard-open-cog-outline","film-open-cog-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"BC0C6C6B-C6BE-4E96-BFAF-782866BCF8C2","name":"movie-open-edit","codepoint":"F16FF","aliases":["slate-open-edit","clapperboard-open-edit","film-open-edit"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"83B13E8A-4202-47CF-B67E-34335B0E5B29","name":"movie-open-edit-outline","codepoint":"F1700","aliases":["slate-open-edit-outline","clapperboard-open-edit-outline","film-open-edit-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"6AF20375-5B60-41D4-B63C-7572F590741C","name":"movie-open-minus","codepoint":"F1701","aliases":["slate-open-minus","clapperboard-open-minus","film-open-minus"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"61DDE079-6865-4609-B2F6-2770A3A039E1","name":"movie-open-minus-outline","codepoint":"F1702","aliases":["slate-open-minus-outline","clapperboard-open-minus-outline","film-open-minus-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"A58F23CF-24CA-42B3-B877-FA9DEA317A3B","name":"movie-open-off","codepoint":"F1703","aliases":["slate-open-off","clapperboard-open-off","film-open-off"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"AF946982-D5F6-4E17-8B0A-B091A873F86E","name":"movie-open-off-outline","codepoint":"F1704","aliases":["slate-open-off-outline","clapperboard-open-off-outline","film-open-off-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"17E4DACC-FDBF-4206-9F03-428157B91803","name":"movie-open-outline","codepoint":"F0FCF","aliases":["slate-open-outline","clapperboard-open-outline","film-open-outline","movie-creation"],"tags":["Video \/ Movie"],"author":"GreenTurtwig","version":"4.0.96"},{"id":"F3CB37FD-2C97-4CD1-83C0-18677B81DAC6","name":"movie-open-play","codepoint":"F1705","aliases":["slate-open-play","clapperboard-open-play","film-open-play"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"C855F888-FB96-40F5-9346-6B7A993C960A","name":"movie-open-play-outline","codepoint":"F1706","aliases":["slate-open-play-outline","clapperboard-open-play-outline","film-open-play-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"C9068163-63A6-44B7-BE11-2FCE6B427CF6","name":"movie-open-plus","codepoint":"F1707","aliases":["clapperboard-open-plus","slate-open-plus","flim-open-plus"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"A060D40D-A702-4EA0-9B66-95C31103C223","name":"movie-open-plus-outline","codepoint":"F1708","aliases":["slate-open-plus-outline","clapperboard-open-plus-outline","film-open-plus-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"1AA27DAA-CD6F-41C5-BB25-8860B368DC0B","name":"movie-open-remove","codepoint":"F1709","aliases":["slate-open-remove","clapperboard-open-remove","film-open-remove"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"320C9DCC-5845-46F6-B3E6-412D22B8BF47","name":"movie-open-remove-outline","codepoint":"F170A","aliases":["slate-open-remove-outline","clapperboard-open-remove-outline","film-open-remove-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"FC6ECE54-744A-4A77-B032-897B24064048","name":"movie-open-settings","codepoint":"F170B","aliases":["slate-open-settings","clapperboard-open-settings","film-open-settings"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"C481209F-DE3F-4D25-8C4F-0D21CB8D3385","name":"movie-open-settings-outline","codepoint":"F170C","aliases":["slate-open-settings-outline","clapperboard-open-settings-outline","film-open-settings-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"D370E43D-3692-4654-B67E-12AA40956EF3","name":"movie-open-star","codepoint":"F170D","aliases":["slate-open-star","clapperboard-open-star","film-open-star"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"85F303FB-9847-450E-BF4B-7A38C86386AF","name":"movie-open-star-outline","codepoint":"F170E","aliases":["slate-open-star-outline","clapperboard-open-star-outline","film-open-star-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"8198AA61-F267-4A56-B9D8-5D492B519545","name":"movie-outline","codepoint":"F0DDD","aliases":["slate-outline","clapperboard-outline","film-outline"],"tags":["Video \/ Movie"],"author":"Google","version":"3.5.94"},{"id":"44B019DA-A010-4B5F-AF03-61DBCC6206DD","name":"movie-play","codepoint":"F170F","aliases":["slate-play","clapperboard-play","film-play"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"48071069-C2BD-4B35-97A1-0167DB7B1B13","name":"movie-play-outline","codepoint":"F1710","aliases":["slate-play-outline","clapperboard-play-outline","film-play-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"543E83B1-B4CD-4D26-9813-A7F23C44AC5F","name":"movie-plus","codepoint":"F1711","aliases":["slate-plus","clapperboard-plus","film-plus"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"1171D3A1-94AD-4DF5-81E0-D7800C05A0AC","name":"movie-plus-outline","codepoint":"F1712","aliases":["slate-plus-outline","clapperboard-plus-outline","film-plus-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"A55FA4A8-DD49-4A4E-8DC0-ED7979F2469B","name":"movie-remove","codepoint":"F1713","aliases":["slate-remove","clapperboard-remove","film-remove"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"6FC268E0-F315-4818-B25F-0576DA4B9A84","name":"movie-remove-outline","codepoint":"F1714","aliases":["slate-remove-outline","clapperboard-remove-outline","film-remove-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"21D0F9FB-6814-4CE7-B37D-FC97EBF1D0D2","name":"movie-roll","codepoint":"F07DE","aliases":["film-reel"],"tags":["Video \/ Movie"],"author":"Contributors","version":"2.0.46"},{"id":"83E13559-040A-4EB7-BBA5-A2455CCEBBB9","name":"movie-search","codepoint":"F11D2","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.5.95"},{"id":"8BF9EEDF-1AE8-4382-8544-3F650525371B","name":"movie-search-outline","codepoint":"F11D3","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.5.95"},{"id":"0A90A107-BB52-4DBA-BC4F-E285D87EB4DF","name":"movie-settings","codepoint":"F1715","aliases":["slate-settings","clapperboard-settings","film-settings"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"D90C8E93-5B99-4604-A597-5DA45FC3CEB2","name":"movie-settings-outline","codepoint":"F1716","aliases":["slate-settings-outline","clapperboard-settings-outline","film-settings-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"07D0534A-0D01-428A-8915-0C3930BE8C41","name":"movie-star","codepoint":"F1717","aliases":["slate-star","clapperboard-star","film-star"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"31542EFD-68FE-435F-8B00-1BDFB218D9E2","name":"movie-star-outline","codepoint":"F1718","aliases":["slate-star-outline","clapperboard-star-outline","film-star-outline"],"tags":["Video \/ Movie"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"27842852-CDEB-4575-AAEB-D7F15F0928F8","name":"mower","codepoint":"F166F","aliases":[],"tags":["Hardware \/ Tools","Home Automation"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"1AF71C6B-087D-493D-81B4-8BDD6A07B2ED","name":"mower-bag","codepoint":"F1670","aliases":[],"tags":["Hardware \/ Tools","Home Automation"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"730FEADE-1281-422D-9E31-9DF7D06AD4E3","name":"muffin","codepoint":"F098C","aliases":[],"tags":["Food \/ Drink"],"author":"Nick","version":"2.4.85"},{"id":"489C9004-CF90-483E-83E3-CD40DD5B9ACF","name":"multiplication","codepoint":"F0382","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"38DF4F2F-85CF-4F71-B170-AAAAF25799E0","name":"multiplication-box","codepoint":"F0383","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.5.54"},{"id":"FCA4F099-5FCB-43DE-8166-2CE30508C1EC","name":"mushroom","codepoint":"F07DF","aliases":["fungus"],"tags":["Nature","Food \/ Drink"],"author":"Contributors","version":"2.0.46"},{"id":"F061399A-D4F9-49C6-B70A-B4D2603699AC","name":"mushroom-off","codepoint":"F13FA","aliases":[],"tags":["Food \/ Drink","Nature"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"5421FAF8-CBB9-43C7-A8C1-EE90C949DD56","name":"mushroom-off-outline","codepoint":"F13FB","aliases":[],"tags":["Food \/ Drink","Nature"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"D6C17EB7-0A54-4ECA-81AA-86311E311934","name":"mushroom-outline","codepoint":"F07E0","aliases":["fungus-outline"],"tags":["Nature","Food \/ Drink"],"author":"Contributors","version":"2.0.46"},{"id":"E7DA3CF2-C345-441D-BFC2-ABC4DB195A6A","name":"music","codepoint":"F075A","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.9.32"},{"id":"0273309C-CE51-4243-8EDF-F86B0B73AAE4","name":"music-accidental-double-flat","codepoint":"F0F69","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"89EC2121-104F-4814-849A-AF9AA744E239","name":"music-accidental-double-sharp","codepoint":"F0F6A","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"1ED310B2-EE64-4011-B725-3D4FFB10E26A","name":"music-accidental-flat","codepoint":"F0F6B","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"4AA4E035-3A6F-40FA-8355-A38F9294E399","name":"music-accidental-natural","codepoint":"F0F6C","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"6FD5E083-A276-4433-8D67-FBC8D9163719","name":"music-accidental-sharp","codepoint":"F0F6D","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"2EDBEBA6-8590-4049-BB28-8959378DC44C","name":"music-box","codepoint":"F0384","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"56F24AF4-9E5B-4E53-89ED-3472E08C9466","name":"music-box-multiple","codepoint":"F0333","aliases":["library-music"],"tags":["Music"],"author":"Google","version":"1.5.54"},{"id":"16F694B0-E5B4-4262-91AE-DB3D0C73EEC0","name":"music-box-multiple-outline","codepoint":"F0F04","aliases":["library-music-outline"],"tags":["Music"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"9E8ADF62-9136-40F3-BED9-54A2934B4B3B","name":"music-box-outline","codepoint":"F0385","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"33A79A85-7985-4E08-8AA8-D6242A9C2700","name":"music-circle","codepoint":"F0386","aliases":["note-circle"],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C8E3DFB3-2F22-489D-90F5-D8C47B66DB3C","name":"music-circle-outline","codepoint":"F0AD4","aliases":["note-circle-outline"],"tags":["Music","Audio"],"author":"Austin Andrews","version":"2.7.94"},{"id":"9AA4CF34-3341-41F7-AC35-E8556A91787B","name":"music-clef-alto","codepoint":"F0F6E","aliases":["music-c-clef","music-clef-tenor","music-clef-soprano","music-clef-baritone"],"tags":["Music"],"author":"Haley Halcyon","version":"3.9.97"},{"id":"279EAB4C-7D62-4C41-A67F-2928723476DA","name":"music-clef-bass","codepoint":"F0F6F","aliases":["music-f-clef"],"tags":["Music"],"author":"Haley Halcyon","version":"3.9.97"},{"id":"7ED69559-58ED-432E-800F-9B8DE4CD53A2","name":"music-clef-treble","codepoint":"F0F70","aliases":["music-g-clef"],"tags":["Music"],"author":"Haley Halcyon","version":"3.9.97"},{"id":"05F3F5DD-59CC-4FBD-9428-0D0CB125A8AE","name":"music-note","codepoint":"F0387","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"40A9BA37-B1BD-4869-A3F9-8F534258DB3F","name":"music-note-bluetooth","codepoint":"F05FE","aliases":[],"tags":["Audio"],"author":"Simran","version":"1.5.54"},{"id":"98CC5D8B-5D4B-4379-8FFF-1C7FEA82672C","name":"music-note-bluetooth-off","codepoint":"F05FF","aliases":[],"tags":["Audio"],"author":"Simran","version":"1.5.54"},{"id":"44EDC206-CF12-4DA5-8DA6-E72FDC35BBD2","name":"music-note-eighth","codepoint":"F0388","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9E5589FE-17DF-4167-9DDE-D41D6503B433","name":"music-note-eighth-dotted","codepoint":"F0F71","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"2F2FC9A9-FAC3-4736-B8EC-B7DF9548586C","name":"music-note-half","codepoint":"F0389","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"53666387-B7D7-4C48-96B9-3D6CAA6E2468","name":"music-note-half-dotted","codepoint":"F0F72","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"08305F79-B7E4-4FC9-9B5B-8E76920C3DCC","name":"music-note-off","codepoint":"F038A","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C47B2AE6-FB1F-4E54-A951-AD26609ECB80","name":"music-note-off-outline","codepoint":"F0F73","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"5888AA23-7D87-46D3-83F3-1AB820E9F77D","name":"music-note-outline","codepoint":"F0F74","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"ED5D1835-D69E-458A-9CCE-F1B81EB831D2","name":"music-note-plus","codepoint":"F0DDE","aliases":["music-note-add"],"tags":["Audio","Music"],"author":"GreenTurtwig","version":"3.5.94"},{"id":"D71DFC98-3401-4268-9956-3EFEEE336235","name":"music-note-quarter","codepoint":"F038B","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"56364DE5-01AE-4702-BC79-F85D07E485C7","name":"music-note-quarter-dotted","codepoint":"F0F75","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"882DF0E2-C223-4B3F-A538-81EC05421BA9","name":"music-note-sixteenth","codepoint":"F038C","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F98989F8-DE11-42A7-A814-5C988CBD7989","name":"music-note-sixteenth-dotted","codepoint":"F0F76","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"13454604-C50C-4381-AC96-552848F0DF9E","name":"music-note-whole","codepoint":"F038D","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6A2B3740-C02F-4097-9713-80C34636CA12","name":"music-note-whole-dotted","codepoint":"F0F77","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"E9D8BB99-B31B-4940-9EEE-B69569060B0D","name":"music-off","codepoint":"F075B","aliases":[],"tags":["Audio","Music"],"author":"Austin Andrews","version":"1.9.32"},{"id":"D77BE879-A1D5-48F5-9068-B74A2ED4017A","name":"music-rest-eighth","codepoint":"F0F78","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"C9124F85-BB56-414C-BEAF-EE02E921B6D2","name":"music-rest-half","codepoint":"F0F79","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"64309B5C-51CC-42D0-B2D1-F42454CC1E2E","name":"music-rest-quarter","codepoint":"F0F7A","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"E7CCD9CF-3FC1-44F0-996B-841B293B1793","name":"music-rest-sixteenth","codepoint":"F0F7B","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"E11E01A9-8231-456F-AF61-82A069BBDAAB","name":"music-rest-whole","codepoint":"F0F7C","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"766E10EA-23CD-42BD-9DB8-633FBF8C584A","name":"mustache","codepoint":"F15DE","aliases":[],"tags":[],"author":"Google","version":"5.6.55"},{"id":"D1A8C00E-5FE4-4016-9C38-40CD9804D7C9","name":"nail","codepoint":"F0DDF","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"001157C4-1AAA-41FF-B204-906ACDB427C3","name":"nas","codepoint":"F08F3","aliases":["network-attached-storage"],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"A69196BD-730F-4684-8604-8668FD60183A","name":"nativescript","codepoint":"F0880","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"C5FCAD4F-C7E6-4BDB-9F2F-A665CB68B7FD","name":"nature","codepoint":"F038E","aliases":["plant"],"tags":["Nature"],"author":"Google","version":"1.5.54"},{"id":"B0635A70-D2A9-41CE-82C6-3FB1D1D353B4","name":"nature-people","codepoint":"F038F","aliases":["plant"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"DAAF6988-6EE9-4595-A758-294C83C7304B","name":"navigation","codepoint":"F0390","aliases":["arrow-compass"],"tags":["Navigation"],"author":"Google","version":"1.5.54"},{"id":"8CEE19E5-13B9-4AFF-8880-B04D36B144BA","name":"navigation-outline","codepoint":"F1607","aliases":[],"tags":["Navigation"],"author":"Google","version":"5.6.55"},{"id":"6766F53D-88E4-452A-A222-7F50DDFB757C","name":"near-me","codepoint":"F05CD","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"70C6DD45-DD16-4629-8BBA-B60FB5D60382","name":"necklace","codepoint":"F0F0B","aliases":[],"tags":["Clothing"],"author":"Michael Richins","version":"3.8.95"},{"id":"2B76647F-92FE-4F8E-B193-7EC20DADD5D2","name":"needle","codepoint":"F0391","aliases":["syringe","injection","medicine","shot","drug","immunization","pharmaceutical"],"tags":["Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"7AEF7097-EC88-4D09-A65E-5244DDA99599","name":"netflix","codepoint":"F0746","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.9.32"},{"id":"089C6F75-2FF5-4B48-B4B4-651AEAD3D24F","name":"network","codepoint":"F06F3","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"B4F8AA0D-E5C6-4FC1-A91C-A7E47269FB31","name":"network-off","codepoint":"F0C9B","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"6CFA3244-3420-4234-BFC6-80DEA8F38CCC","name":"network-off-outline","codepoint":"F0C9C","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"D6F66231-B4F7-4E89-80D5-D9DDD2354D02","name":"network-outline","codepoint":"F0C9D","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"7AEB6E6A-4B4E-42C3-9AB2-1F47FE1BD29B","name":"network-strength-1","codepoint":"F08F4","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"2.3.50"},{"id":"9C2C41A2-7BA9-46C3-B017-941C7B2C2E60","name":"network-strength-1-alert","codepoint":"F08F5","aliases":["network-strength-1-warning"],"tags":["Cellphone \/ Phone","Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"DF3CEC8C-F6B7-467B-833C-92FE260C6A73","name":"network-strength-2","codepoint":"F08F6","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"2.3.50"},{"id":"DB8EEB5C-3705-4DE7-A770-D63ACE14F1BD","name":"network-strength-2-alert","codepoint":"F08F7","aliases":["network-strength-2-warning"],"tags":["Cellphone \/ Phone","Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"7FAA15D1-1E1D-41F5-98F0-1B640DFB0688","name":"network-strength-3","codepoint":"F08F8","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"2.3.50"},{"id":"99771A39-B621-45BA-96BE-7589E5A85B9E","name":"network-strength-3-alert","codepoint":"F08F9","aliases":["network-strength-3-warning"],"tags":["Cellphone \/ Phone","Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"87FF7D68-6F78-44AB-80C4-DC7FE976E3A3","name":"network-strength-4","codepoint":"F08FA","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"2.3.50"},{"id":"1173684B-E68C-4BE5-BD9C-53C01A619896","name":"network-strength-4-alert","codepoint":"F08FB","aliases":["network-strength-4-warning"],"tags":["Cellphone \/ Phone","Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"E3FEE803-9C91-4BAE-9528-D016588E99AD","name":"network-strength-off","codepoint":"F08FC","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"2.3.50"},{"id":"E7A4CEE7-C6E2-4FD6-B0BF-B3DD131100CB","name":"network-strength-off-outline","codepoint":"F08FD","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"2.3.50"},{"id":"5A80D579-DF12-4B68-AAD8-AFE8039E6657","name":"network-strength-outline","codepoint":"F08FE","aliases":["network-strength-0"],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"2.3.50"},{"id":"1ABEE375-A0DC-4262-9CCD-3B9C78B5FE7D","name":"new-box","codepoint":"F0394","aliases":["fiber-new"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"EE440B14-2E25-4C8E-99A7-A3C98CBC9151","name":"newspaper","codepoint":"F0395","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4949C4CF-3395-466E-B459-9FEBA1BFD1AC","name":"newspaper-minus","codepoint":"F0F0C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"7B4B8A85-6E8F-4C2B-938C-58DF98E8823B","name":"newspaper-plus","codepoint":"F0F0D","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"B7E3A571-DF01-4CBF-A3AE-CDEF835F2A21","name":"newspaper-variant","codepoint":"F1001","aliases":[],"tags":[],"author":"Google","version":"4.0.96"},{"id":"2672B224-C14E-41B7-B7F2-632CA02F9D3B","name":"newspaper-variant-multiple","codepoint":"F1002","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"687B9CDE-25C6-49DF-B28F-051B30FD11D3","name":"newspaper-variant-multiple-outline","codepoint":"F1003","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"1859420B-45AE-4AC1-AC8D-91AB0FF84BBA","name":"newspaper-variant-outline","codepoint":"F1004","aliases":[],"tags":[],"author":"Google","version":"4.0.96"},{"id":"961106B7-BD56-462C-936C-E2CDC83051B5","name":"nfc","codepoint":"F0396","aliases":["near-field-communication"],"tags":[],"author":"Contributors","version":"1.5.54"},{"id":"2AD73512-8D95-4CCB-8A7E-528E70F510B9","name":"nfc-search-variant","codepoint":"F0E53","aliases":[],"tags":[],"author":"Terren","version":"3.6.95"},{"id":"656C274C-CDC8-4FB6-AFFA-F704784BC997","name":"nfc-tap","codepoint":"F0397","aliases":["near-field-communication-tap"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"4DFF5414-0EA3-4255-BC50-B40B0E3ADB15","name":"nfc-variant","codepoint":"F0398","aliases":["near-field-communication-variant"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"2BD17DBC-5002-4378-B885-A1952D740C0B","name":"nfc-variant-off","codepoint":"F0E54","aliases":[],"tags":[],"author":"TheChilliPL","version":"3.6.95"},{"id":"8E7C1B4B-C4E8-4072-9FB7-90E207038FFB","name":"ninja","codepoint":"F0774","aliases":[],"tags":[],"author":"Michael Richins","version":"1.9.32"},{"id":"A067CF52-3D9E-43DB-9542-44BE780B4117","name":"nintendo-game-boy","codepoint":"F1393","aliases":[],"tags":[],"author":"GreenTurtwig","version":"5.0.45"},{"id":"D57C5D23-1122-4DEB-BEC4-77D5A4D685FE","name":"nintendo-switch","codepoint":"F07E1","aliases":["nintendo-switch-online"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.0.46"},{"id":"AA2F2BCF-A9BD-4B3A-83A4-880E518F9428","name":"nintendo-wii","codepoint":"F05AB","aliases":["nintendo-wii"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.5.54"},{"id":"7D322B2B-5B7D-46B4-ACC3-A8900CFED5C9","name":"nintendo-wiiu","codepoint":"F072D","aliases":["nintendo-wiiu"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.8.36"},{"id":"525A43D5-4292-4C31-9E7D-7B65DB386BF9","name":"nix","codepoint":"F1105","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.3.95"},{"id":"46A696BA-7A78-40C1-A685-C9B9851286A6","name":"nodejs","codepoint":"F0399","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"1655675D-A197-44BD-83E9-76E2BAD31740","name":"noodles","codepoint":"F117E","aliases":["food-ramen","asian-noodles"],"tags":["Food \/ Drink"],"author":"Google","version":"4.4.95"},{"id":"A301F5C0-B760-4EA0-B803-DEF84D1B01CD","name":"not-equal","codepoint":"F098D","aliases":[],"tags":[],"author":"Nick","version":"2.4.85"},{"id":"AF2B1665-3D54-4017-BF7C-AE03A7C6AA52","name":"not-equal-variant","codepoint":"F098E","aliases":[],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"5E1DF73F-AEF5-48F8-B766-419FBB05C5D0","name":"note","codepoint":"F039A","aliases":["paper"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"5F9984C8-D7D1-42A8-9167-52B0B849CF22","name":"note-minus","codepoint":"F164F","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"244AEF5D-38E8-42E6-9C4F-8D4AFF831651","name":"note-minus-outline","codepoint":"F1650","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"0A0E42BA-FE9D-44C6-BF6A-D29D6013F2E0","name":"note-multiple","codepoint":"F06B8","aliases":["notes"],"tags":[],"author":"Austin Andrews","version":"1.7.22"},{"id":"6294246C-A524-4121-B141-5262D89FFD4D","name":"note-multiple-outline","codepoint":"F06B9","aliases":["notes-outline"],"tags":[],"author":"Austin Andrews","version":"1.7.22"},{"id":"DD6D5075-A7F5-4183-9F99-93C295F18B0B","name":"note-outline","codepoint":"F039B","aliases":["paper-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"753F2E09-A32F-4790-9C07-7CD9AB69104D","name":"note-plus","codepoint":"F039C","aliases":["note-add"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"706F4C63-412B-44CD-81DE-612D4483D09C","name":"note-plus-outline","codepoint":"F039D","aliases":["note-add-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"948C92D0-A16F-48FD-8A25-37898D6B9768","name":"note-remove","codepoint":"F1651","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"4F471FC1-C060-4081-9866-21830957AE90","name":"note-remove-outline","codepoint":"F1652","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"D914BB12-8F9A-4B71-86A0-DA016AA91B90","name":"note-search","codepoint":"F1653","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"FAA55692-47B7-492B-897A-9225E7F0C766","name":"note-search-outline","codepoint":"F1654","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"2ADC4253-F51B-4BC2-B04C-0DDD139425CF","name":"note-text","codepoint":"F039E","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E39F6865-3E35-4BE8-8440-643FC83351F7","name":"note-text-outline","codepoint":"F11D7","aliases":[],"tags":[],"author":"Michael Richins","version":"4.5.95"},{"id":"2D28230E-DAF3-4A49-ACB6-7D9C3E9E6495","name":"notebook","codepoint":"F082E","aliases":["journal","planner"],"tags":[],"author":"Contributors","version":"2.1.19"},{"id":"7DBD97BD-376C-45C2-85BA-74BE45C03F2E","name":"notebook-check","codepoint":"F14F5","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.4.55"},{"id":"0C11F6D4-B9DE-4927-AB54-B17695167B25","name":"notebook-check-outline","codepoint":"F14F6","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.4.55"},{"id":"EFBA00EA-395F-47DF-A0B9-8F42C1A697E1","name":"notebook-edit","codepoint":"F14E7","aliases":[],"tags":["Edit \/ Modify"],"author":"Austin Andrews","version":"5.4.55"},{"id":"31A232F5-6134-4A8D-A9D1-41DC4404922D","name":"notebook-edit-outline","codepoint":"F14E9","aliases":[],"tags":["Edit \/ Modify"],"author":"Austin Andrews","version":"5.4.55"},{"id":"60952B51-85EE-45B0-9834-7117F8DED9D7","name":"notebook-minus","codepoint":"F1610","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"0B3667B2-5DB3-4C7B-8E01-4601666EE765","name":"notebook-minus-outline","codepoint":"F1611","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"3F75C3D8-9360-4C31-AF58-1C01321620F0","name":"notebook-multiple","codepoint":"F0E55","aliases":["journal-multiple","planner-multiple"],"tags":[],"author":"Contributors","version":"3.6.95"},{"id":"71D72BE3-C04C-40EF-87B7-A08E74045DC0","name":"notebook-outline","codepoint":"F0EBF","aliases":["journal-outline","planner-outline"],"tags":[],"author":"Austin Andrews","version":"3.7.94"},{"id":"03D29CD4-AFB3-41E3-9B35-80F27ABFDD13","name":"notebook-plus","codepoint":"F1612","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"8652F3A3-ED31-48CA-B051-A4ADCFC722F6","name":"notebook-plus-outline","codepoint":"F1613","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"318A0AA0-55F5-4242-B377-BA972C7B3AD3","name":"notebook-remove","codepoint":"F1614","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"92BD7E81-2B29-48FB-B0B0-F38C94BE4B51","name":"notebook-remove-outline","codepoint":"F1615","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"E758A025-3B14-4A2F-A1D7-2D12C38B47E4","name":"notification-clear-all","codepoint":"F039F","aliases":[],"tags":["Notification"],"author":"Google","version":"1.5.54"},{"id":"5E072845-A46E-4D62-A65D-28CD7DAD976B","name":"npm","codepoint":"F06F7","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.8.36"},{"id":"DB44684C-B1E7-4039-8BAA-C7C0BC4EB075","name":"nuke","codepoint":"F06A4","aliases":["nuclear","atomic-bomb"],"tags":[],"author":"GreenTurtwig","version":"1.7.12"},{"id":"5004722B-DE0B-4F37-BCAD-36B46477E80F","name":"null","codepoint":"F07E2","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"1293DBCD-E538-4AD1-97C9-3F17BBD28457","name":"numeric","codepoint":"F03A0","aliases":["numbers","1-2-3","one-two-three","123"],"tags":["Alpha \/ Numeric"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3396CDF3-94D7-4F1B-B0FF-58FA3935468C","name":"numeric-0","codepoint":"F0B39","aliases":["number-0","numeric-zero"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"C676CDFC-A808-4BCA-A670-49EE8478ED32","name":"numeric-0-box","codepoint":"F03A1","aliases":["numeric-zero-box","number-0-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"D54CC81B-F785-4896-BA17-454BBBE96EC5","name":"numeric-0-box-multiple","codepoint":"F0F0E","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"B3652E81-9CA5-4B7C-B603-FE94CB2D1323","name":"numeric-0-box-multiple-outline","codepoint":"F03A2","aliases":["numeric-zero-box-multiple-outline","numeric-0-boxes-outline","number-0-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"1EB53615-9A62-4377-A2D0-246C8F42CAF8","name":"numeric-0-box-outline","codepoint":"F03A3","aliases":["numeric-zero-box-outline","number-0-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"802F5332-8865-46C9-890D-130209044E17","name":"numeric-0-circle","codepoint":"F0C9E","aliases":["numeric-zero-circle","number-0-circle","number-zero-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"BB859C27-AAAC-4ED4-A50B-45427C15CF05","name":"numeric-0-circle-outline","codepoint":"F0C9F","aliases":["numeric-zero-circle-outline","number-0-circle-outline","number-zero-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"DF225E4A-DED0-43C3-83B1-4867ABA9D45B","name":"numeric-1","codepoint":"F0B3A","aliases":["number-1","numeric-one"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"0EF5316E-7978-4F6C-B38E-297837B3CFF5","name":"numeric-1-box","codepoint":"F03A4","aliases":["looks-one","numeric-one-box","number-1-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"9CF3C6FF-4E68-478B-85B9-02ABA9A7980C","name":"numeric-1-box-multiple","codepoint":"F0F0F","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"55513DD6-D73E-438E-8834-D6761C47BA4B","name":"numeric-1-box-multiple-outline","codepoint":"F03A5","aliases":["filter-1","numeric-one-box-multiple-outline","numeric-1-boxes-outline","number-1-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"50AEDC65-99B1-45CA-8078-CD6D8633995A","name":"numeric-1-box-outline","codepoint":"F03A6","aliases":["numeric-one-box-outline","number-1-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"77E2B22B-C6FB-4759-B2BB-0528DAFA6210","name":"numeric-1-circle","codepoint":"F0CA0","aliases":["numeric-one-circle","number-1-circle","number-one-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"7621E523-93F4-47A9-A7A5-9BC2A01A4DD4","name":"numeric-1-circle-outline","codepoint":"F0CA1","aliases":["numeric-one-circle-outline","number-1-circle-outline","number-one-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"59F26CDB-B593-4675-941C-68F0E99F2CFF","name":"numeric-10","codepoint":"F0FE9","aliases":[],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"4.0.96"},{"id":"BD0566FC-D422-4ABD-8D6E-7E08EED3708D","name":"numeric-10-box","codepoint":"F0F7D","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"0ABCD0B7-C95E-4BD9-AFBB-C1CF415FE53C","name":"numeric-10-box-multiple","codepoint":"F0FEA","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.0.96"},{"id":"4C455257-74B0-4140-BA07-71582A9750FD","name":"numeric-10-box-multiple-outline","codepoint":"F0FEB","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.0.96"},{"id":"12AB352E-27A7-43D6-BF2E-EF35BC4CA288","name":"numeric-10-box-outline","codepoint":"F0F7E","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"487FE19B-CDA9-4895-B904-606B73BB66E7","name":"numeric-10-circle","codepoint":"F0FEC","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.0.96"},{"id":"FAABED75-FE76-4109-824D-F16C54E43FA2","name":"numeric-10-circle-outline","codepoint":"F0FED","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.0.96"},{"id":"55F915B1-69CB-4394-9313-F8A0B7A8EBB9","name":"numeric-2","codepoint":"F0B3B","aliases":["number-2","numeric-two"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"0F35B058-84BF-42A1-8EC2-4DF8A5F2CB6D","name":"numeric-2-box","codepoint":"F03A7","aliases":["looks-two","numeric-two-box","number-2-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"4950EF31-6A39-4EFE-91CD-10CB750A3634","name":"numeric-2-box-multiple","codepoint":"F0F10","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"989BAC0E-21F6-4AF2-849A-3DA35BA5958F","name":"numeric-2-box-multiple-outline","codepoint":"F03A8","aliases":["filter-2","numeric-two-box-multiple-outline","numeric-2-boxes-outline","number-2-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"0C255402-1176-46B5-B38C-60118732FCC7","name":"numeric-2-box-outline","codepoint":"F03A9","aliases":["numeric-two-box-outline","number-2-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"C8CF7706-2522-4EB4-A304-C25BAD47C1C7","name":"numeric-2-circle","codepoint":"F0CA2","aliases":["numeric-two-circle","number-2-circle","number-two-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"36906959-9333-4F37-9BB3-BE1481F2A99A","name":"numeric-2-circle-outline","codepoint":"F0CA3","aliases":["numeric-two-circle-outline","number-2-circle-outline","number-two-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"E7B3F9D9-BC8D-4BE8-B02D-F2E20B3B357A","name":"numeric-3","codepoint":"F0B3C","aliases":["number-3","numeric-three"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"F34D170B-4DF1-470D-ABC4-AE0A93035227","name":"numeric-3-box","codepoint":"F03AA","aliases":["looks-3","numeric-three-box","number-3-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"9D8EBAFA-19A3-4E74-9800-570AFD910814","name":"numeric-3-box-multiple","codepoint":"F0F11","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"394B1DFD-7009-4057-AD14-7F7D99B3A658","name":"numeric-3-box-multiple-outline","codepoint":"F03AB","aliases":["filter-3","numeric-three-box-multiple-outline","numeric-3-boxes-outline","number-3-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"0A0F7443-4234-4990-9C0B-A8AC88F924E5","name":"numeric-3-box-outline","codepoint":"F03AC","aliases":["numeric-three-box-outline","number-3-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"07FDE137-E119-45E9-8100-3C0194FFF51D","name":"numeric-3-circle","codepoint":"F0CA4","aliases":["numeric-three-circle","number-3-circle","number-three-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"4AF81318-EC08-4E9D-9853-F7C8AD694E10","name":"numeric-3-circle-outline","codepoint":"F0CA5","aliases":["numeric-three-circle-outline","number-3-circle-outline","number-three-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"099C1A7A-865B-4BA2-951B-EED8F8665083","name":"numeric-4","codepoint":"F0B3D","aliases":["number-4","numeric-four"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"9C9EEFA4-B764-41CE-A679-3927454AE59A","name":"numeric-4-box","codepoint":"F03AD","aliases":["looks-4","numeric-four-box","number-4-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"DB253DAA-77F7-41F0-A1A4-76388FEFA092","name":"numeric-4-box-multiple","codepoint":"F0F12","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"EB320CFB-296A-4C6F-9585-76CA21DDCD04","name":"numeric-4-box-multiple-outline","codepoint":"F03B2","aliases":["filter-4","numeric-four-box-multiple-outline","numeric-4-boxes-outline","number-4-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"18423C69-0B97-4590-A690-1AAF99615875","name":"numeric-4-box-outline","codepoint":"F03AE","aliases":["numeric-four-box-outline","number-4-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"3C8A2386-5BBE-495F-A1BE-BFBB3385D857","name":"numeric-4-circle","codepoint":"F0CA6","aliases":["numeric-four-circle","number-4-circle","number-four-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"898E368A-092D-45E4-B84D-9C99ABFFF2AC","name":"numeric-4-circle-outline","codepoint":"F0CA7","aliases":["numeric-four-circle-outline","number-4-circle-outline","number-four-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"EFB5FA9A-E828-4D71-A35F-011D873DE490","name":"numeric-5","codepoint":"F0B3E","aliases":["number-5","numeric-five"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"1F91841C-B56D-486E-8113-187E28F1E53A","name":"numeric-5-box","codepoint":"F03B1","aliases":["looks-5","numeric-five-box","number-5-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"C3FBC921-E4A1-4B04-BDEA-E883EE5FB695","name":"numeric-5-box-multiple","codepoint":"F0F13","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"A39788D6-B09D-42CF-ADC3-7575B14DBE79","name":"numeric-5-box-multiple-outline","codepoint":"F03AF","aliases":["filter-5","numeric-five-box-multiple-outline","numeric-5-boxes-outline","number-5-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"38CB37B2-2BF9-4890-8060-5576DDAE6FC6","name":"numeric-5-box-outline","codepoint":"F03B0","aliases":["numeric-five-box-outline","number-5-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"B4079A0A-5D66-4982-B31F-4145B49E5512","name":"numeric-5-circle","codepoint":"F0CA8","aliases":["numeric-five-circle","number-5-circle","number-five-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"1FFAD3CC-0B61-4A7A-90F0-E5A5D78D7D3A","name":"numeric-5-circle-outline","codepoint":"F0CA9","aliases":["numeric-five-circle-outline","number-5-circle-outline","number-five-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"8B73A4D3-4AC9-448B-8C60-497EC2167898","name":"numeric-6","codepoint":"F0B3F","aliases":["number-6","numeric-six"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"DC1FE999-3DD7-423B-95A5-89005C66875E","name":"numeric-6-box","codepoint":"F03B3","aliases":["looks-6","numeric-six-box","number-6-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"231F08AC-E082-407D-9EC9-55C2E654EF16","name":"numeric-6-box-multiple","codepoint":"F0F14","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"F3AA6A15-D060-40D7-A301-9EB1BAAF2F12","name":"numeric-6-box-multiple-outline","codepoint":"F03B4","aliases":["filter-6","numeric-six-box-multiple-outline","numeric-6-boxes-outline","number-6-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"8ED3719B-D733-46ED-BFCF-0BDE0819F7EF","name":"numeric-6-box-outline","codepoint":"F03B5","aliases":["numeric-six-box-outline","number-6-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"E15A2826-796D-439A-9A10-4F068C76C6FC","name":"numeric-6-circle","codepoint":"F0CAA","aliases":["numeric-six-circle","number-6-circle","number-six-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"6D644C9F-A3C4-45E6-A2E8-E3077A170E4A","name":"numeric-6-circle-outline","codepoint":"F0CAB","aliases":["numeric-six-circle-outline","number-6-circle-outline","number-six-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"19BDA673-8B20-4A75-87B9-7286F0B14730","name":"numeric-7","codepoint":"F0B40","aliases":["number-7","numeric-seven"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"C01DF00A-5B63-4B15-B6A5-FEA9E3E084B1","name":"numeric-7-box","codepoint":"F03B6","aliases":["numeric-seven-box","number-7-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"C69F2D2A-7226-4D0A-87A8-3D53753C0572","name":"numeric-7-box-multiple","codepoint":"F0F15","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"CF43DB99-4419-491B-A5E3-2486A36F24DB","name":"numeric-7-box-multiple-outline","codepoint":"F03B7","aliases":["filter-7","numeric-seven-box-multiple-outline","numeric-7-boxes-outline","number-7-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"373DD873-E15F-4B7C-8328-76389DC81DB0","name":"numeric-7-box-outline","codepoint":"F03B8","aliases":["numeric-seven-box-outline","number-7-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"FE25714F-69B5-463B-8C11-5E4E057C83C3","name":"numeric-7-circle","codepoint":"F0CAC","aliases":["numeric-seven-circle","number-7-circle","number-seven-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"67707F91-E498-46C6-816B-2A6D1BE437F6","name":"numeric-7-circle-outline","codepoint":"F0CAD","aliases":["numeric-seven-circle-outline","number-7-circle-outline","number-seven-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"F92BFF4C-3D23-466A-BBE6-AF98DB0F43A9","name":"numeric-8","codepoint":"F0B41","aliases":["number-8","numeric-eight"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"863E0667-F376-4303-9261-CAA4B7F073C6","name":"numeric-8-box","codepoint":"F03B9","aliases":["numeric-eight-box","number-8-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"D032F5F3-670D-4576-AD76-A17562377466","name":"numeric-8-box-multiple","codepoint":"F0F16","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"869A508B-5F8E-41A7-BCE5-E205FC66C80F","name":"numeric-8-box-multiple-outline","codepoint":"F03BA","aliases":["filter-8","numeric-eight-box-multiple-outline","numeric-8-boxes-outline","number-8-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"DC2B6D38-A6B3-4171-AAC6-E08EF2C23710","name":"numeric-8-box-outline","codepoint":"F03BB","aliases":["numeric-eight-box-outline","number-8-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"26382400-22B1-40A6-9C1A-46C649C36783","name":"numeric-8-circle","codepoint":"F0CAE","aliases":["numeric-eight-circle","number-8-circle","number-eight-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"C1306EC5-E7F0-4152-A19D-84E851537171","name":"numeric-8-circle-outline","codepoint":"F0CAF","aliases":["numeric-eight-circle-outline","number-8-circle-outline","number-eight-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"11F0ADB8-0CC8-48A3-8653-11E7F58B5C9B","name":"numeric-9","codepoint":"F0B42","aliases":["number-9","numeric-nine"],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"12DCC44D-8BA2-4D25-A88B-665920C8B730","name":"numeric-9-box","codepoint":"F03BC","aliases":["numeric-nine-box","number-9-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"3DAA435E-D837-4AD3-9937-0D554F409BB0","name":"numeric-9-box-multiple","codepoint":"F0F17","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"A41F44A0-816E-497E-A08C-C9646FE161BE","name":"numeric-9-box-multiple-outline","codepoint":"F03BD","aliases":["filter-9","numeric-nine-box-multiple-outline","numeric-9-boxes-outline","number-9-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"EE2E9486-0C32-4EC9-9D4F-9B8A7287F696","name":"numeric-9-box-outline","codepoint":"F03BE","aliases":["numeric-nine-box-outline","number-9-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"FB06011B-B2CC-4F3A-8ADE-2F7E78F0AE7C","name":"numeric-9-circle","codepoint":"F0CB0","aliases":["numeric-nine-circle","number-9-circle","number-nine-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"F27ABCBB-C6D6-4C1E-AF0C-C406057245AA","name":"numeric-9-circle-outline","codepoint":"F0CB1","aliases":["numeric-nine-circle-outline","number-9-circle-outline","number-nine-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"CF313E88-0D2F-49B9-B2BC-6651ACEAA677","name":"numeric-9-plus","codepoint":"F0FEE","aliases":[],"tags":["Alpha \/ Numeric"],"author":"GreenTurtwig","version":"4.0.96"},{"id":"7CF309F0-D751-44A3-A313-BA7F2F8865FD","name":"numeric-9-plus-box","codepoint":"F03BF","aliases":["numeric-nine-plus-box","number-9-plus-box"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"20E22DC1-795D-432F-9CB9-D339EA3B96DB","name":"numeric-9-plus-box-multiple","codepoint":"F0F18","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.8.95"},{"id":"46A850FC-F6E6-4000-A93F-6B954DA62886","name":"numeric-9-plus-box-multiple-outline","codepoint":"F03C0","aliases":["filter-9-plus","numeric-nine-plus-box-multiple-outline","numeric-9-plus-boxes-outline","number-9-plus-box-multiple-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"C1F38C40-BD01-45FE-A94C-B3C1432707E0","name":"numeric-9-plus-box-outline","codepoint":"F03C1","aliases":["numeric-nine-plus-box-outline","number-9-plus-box-outline"],"tags":["Alpha \/ Numeric"],"author":"Google","version":"1.5.54"},{"id":"757FDF81-DCCF-4B75-9A2A-9ED3D2DB966E","name":"numeric-9-plus-circle","codepoint":"F0CB2","aliases":["numeric-nine-plus-circle","number-9-plus-circle","number-nine-plus-circle"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"00BD21E8-FAF1-470D-8F64-0030C1C222F3","name":"numeric-9-plus-circle-outline","codepoint":"F0CB3","aliases":["numeric-nine-plus-circle-outline","number-9-plus-circle-outline","number-nine-plus-circle-outline"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"3.2.89"},{"id":"B198FE0B-15C3-4FFB-B5C9-2D6E60E825A1","name":"numeric-negative-1","codepoint":"F1052","aliases":["decrement","minus-one"],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.1.95"},{"id":"73DE8F6E-A301-42D1-B2C3-3699265BA2BB","name":"numeric-positive-1","codepoint":"F15CB","aliases":["increment","plus-one"],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"8B702257-4232-459E-BDA8-C4E698DF8E8E","name":"nut","codepoint":"F06F8","aliases":[],"tags":["Hardware \/ Tools"],"author":"Simran","version":"1.8.36"},{"id":"723E0BBB-78CC-4192-98B1-426B17D694B9","name":"nutrition","codepoint":"F03C2","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"EDCDD59F-BD6B-49C9-B93A-36879031CEA3","name":"nuxt","codepoint":"F1106","aliases":[],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.3.95"},{"id":"A065A53E-118C-424A-8A81-0D300975AB04","name":"oar","codepoint":"F067C","aliases":[],"tags":[],"author":"Thomas Hunsaker","version":"1.7.12"},{"id":"1C1A3850-DB11-4F6D-B031-8E4CE14E9760","name":"ocarina","codepoint":"F0DE0","aliases":[],"tags":["Music","Gaming \/ RPG"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"53021908-1FB5-4293-896E-94C5330E6101","name":"oci","codepoint":"F12E9","aliases":["open-container-initiative"],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.8.95"},{"id":"2943D362-A548-448C-A868-19E6D37C8B2D","name":"ocr","codepoint":"F113A","aliases":["optical-character-recognition"],"tags":[],"author":"Simran","version":"4.4.95"},{"id":"5E3C88DE-A208-471A-9096-7C7868CC957C","name":"octagon","codepoint":"F03C3","aliases":["stop"],"tags":["Shape","Transportation + Road"],"author":"Simran","version":"1.5.54"},{"id":"3CF63E10-42E7-4E13-8BFF-10E9257953AB","name":"octagon-outline","codepoint":"F03C4","aliases":["stop-outline"],"tags":["Shape","Transportation + Road"],"author":"Simran","version":"1.5.54"},{"id":"455C8475-5555-49B7-825B-206581104AB2","name":"octagram","codepoint":"F06F9","aliases":["starburst"],"tags":["Shape"],"author":"Austin Andrews","version":"1.8.36"},{"id":"8316E0F1-5F66-4C4E-ACA8-EE61AD93A42A","name":"octagram-outline","codepoint":"F0775","aliases":["starburst-outline"],"tags":["Shape"],"author":"Austin Andrews","version":"1.9.32"},{"id":"8BB24B94-491F-4465-8E87-45FF8FED7C4A","name":"odnoklassniki","codepoint":"F03C5","aliases":["ok-ru"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"64C3CB40-BBDF-4A82-9B07-62CA527A258C","name":"offer","codepoint":"F121B","aliases":[],"tags":[],"author":"Simran","version":"4.6.95"},{"id":"C6BEE3A0-C734-48D4-A2E4-622E9B16CA06","name":"office-building","codepoint":"F0991","aliases":[],"tags":["Places"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"8409886F-203E-45A5-8A70-C1670406BBA2","name":"office-building-marker","codepoint":"F1520","aliases":["office-building-location"],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"B9C8DF7B-34D7-4D58-B769-B3ABAD0990FC","name":"office-building-marker-outline","codepoint":"F1521","aliases":["office-building-location-outline"],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"1171525F-C510-44B9-9E5C-0F5CAC7A71D2","name":"office-building-outline","codepoint":"F151F","aliases":[],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"DE398350-B7B7-4E6B-AE4C-F99AAE56C7CF","name":"oil","codepoint":"F03C7","aliases":[],"tags":["Automotive"],"author":"Austin Andrews","version":"1.5.54"},{"id":"790DAFDA-8291-47F5-A5B9-9563AE201832","name":"oil-lamp","codepoint":"F0F19","aliases":["wish","genie-lamp"],"tags":[],"author":"Michael Richins","version":"3.8.95"},{"id":"A6579EB0-C38D-4052-A6C9-C1ECD97E482C","name":"oil-level","codepoint":"F1053","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"C8743DBF-39CD-43E8-8EC3-B99D422422FC","name":"oil-temperature","codepoint":"F0FF8","aliases":[],"tags":["Automotive"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"A98F63CB-AB27-4A2D-B76C-6994507BCDBB","name":"omega","codepoint":"F03C9","aliases":["ohm","electrical-resistance"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"DF8CCF67-8BD2-4632-8647-2B42BA2047A5","name":"one-up","codepoint":"F0BAD","aliases":["1up","extra-life"],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"2B9B64C7-B799-45C5-BDCC-BEC3B8672CFE","name":"onepassword","codepoint":"F0881","aliases":["1password"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"27C36043-E269-4223-ADCE-568B1EFB4623","name":"opacity","codepoint":"F05CC","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"AF69E2E1-8119-49A2-8E24-915E2254522A","name":"open-in-app","codepoint":"F03CB","aliases":["open-in-browser"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"12B95238-1D74-4C6C-9BBD-C055B4DD0E4D","name":"open-in-new","codepoint":"F03CC","aliases":["external-link"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DA48F078-4BE9-42DC-AF35-F557E16DD2AE","name":"open-source-initiative","codepoint":"F0BAE","aliases":[],"tags":[],"author":"Contributors","version":"3.0.39"},{"id":"C9525FF9-FE74-467C-99CE-F8DD8FE3576C","name":"openid","codepoint":"F03CD","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"A0BCE6D1-D558-487E-9629-F7CCC495C27B","name":"opera","codepoint":"F03CE","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"D672819E-C3D1-49FC-A1E7-9F4732D034DC","name":"orbit","codepoint":"F0018","aliases":[],"tags":["Science"],"author":"Roberto Graham","version":"1.5.54"},{"id":"4A0C34D7-1D3D-472B-9E5D-858DBBCBC7B2","name":"orbit-variant","codepoint":"F15DB","aliases":["camera-flip"],"tags":["Photography"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"B6FBB02F-98A0-4521-BA9B-D00EA8A2FC57","name":"order-alphabetical-ascending","codepoint":"F020D","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"1.5.54"},{"id":"D9CEAAB0-32D3-4A42-A0F3-74B1FC50E9F0","name":"order-alphabetical-descending","codepoint":"F0D07","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"3.3.92"},{"id":"2D12922D-3C06-4916-9575-CA9A1014C4BF","name":"order-bool-ascending","codepoint":"F02BE","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"1.5.54"},{"id":"FA5DB7BA-69CB-4DF5-9DE9-B0681889CB2D","name":"order-bool-ascending-variant","codepoint":"F098F","aliases":["order-checkbox-ascending"],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"2.4.85"},{"id":"62006FDB-1540-4E32-B74D-A758C8974661","name":"order-bool-descending","codepoint":"F1384","aliases":["order-checkbox-descending"],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"5.0.45"},{"id":"56E79669-E557-4D22-A21D-E07FFDB1C2B6","name":"order-bool-descending-variant","codepoint":"F0990","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"2.4.85"},{"id":"1ADB886B-B791-42BF-AC04-5EB73E665EA6","name":"order-numeric-ascending","codepoint":"F0545","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"1.5.54"},{"id":"3979C805-4C53-4F45-A6E5-9CAADE1C2D80","name":"order-numeric-descending","codepoint":"F0546","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"1.5.54"},{"id":"E41855D5-FB0E-4FAD-8CD8-D085B1577D2F","name":"origin","codepoint":"F0B43","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.8.94"},{"id":"ADC4F1DD-B840-4C28-8D5C-08F3BE15A424","name":"ornament","codepoint":"F03CF","aliases":[],"tags":["Holiday"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9C3E1D75-FB73-44AA-8BCC-9B30692D8D79","name":"ornament-variant","codepoint":"F03D0","aliases":[],"tags":["Holiday"],"author":"Austin Andrews","version":"1.5.54"},{"id":"09F61849-C1AA-4755-B49E-75DB800B5273","name":"outdoor-lamp","codepoint":"F1054","aliases":["outdoor-light"],"tags":["Home Automation"],"author":"Borre Haugen","version":"4.1.95"},{"id":"059B5D2A-9B8B-412D-BAF1-F3F9B7E14A44","name":"overscan","codepoint":"F1005","aliases":["fullscreen"],"tags":[],"author":"Google","version":"4.0.96"},{"id":"1F963457-7A4F-4BEE-AE9C-0E54CF804DD3","name":"owl","codepoint":"F03D2","aliases":[],"tags":["Animal"],"author":"Simran","version":"1.5.54"},{"id":"29FC6427-61B9-4961-9004-FCD4A6E6522D","name":"pac-man","codepoint":"F0BAF","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"3.0.39"},{"id":"57771FFC-0E2C-40DE-AF7C-F3F51EFFE2C0","name":"package","codepoint":"F03D3","aliases":["box"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0C18B335-700A-4D68-BF88-C95A69479F2E","name":"package-down","codepoint":"F03D4","aliases":["archive","box-down"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"383EF914-6014-473D-8C54-0314432007E3","name":"package-up","codepoint":"F03D5","aliases":["unarchive","box-up"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"558C8C17-E4E1-4921-874D-F9ACB26C35C8","name":"package-variant","codepoint":"F03D6","aliases":["box-variant"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"290F16B3-147C-446D-B14B-56AECCA76276","name":"package-variant-closed","codepoint":"F03D7","aliases":["box-variant-closed"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"DF23FF47-4DD3-4CB3-9BEC-6EE986B0FA65","name":"page-first","codepoint":"F0600","aliases":["first-page"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"CF9B4635-FE27-4DA5-BE51-F5F4116AFC54","name":"page-last","codepoint":"F0601","aliases":["last-page"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"39AF8334-4244-49DD-A8A4-D4F638B9D939","name":"page-layout-body","codepoint":"F06FA","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"74636C38-381A-46B8-97FD-B312735DE60D","name":"page-layout-footer","codepoint":"F06FB","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"3606AC64-ABC8-4DA6-ACE8-64D58E0B0A46","name":"page-layout-header","codepoint":"F06FC","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"C1258752-7002-4714-81E3-D90828B5A896","name":"page-layout-header-footer","codepoint":"F0F7F","aliases":["page-layout-marginals"],"tags":[],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"6E39564D-2B4B-4940-9E74-5274ED12E800","name":"page-layout-sidebar-left","codepoint":"F06FD","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"29C8714B-1CAD-41B8-829B-2A14F6F87684","name":"page-layout-sidebar-right","codepoint":"F06FE","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"760D3DDF-F710-4BE1-A4E6-CC5AD6AF49DB","name":"page-next","codepoint":"F0BB0","aliases":["read-more"],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"9213C60D-0232-4ECB-91C6-8D2BF812FE6A","name":"page-next-outline","codepoint":"F0BB1","aliases":["read-more-outline"],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"AF1A8DA7-B3AC-4E11-A50B-59FBA8B34CF5","name":"page-previous","codepoint":"F0BB2","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"A26AE0CE-1223-4A40-B7B6-E4FDCC5AE820","name":"page-previous-outline","codepoint":"F0BB3","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"C4C17ED6-0DB6-4A13-9C6F-0C3146B0CD80","name":"pail","codepoint":"F1417","aliases":["bucket"],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"ECD25F41-E1C8-438E-BFF3-54F529504071","name":"pail-minus","codepoint":"F1437","aliases":["bucket-minus"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"599354BE-5249-40F9-8E62-466F89203E5B","name":"pail-minus-outline","codepoint":"F143C","aliases":["bucket-minus-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"2F1D4972-0025-4EB4-ADFC-2ACBEF34C7EA","name":"pail-off","codepoint":"F1439","aliases":["bucket-off"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"896E500B-797D-4687-917C-063906BB503F","name":"pail-off-outline","codepoint":"F143E","aliases":["bucket-off-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"02152202-9609-4E5D-A6C5-1C7FE35F97E8","name":"pail-outline","codepoint":"F143A","aliases":["bucket-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"ED64CE31-8F78-4383-A3BF-2AFBE5485E38","name":"pail-plus","codepoint":"F1436","aliases":["bucket-plus"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"63B16204-CDD1-425F-8DDD-7DD80F2639D9","name":"pail-plus-outline","codepoint":"F143B","aliases":["bucket-plus-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"FC5A2451-43C6-40D1-905D-7E473ACA134C","name":"pail-remove","codepoint":"F1438","aliases":["bucket-remove"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"48413062-A335-454F-9349-04CD2B7BC628","name":"pail-remove-outline","codepoint":"F143D","aliases":["bucket-remove-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"954CCE2B-7FEE-4F9C-9923-4E1D567607C3","name":"palette","codepoint":"F03D8","aliases":["color-lens","colour-lens","paint","art","color"],"tags":["Color","Drawing \/ Art"],"author":"Google","version":"1.5.54"},{"id":"3617B5EE-9A4A-4C3C-9C9A-8C69C7569EB4","name":"palette-advanced","codepoint":"F03D9","aliases":["paint"],"tags":["Color","Drawing \/ Art"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6C41ED7D-CA9F-45BA-B94D-F20ABB54519B","name":"palette-outline","codepoint":"F0E0C","aliases":["paint-outline"],"tags":["Drawing \/ Art","Color","Geographic Information System"],"author":"Google","version":"3.5.95"},{"id":"158F8306-CE63-45E8-94E5-58484FF5F050","name":"palette-swatch","codepoint":"F08B5","aliases":["style","paint"],"tags":["Drawing \/ Art","Color"],"author":"Google","version":"2.2.43"},{"id":"3D2690B4-4A3D-4B7C-B384-1C0AB180DD0B","name":"palette-swatch-outline","codepoint":"F135C","aliases":["style-outline","paint-outline"],"tags":["Drawing \/ Art","Color"],"author":"Google","version":"4.9.95"},{"id":"787F9145-5272-4028-94C8-46B0623FE039","name":"palm-tree","codepoint":"F1055","aliases":[],"tags":["Nature"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"FEDAC98D-95D1-44FE-81DE-2BAACA196408","name":"pan","codepoint":"F0BB4","aliases":[],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"F5AFD529-AD6F-4A1B-AB69-E3E10FD0E654","name":"pan-bottom-left","codepoint":"F0BB5","aliases":["pan-down-left"],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"BAAF741C-C242-49A8-8A16-DA1EC373385D","name":"pan-bottom-right","codepoint":"F0BB6","aliases":["pan-down-right"],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"408FB11D-9531-4C8F-A592-48CD10A1AF4B","name":"pan-down","codepoint":"F0BB7","aliases":[],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"9881BB2E-CCAF-4698-83B5-452ED749C314","name":"pan-horizontal","codepoint":"F0BB8","aliases":[],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"59CEB0A5-75F5-4D3D-AF4D-2F0D8AEAEB0C","name":"pan-left","codepoint":"F0BB9","aliases":[],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"D563253F-1895-4DB7-95E9-A0C4C5562D12","name":"pan-right","codepoint":"F0BBA","aliases":[],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"C497D005-A9A3-4B1A-B440-CE574E81AF2F","name":"pan-top-left","codepoint":"F0BBB","aliases":["pan-up-left"],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"E9886955-5257-4E95-A017-C903F5F850C2","name":"pan-top-right","codepoint":"F0BBC","aliases":["pan-up-right"],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"989DC863-1210-44A7-88A3-B414994983F6","name":"pan-up","codepoint":"F0BBD","aliases":[],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"A27AD714-E988-4970-B995-8EEADCDA5D55","name":"pan-vertical","codepoint":"F0BBE","aliases":[],"tags":[],"author":"Simran","version":"3.0.39"},{"id":"A797FE46-DF68-4179-85BE-172BD79F0667","name":"panda","codepoint":"F03DA","aliases":[],"tags":["Animal"],"author":"Austin Andrews","version":"1.5.54"},{"id":"24BCD03F-8D84-4154-95F5-086230CE3BBA","name":"pandora","codepoint":"F03DB","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"4054A322-F348-49BA-B85F-B978EFC1BDAD","name":"panorama","codepoint":"F03DC","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"6D0BD840-6985-440A-9C55-782B5C3F4F9C","name":"panorama-fisheye","codepoint":"F03DD","aliases":["panorama-fish-eye"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"42B1DAD8-8731-49DB-B415-9BFD78A8DDEA","name":"panorama-horizontal","codepoint":"F03DE","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"7EC1E0AF-1AC5-4CC8-BDCC-5E2D3BF2AC70","name":"panorama-vertical","codepoint":"F03DF","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"12D83006-87DE-49CE-B8C3-7D6492934CDA","name":"panorama-wide-angle","codepoint":"F03E0","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4E8B4DBC-83EE-4CBD-BEDD-5866DE057324","name":"paper-cut-vertical","codepoint":"F03E1","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"1666E605-F46A-4AD2-8345-A599811B7D45","name":"paper-roll","codepoint":"F1157","aliases":["lavatory-roll","bathroom-tissue","toilet-paper","kitchen-roll","paper-towels","receipt-roll"],"tags":["Home Automation","Printer"],"author":"Simran","version":"4.4.95"},{"id":"2A7CBB78-4672-450C-8578-48AFB13243CD","name":"paper-roll-outline","codepoint":"F1158","aliases":["lavatory-roll-outline","bathroom-tissue-outline","kitchen-roll-outline","paper-towels-outline","toilet-paper-outline","receipt-roll-outline"],"tags":["Home Automation","Printer"],"author":"Simran","version":"4.4.95"},{"id":"27BCEC7F-ABF8-4506-B339-EE2425E1BAF9","name":"paperclip","codepoint":"F03E2","aliases":["attachment-vertical","attach-file"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"47070C5A-B989-49C6-A635-3B764DC112CB","name":"parachute","codepoint":"F0CB4","aliases":[],"tags":["Transportation + Flying"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"739633DB-1136-4AD6-8E4E-80077562E9F1","name":"parachute-outline","codepoint":"F0CB5","aliases":[],"tags":["Transportation + Flying"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"07C8266A-A135-443C-B2DD-4148CD718C51","name":"parking","codepoint":"F03E3","aliases":["car-park","local-parking"],"tags":["Places"],"author":"Google","version":"1.5.54"},{"id":"AED614C4-13E2-4009-9D9F-950258DB5124","name":"party-popper","codepoint":"F1056","aliases":["celebration"],"tags":["Holiday"],"author":"Google","version":"4.1.95"},{"id":"31BE5768-FCE0-46D5-A20B-E8CBFED471E0","name":"passport","codepoint":"F07E3","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.0.46"},{"id":"86A974C4-6E5A-48F6-A3B9-35B3DCD1DE7A","name":"passport-biometric","codepoint":"F0DE1","aliases":["passport-electronic"],"tags":[],"author":"GreenTurtwig","version":"3.5.94"},{"id":"8288CA76-67E5-4EEA-82CD-DE0E0842F34D","name":"pasta","codepoint":"F1160","aliases":["food-italian","spaghetti"],"tags":["Food \/ Drink"],"author":"Google","version":"4.4.95"},{"id":"03B35003-B782-475E-AE4C-13021109AD97","name":"patio-heater","codepoint":"F0F80","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"9B72D845-E704-489C-A447-D02306AF5228","name":"patreon","codepoint":"F0882","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"2A1F0831-13CA-4419-BBD7-1F1FAF62A32B","name":"pause","codepoint":"F03E4","aliases":[],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"7AA13CBC-D472-4462-8263-88DA2BDCD6BB","name":"pause-circle","codepoint":"F03E5","aliases":["pause-circle-filled"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"6F271406-B475-45D0-9B37-EF3DBE7D0DAA","name":"pause-circle-outline","codepoint":"F03E6","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"D0A95719-9B9F-4E86-A6E5-8013C1A6D4A7","name":"pause-octagon","codepoint":"F03E7","aliases":["stop-pause"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"95AA0ED2-4221-4123-B3BF-9FACF3702CA4","name":"pause-octagon-outline","codepoint":"F03E8","aliases":["stop-pause-outline"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"802EBFA2-6D86-4E93-BEBF-7F69F6C98C01","name":"paw","codepoint":"F03E9","aliases":["pets"],"tags":["Animal","Nature"],"author":"Simran","version":"1.5.54"},{"id":"039D7C7E-AB09-4364-B08D-1FC120442AFE","name":"paw-off","codepoint":"F0657","aliases":[],"tags":["Animal"],"author":"Simran","version":"1.6.50"},{"id":"EADDFE7F-B2A0-40AD-B060-555080D02BCB","name":"paw-off-outline","codepoint":"F1676","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"C0FB173F-3D34-4DC2-9D54-C82BEE350FFB","name":"paw-outline","codepoint":"F1675","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"088F07BD-BEA9-46D5-A2DF-0B9FA37BBF99","name":"pdf-box","codepoint":"F0E56","aliases":[],"tags":["Files \/ Folders"],"author":"Google","version":"3.6.95"},{"id":"7E574E80-7DB1-4722-9BC4-60F53509AACD","name":"peace","codepoint":"F0884","aliases":[],"tags":[],"author":"Michael Richins","version":"2.1.99"},{"id":"87A5BD64-6069-4C5B-8D50-69D9049B80BC","name":"peanut","codepoint":"F0FFC","aliases":["allergen","food-allergy"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"4.0.96"},{"id":"D8BD17A2-5CE7-4219-8363-E87D80C2E7DF","name":"peanut-off","codepoint":"F0FFD","aliases":["allergen-off","food-allergy-off"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"4.0.96"},{"id":"A3B86034-EAD9-4DE1-AF76-A11F21285DF9","name":"peanut-off-outline","codepoint":"F0FFF","aliases":["allergen-off-outline","food-allergy-off-outline"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"4.0.96"},{"id":"C3883026-99A7-48ED-898E-37AC117A6C4F","name":"peanut-outline","codepoint":"F0FFE","aliases":["allergen-outline","food-allergy-outline"],"tags":["Food \/ Drink"],"author":"Michael Richins","version":"4.0.96"},{"id":"054B1710-EE28-4AA8-9D7E-705B5703E33E","name":"pen","codepoint":"F03EA","aliases":[],"tags":["Drawing \/ Art"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BDCCD15F-231E-4449-AADF-E2D21286396A","name":"pen-lock","codepoint":"F0DE2","aliases":[],"tags":["Lock"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"19D98B8F-B4D1-49B2-A870-20F7E72E4133","name":"pen-minus","codepoint":"F0DE3","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"9D2F36EB-BE54-482B-9EBD-083699503E16","name":"pen-off","codepoint":"F0DE4","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"299ED912-E240-41D8-AA28-5FB0025BC782","name":"pen-plus","codepoint":"F0DE5","aliases":["pen-add"],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"71997C15-3E04-4212-B08D-3F03AA110261","name":"pen-remove","codepoint":"F0DE6","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"BB27CE6C-769A-4C0C-A53C-F1B10B9C4423","name":"pencil","codepoint":"F03EB","aliases":["edit","create","mode-edit"],"tags":["Drawing \/ Art","Edit \/ Modify"],"author":"Google","version":"1.5.54"},{"id":"56CC04F4-4E58-434D-962A-C824F5959D20","name":"pencil-box","codepoint":"F03EC","aliases":[],"tags":["Drawing \/ Art"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3E7031C9-56EE-458C-BE57-B1A737E09998","name":"pencil-box-multiple","codepoint":"F1144","aliases":["library-edit"],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"071E2A53-1647-4747-98BE-A7787AF39C15","name":"pencil-box-multiple-outline","codepoint":"F1145","aliases":["library-edit-outline"],"tags":["Edit \/ Modify"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"48A9B269-08B8-4DCB-85F1-68F2334DC004","name":"pencil-box-outline","codepoint":"F03ED","aliases":[],"tags":["Drawing \/ Art"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F5C5B903-7160-4B46-AC15-28C965289469","name":"pencil-circle","codepoint":"F06FF","aliases":[],"tags":["Drawing \/ Art"],"author":"GreenTurtwig","version":"1.8.36"},{"id":"5D68DE43-969F-40BE-8A2D-F5C25F2B0853","name":"pencil-circle-outline","codepoint":"F0776","aliases":[],"tags":["Drawing \/ Art"],"author":"Austin Andrews","version":"1.9.32"},{"id":"33BBFD25-1E97-49AA-BA9A-0B42369DF4A6","name":"pencil-lock","codepoint":"F03EE","aliases":[],"tags":["Lock"],"author":"Simran","version":"1.5.54"},{"id":"0EDDA4FC-DC06-4621-AE19-5E0CF693997B","name":"pencil-lock-outline","codepoint":"F0DE7","aliases":[],"tags":["Lock"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"07FDD339-D255-4ED3-BDEB-00B57F521A0E","name":"pencil-minus","codepoint":"F0DE8","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"030723AA-4B87-4648-8A6A-CECB909A3140","name":"pencil-minus-outline","codepoint":"F0DE9","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"AEB0F9CD-B3FF-4F64-9D6E-4916D5C720C3","name":"pencil-off","codepoint":"F03EF","aliases":["edit-off"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"5B4952DA-7867-403A-AC98-12CFA78B52C0","name":"pencil-off-outline","codepoint":"F0DEA","aliases":["edit-off-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"A17D67B7-C5FF-45E2-91AE-975584067388","name":"pencil-outline","codepoint":"F0CB6","aliases":["edit-outline","create-outline","mode-edit-outline"],"tags":["Drawing \/ Art","Edit \/ Modify"],"author":"Google","version":"3.2.89"},{"id":"F6194D2A-B09D-416D-98B9-C80FDA45D831","name":"pencil-plus","codepoint":"F0DEB","aliases":["pencil-add"],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"831CF37A-6530-48BB-8CB7-B3FF50D61860","name":"pencil-plus-outline","codepoint":"F0DEC","aliases":["pencil-add-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"B536A740-BC15-4F6B-A923-28450B1ED3BD","name":"pencil-remove","codepoint":"F0DED","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"EEEC97B0-5E06-4D77-9934-6AC66B8F8538","name":"pencil-remove-outline","codepoint":"F0DEE","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"B8F0B132-5AD7-4E4B-ADDB-311FDBDD35CC","name":"pencil-ruler","codepoint":"F1353","aliases":["design"],"tags":["Drawing \/ Art"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"B2649A8A-D1EC-43AF-9C99-F233AF709155","name":"penguin","codepoint":"F0EC0","aliases":[],"tags":["Animal"],"author":"Augustin Ursu","version":"3.7.94"},{"id":"A1E0EA60-79AF-42FD-966D-485276671F9C","name":"pentagon","codepoint":"F0701","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"7251D20A-5A23-456D-9A68-0107EF2BF01B","name":"pentagon-outline","codepoint":"F0700","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"EA9C6D1A-79AE-4114-9AF6-59A2A39FC8DF","name":"pentagram","codepoint":"F1667","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.7.55"},{"id":"3AB307BF-41D9-4CA4-9D44-58C82304C7BB","name":"percent","codepoint":"F03F0","aliases":[],"tags":["Math"],"author":"Simran","version":"1.5.54"},{"id":"0625AC7C-AD52-4221-8F53-A9AE6DAA57BD","name":"percent-outline","codepoint":"F1278","aliases":[],"tags":[],"author":"Contributors","version":"4.7.95"},{"id":"1DB2BD6D-830D-4A4F-8E04-94D14901895A","name":"periodic-table","codepoint":"F08B6","aliases":[],"tags":["Science"],"author":"Simran","version":"2.2.43"},{"id":"408FA22D-2054-4579-A991-DF061CDE5A00","name":"perspective-less","codepoint":"F0D23","aliases":["perspective-decrease"],"tags":["Math"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"6F54CAE0-D2B7-4E00-83AA-0B98A7601CF6","name":"perspective-more","codepoint":"F0D24","aliases":["perspective-increase"],"tags":["Math"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"71BD315A-B0C1-4B8B-93CB-2A952C3A7C16","name":"pharmacy","codepoint":"F03F1","aliases":["chemist","local-pharmacy","mortar-pestle","pharmaceutical"],"tags":["Medical \/ Hospital"],"author":"Google","version":"1.5.54"},{"id":"B5BA809F-FCE8-476C-8388-6A9CFFF73015","name":"phone","codepoint":"F03F2","aliases":["call","local-phone","telephone"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"B7AE9DEE-6F1D-4CAF-9FD8-C6A6BF5D739D","name":"phone-alert","codepoint":"F0F1A","aliases":[],"tags":["Cellphone \/ Phone","Alert \/ Error"],"author":"Contributors","version":"3.8.95"},{"id":"A4D67201-7E48-469A-A424-0D772DBAD344","name":"phone-alert-outline","codepoint":"F118E","aliases":[],"tags":["Cellphone \/ Phone","Alert \/ Error"],"author":"Contributors","version":"4.5.95"},{"id":"34F52268-8571-4501-93C1-D4BF606BB10E","name":"phone-bluetooth","codepoint":"F03F3","aliases":["phone-bluetooth-speaker","telephone-bluetooth"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"64F560E8-6BEE-4CDC-81D4-FE87B76C906C","name":"phone-bluetooth-outline","codepoint":"F118F","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"C97B6119-5EB1-4930-AEFA-7E3E216D3875","name":"phone-cancel","codepoint":"F10BC","aliases":["phone-block"],"tags":["Cellphone \/ Phone"],"author":"Contributors","version":"4.2.95"},{"id":"70F0895F-EF78-404A-9CBE-D3FCAD39CE32","name":"phone-cancel-outline","codepoint":"F1190","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Contributors","version":"4.5.95"},{"id":"7FA6178B-0275-4545-BBCB-F10B77E9603D","name":"phone-check","codepoint":"F11A9","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"4.5.95"},{"id":"A91DFA4F-355A-4CB2-9013-F2ADFAA482D4","name":"phone-check-outline","codepoint":"F11AA","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"4.5.95"},{"id":"A9ED94F7-0ADB-4CB3-AAF1-35B87D9B7724","name":"phone-classic","codepoint":"F0602","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"1.5.54"},{"id":"4D938684-537A-4ED1-B227-6859EA3DADAF","name":"phone-classic-off","codepoint":"F1279","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"8F4DBE23-BD53-447F-917D-5343B4DDE8B8","name":"phone-dial","codepoint":"F1559","aliases":["phone-keypad"],"tags":["Cellphone \/ Phone"],"author":"Fran\u00e7ois Risoud","version":"5.5.55"},{"id":"90BA0013-C6A8-47E9-960C-A1DE13516B25","name":"phone-dial-outline","codepoint":"F155A","aliases":["phone-keypad-outline"],"tags":["Cellphone \/ Phone"],"author":"Fran\u00e7ois Risoud","version":"5.5.55"},{"id":"5EF77B27-31D7-47F8-8D72-8BC040CD154E","name":"phone-forward","codepoint":"F03F4","aliases":["phone-forwarded","telephone-forward"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"B168C56E-76CD-47CC-AD20-BA116911E3F8","name":"phone-forward-outline","codepoint":"F1191","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"2018B4C8-A296-4D62-A30A-85F988B206EA","name":"phone-hangup","codepoint":"F03F5","aliases":["call-end","telephone-hangup"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"56BBAAEB-F773-4C5D-B122-74F698048F5C","name":"phone-hangup-outline","codepoint":"F1192","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"F9BA7066-C1F8-4B19-9860-37BDCEB6F11C","name":"phone-in-talk","codepoint":"F03F6","aliases":["telephone-in-talk"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"BC90A08C-75FB-4E14-9795-3E408CB021AB","name":"phone-in-talk-outline","codepoint":"F1182","aliases":["telephone-in-talk-outline"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.4.95"},{"id":"AA8EEDF8-EB34-46C5-8117-9258E1349197","name":"phone-incoming","codepoint":"F03F7","aliases":["telephone-incoming"],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"1.5.54"},{"id":"75D9229A-5E93-4E44-8259-0808D47D6458","name":"phone-incoming-outline","codepoint":"F1193","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"31349A83-A803-48DF-98C8-55D5E27B81E4","name":"phone-lock","codepoint":"F03F8","aliases":["telephone-locked","phone-locked","telephone-lock"],"tags":["Cellphone \/ Phone","Lock"],"author":"Google","version":"1.5.54"},{"id":"436AB859-CF22-4225-9606-5D2F603C102C","name":"phone-lock-outline","codepoint":"F1194","aliases":[],"tags":["Cellphone \/ Phone","Lock"],"author":"Google","version":"4.5.95"},{"id":"B87821E3-2131-4C50-BB88-880BE6D0066F","name":"phone-log","codepoint":"F03F9","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"1.5.54"},{"id":"232EE7DD-4AC1-442D-B8E4-B914038E92CB","name":"phone-log-outline","codepoint":"F1195","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"4.5.95"},{"id":"16930FBE-3379-43F2-BEA6-057D64D18348","name":"phone-message","codepoint":"F1196","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"CBA2C764-2B58-4914-A5C9-F0DAB190BB4C","name":"phone-message-outline","codepoint":"F1197","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"7F431DF5-245C-4572-962C-CC57177BD8D0","name":"phone-minus","codepoint":"F0658","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.6.50"},{"id":"F27193C4-051E-4142-A17D-9AFD5D15687D","name":"phone-minus-outline","codepoint":"F1198","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"BF6662C4-D1D0-42E6-8C0A-B071F12975F2","name":"phone-missed","codepoint":"F03FA","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"1E87E90C-5DCD-4250-81EF-61138B268FBB","name":"phone-missed-outline","codepoint":"F11A5","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"43E0E6E7-ABC0-4146-A3D3-B2355FA84A5E","name":"phone-off","codepoint":"F0DEF","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"3.5.94"},{"id":"DDD4308D-34BE-4708-B9B6-E547DDAFC6B3","name":"phone-off-outline","codepoint":"F11A6","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"52280181-270B-4624-97FE-F46126C65BE7","name":"phone-outgoing","codepoint":"F03FB","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"1.5.54"},{"id":"AE3A49AE-0125-448B-8EFF-0146293FD123","name":"phone-outgoing-outline","codepoint":"F1199","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"4.5.95"},{"id":"79252282-1FDF-4DE8-A00F-51CD9D23311D","name":"phone-outline","codepoint":"F0DF0","aliases":["telephone-outline","call-outline"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"3.5.94"},{"id":"1ABFB2C1-72CB-46C7-8E8B-B8A24C0285EA","name":"phone-paused","codepoint":"F03FC","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"3DF9D1F2-FE29-4385-9741-4B7F4B381EE6","name":"phone-paused-outline","codepoint":"F119A","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"E58A5CD8-2D42-4A3A-BCC2-70870B43752C","name":"phone-plus","codepoint":"F0659","aliases":["add-call"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.6.50"},{"id":"64C853E0-F60C-435D-9E93-261CCE84B0EB","name":"phone-plus-outline","codepoint":"F119B","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"7AE0A1C1-0FFD-4182-93B5-95F2419AEE8E","name":"phone-remove","codepoint":"F152F","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"E829DF09-29F7-4FEF-A934-9C7A2119A628","name":"phone-remove-outline","codepoint":"F1530","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"B0FC2BB4-6C44-42CA-8F90-52CBCD0F1AD4","name":"phone-return","codepoint":"F082F","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"2.1.19"},{"id":"7D826B1C-8945-48EA-95F8-30F864E4EA7D","name":"phone-return-outline","codepoint":"F119C","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"4.5.95"},{"id":"280ECA2D-5D38-4B9E-81FA-58EEB580481A","name":"phone-ring","codepoint":"F11AB","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"172E080A-5125-42C8-83FB-980DDE41715C","name":"phone-ring-outline","codepoint":"F11AC","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Google","version":"4.5.95"},{"id":"48667BD8-2891-45D0-92E9-F4FF292527A4","name":"phone-rotate-landscape","codepoint":"F0885","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"2.1.99"},{"id":"B839A0B6-9E89-40C2-811F-2253514267C9","name":"phone-rotate-portrait","codepoint":"F0886","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"2.1.99"},{"id":"C9E81E97-C4DA-4612-AC4D-0F81C7986CD8","name":"phone-settings","codepoint":"F03FD","aliases":["settings-phone"],"tags":["Settings","Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"E4A0F700-DF2C-4A72-AE99-8249ADDBB5FD","name":"phone-settings-outline","codepoint":"F119D","aliases":[],"tags":["Cellphone \/ Phone","Settings"],"author":"Google","version":"4.5.95"},{"id":"43DAD9DC-C484-452A-9450-1F9C83C6B50E","name":"phone-voip","codepoint":"F03FE","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"1.5.54"},{"id":"0E3F11DA-8458-4A89-BB7B-D3A6972D3E30","name":"pi","codepoint":"F03FF","aliases":[],"tags":["Math"],"author":"Simran","version":"1.5.54"},{"id":"7C14B1F3-D836-42D6-AC5F-9FD31ADEBFFD","name":"pi-box","codepoint":"F0400","aliases":[],"tags":["Math"],"author":"Simran","version":"1.5.54"},{"id":"C41264FE-89C3-47A7-AE24-36F4B419B4E4","name":"pi-hole","codepoint":"F0DF1","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"3.5.94"},{"id":"E7651219-1BF9-4D06-9B4A-7599A2E0A407","name":"piano","codepoint":"F067D","aliases":[],"tags":["Music"],"author":"Austin Andrews","version":"1.7.12"},{"id":"A4DE211E-02E2-4514-9059-17AEFADA22F7","name":"pickaxe","codepoint":"F08B7","aliases":[],"tags":[],"author":"Michael Richins","version":"2.2.43"},{"id":"D184F762-16C9-4266-A485-8AA14A83A575","name":"picture-in-picture-bottom-right","codepoint":"F0E57","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"C9D5809D-900A-418A-98C3-2EF4106E620E","name":"picture-in-picture-bottom-right-outline","codepoint":"F0E58","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"C75700F6-A468-4452-BFFB-FFB4A496563B","name":"picture-in-picture-top-right","codepoint":"F0E59","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"3910AABC-4BEB-4D91-B35D-AAE58A1115C8","name":"picture-in-picture-top-right-outline","codepoint":"F0E5A","aliases":[],"tags":[],"author":"Google","version":"3.6.95"},{"id":"68AE7D9F-95E4-4AAC-B39F-748FD8677ACF","name":"pier","codepoint":"F0887","aliases":[],"tags":["Places","Transportation + Water"],"author":"Michael Irigoyen","version":"2.1.99"},{"id":"547D5950-A129-411D-92AF-B8477D21230D","name":"pier-crane","codepoint":"F0888","aliases":[],"tags":["Transportation + Water"],"author":"Michael Irigoyen","version":"2.1.99"},{"id":"5E4A3F96-7779-44C8-86EF-948EDBD53C20","name":"pig","codepoint":"F0401","aliases":[],"tags":["Animal","Agriculture"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A25A5576-C967-444E-989D-750CD275BF27","name":"pig-variant","codepoint":"F1006","aliases":[],"tags":["Animal","Agriculture"],"author":"Alex Efremo","version":"4.0.96"},{"id":"04A432B2-ABA5-49D7-9650-D6518D5D0A94","name":"pig-variant-outline","codepoint":"F1678","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.7.55"},{"id":"7168E9C8-32AE-4E0F-B3A4-EA05452C63C0","name":"piggy-bank","codepoint":"F1007","aliases":[],"tags":["Banking"],"author":"Alex Efremo","version":"4.0.96"},{"id":"37D67BA6-70A1-44C4-9C62-0647BBB7CDA2","name":"piggy-bank-outline","codepoint":"F1679","aliases":[],"tags":["Banking"],"author":"Contributors","version":"5.7.55"},{"id":"6487E4ED-C501-416C-9DCE-1B7C1F676050","name":"pill","codepoint":"F0402","aliases":["medicine","capsule","drug","pharmaceutical"],"tags":["Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AD451D24-BA4B-466E-8146-D3FBBDA6E275","name":"pillar","codepoint":"F0702","aliases":["historic","column"],"tags":[],"author":"GreenTurtwig","version":"1.8.36"},{"id":"B1337135-0E57-465F-8C0C-E658C9981A19","name":"pin","codepoint":"F0403","aliases":["keep"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8C59FE68-D89C-4A86-8E01-5C8109D1B028","name":"pin-off","codepoint":"F0404","aliases":["keep-off"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0ED785A3-7387-4989-BF3A-11F2F53C81B5","name":"pin-off-outline","codepoint":"F0930","aliases":["keep-off-outline"],"tags":[],"author":"Contributors","version":"2.3.54"},{"id":"BF736212-EE8D-49D0-8C8B-63A463488E88","name":"pin-outline","codepoint":"F0931","aliases":["keep-outline"],"tags":[],"author":"Google","version":"2.3.54"},{"id":"F053196C-66BC-4D0D-B75F-24773CA618E5","name":"pine-tree","codepoint":"F0405","aliases":["forest","plant"],"tags":["Holiday","Nature","Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A8F37CBB-10AA-42DE-9CD6-BDCE10C2AF8C","name":"pine-tree-box","codepoint":"F0406","aliases":["plant"],"tags":["Holiday","Nature"],"author":"Austin Andrews","version":"1.5.54"},{"id":"707539BB-56A1-4346-B907-95DEE51799A3","name":"pine-tree-fire","codepoint":"F141A","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.2.45"},{"id":"6BAC7A7E-340B-474D-8448-2DEC0FE66146","name":"pinterest","codepoint":"F0407","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"BB298846-B608-4289-987C-A8F2A904409F","name":"pinwheel","codepoint":"F0AD5","aliases":["toys"],"tags":[],"author":"Google","version":"2.7.94"},{"id":"279BF513-8015-4F28-83FD-B69CE7E0EB78","name":"pinwheel-outline","codepoint":"F0AD6","aliases":["toys-outline"],"tags":[],"author":"Google","version":"2.7.94"},{"id":"840AF950-F514-452B-AD1F-18EC878CB1F8","name":"pipe","codepoint":"F07E5","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"2.0.46"},{"id":"01D59BE4-7863-471D-840D-8C810F934344","name":"pipe-disconnected","codepoint":"F07E6","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"2.0.46"},{"id":"A39D910A-D5C9-4A9D-86CF-F61A60486758","name":"pipe-leak","codepoint":"F0889","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"5767EA8C-592F-4CEF-A01D-52F3CD0D111E","name":"pipe-wrench","codepoint":"F1354","aliases":["monkey-wrench"],"tags":["Hardware \/ Tools"],"author":"Google","version":"4.9.95"},{"id":"5CDFFABD-F3B4-4E4D-97A3-F8B1AE403809","name":"pirate","codepoint":"F0A08","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"34C9947D-5943-4C3E-9E7A-2CD95061222B","name":"pistol","codepoint":"F0703","aliases":["gun"],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"212476A4-B98A-4A84-BE27-37F28847A7D2","name":"piston","codepoint":"F088A","aliases":[],"tags":["Automotive"],"author":"Michael Richins","version":"2.1.99"},{"id":"BD8E12AD-25AA-42FA-9C9C-EA023794A93D","name":"pitchfork","codepoint":"F1553","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"E617E8BD-2C63-4E59-B1F4-EB3F9F3916D3","name":"pizza","codepoint":"F0409","aliases":["pizzeria","local-pizza"],"tags":["Food \/ Drink","Places"],"author":"Google","version":"1.5.54"},{"id":"90AD6D2A-7986-49D0-8DA5-DC92F9F92A15","name":"play","codepoint":"F040A","aliases":["play-arrow"],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"B60DF8C7-F693-4E2B-B5AB-65CA6DC21A8E","name":"play-box","codepoint":"F127A","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.7.95"},{"id":"9700DCD7-8658-479A-A817-1241A09F9654","name":"play-box-multiple","codepoint":"F0D19","aliases":[],"tags":[],"author":"Google","version":"3.3.92"},{"id":"73F0C681-0A20-484A-B276-3EE052090089","name":"play-box-multiple-outline","codepoint":"F13E6","aliases":[],"tags":[],"author":"Google","version":"5.1.45"},{"id":"D0431F42-A1C2-409B-9D44-2EDDEF3F9AB3","name":"play-box-outline","codepoint":"F040B","aliases":["slideshow"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"79F68E60-010F-4A8E-8E30-06CB64A5DBF6","name":"play-circle","codepoint":"F040C","aliases":["play-circle-filled"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"E0C875C2-16F3-4C92-BABF-DAB2D08258DC","name":"play-circle-outline","codepoint":"F040D","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"5B10237B-B7AA-4B35-B8C0-C97747F1E3E7","name":"play-network","codepoint":"F088B","aliases":["media-network"],"tags":[],"author":"Michael Richins","version":"2.1.99"},{"id":"951FE34F-7D2E-45FF-8014-FB4EBC49BED1","name":"play-network-outline","codepoint":"F0CB7","aliases":["media-network-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"554AC834-1F9C-401A-86F5-E26FFD201683","name":"play-outline","codepoint":"F0F1B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"93DAA69E-9A21-4D5A-B6B1-0AF0A24B7FEB","name":"play-pause","codepoint":"F040E","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"FEB9507A-DA7D-4CB3-918A-E64BBB9D4CC9","name":"play-protected-content","codepoint":"F040F","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"72410FAF-5315-452B-ACE1-C0FEB3B897F8","name":"play-speed","codepoint":"F08FF","aliases":[],"tags":[],"author":"Google","version":"2.3.50"},{"id":"F3E26F6E-9F9A-490B-A28A-1BD32A60D143","name":"playlist-check","codepoint":"F05C7","aliases":["subscriptions","playlist-add-check","playlist-tick"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"EBBE4C11-9C6D-40AA-844A-167B274A4E81","name":"playlist-edit","codepoint":"F0900","aliases":[],"tags":["Edit \/ Modify"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"1D472295-8F79-4F51-B68A-63A2CD2DF634","name":"playlist-minus","codepoint":"F0410","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"F7BFD179-3B1E-4347-BD64-C51686B00E65","name":"playlist-music","codepoint":"F0CB8","aliases":["playlist-note","queue-music"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"97526C1D-E3B9-4900-8C13-3969E80949B3","name":"playlist-music-outline","codepoint":"F0CB9","aliases":["playlist-note-outline","queue-music-outline"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"313918D8-1CB9-40FC-B24F-3A974F1A6EAF","name":"playlist-play","codepoint":"F0411","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"350D7B60-3F36-4FB0-9959-B90625F5267C","name":"playlist-plus","codepoint":"F0412","aliases":["playlist-add"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"526856F3-6DF1-454A-B905-3DA120370563","name":"playlist-remove","codepoint":"F0413","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"80A0AA10-9B8E-4AAA-BDEA-EDDADB94A7CC","name":"playlist-star","codepoint":"F0DF2","aliases":[],"tags":[],"author":"Google","version":"3.5.94"},{"id":"D390D1E2-571E-49DB-BBB9-9D3821EAF819","name":"plex","codepoint":"F06BA","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.7.22"},{"id":"2DE4F8E6-F25C-4FCA-8405-109FA8918B78","name":"plus","codepoint":"F0415","aliases":["add"],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"87EE041D-81D2-4F1A-A757-F76E9D8686EF","name":"plus-box","codepoint":"F0416","aliases":["add-box"],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"BF1B666E-57AC-41B0-950B-4F4060BDF601","name":"plus-box-multiple","codepoint":"F0334","aliases":["add-to-photos","library-add","queue","library-plus"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"910CB053-6597-49C2-A20D-EBC310D03364","name":"plus-box-multiple-outline","codepoint":"F1143","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"75A7BDE6-40BC-4938-AFCD-D4DDF1B65B2A","name":"plus-box-outline","codepoint":"F0704","aliases":[],"tags":["Math"],"author":"Google","version":"1.8.36"},{"id":"0F76DADF-2A8D-4C1F-B43E-DC3C6D282BBF","name":"plus-circle","codepoint":"F0417","aliases":["add-circle"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"93BBA1EA-76F8-4D2E-B4D0-98F684B15AC3","name":"plus-circle-multiple","codepoint":"F034C","aliases":["coins-plus"],"tags":[],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"0C5565E9-9E74-4E50-BF9E-6F904BB83E52","name":"plus-circle-multiple-outline","codepoint":"F0418","aliases":["control-point-duplicate","plus-circles-outline","coins-plus-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"EFB8C700-D60B-4995-B8DE-F3A3E2DA75F3","name":"plus-circle-outline","codepoint":"F0419","aliases":["add-circle-outline","control-point","circles-add"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"34BDA78C-9BF6-441A-9924-E8619719C333","name":"plus-minus","codepoint":"F0992","aliases":[],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"C8A8A7E4-7745-4CA1-A99B-724C2471CAF5","name":"plus-minus-box","codepoint":"F0993","aliases":[],"tags":["Math"],"author":"Nick","version":"2.4.85"},{"id":"D86C99FA-DFA7-4DD2-9EB8-CBB094BD1366","name":"plus-minus-variant","codepoint":"F14C9","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"5.3.45"},{"id":"14F6A9EC-BD40-4181-B084-05A9FCFA3973","name":"plus-network","codepoint":"F041A","aliases":["add-network"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"349600D3-B39C-46C2-8E61-5A256C4BA98C","name":"plus-network-outline","codepoint":"F0CBA","aliases":["add-network-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"E67044BA-8025-4D61-916C-56DF4D6FFE6D","name":"plus-one","codepoint":"F041B","aliases":[],"tags":[],"author":"Google","version":"1.5.54","deprecated":true},{"id":"680B6AD6-C9AD-44D1-9228-EDDB8C242343","name":"plus-outline","codepoint":"F0705","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"2FD9933D-7226-4745-B5DB-C8E6245FB170","name":"plus-thick","codepoint":"F11EC","aliases":["add-thick","add-bold","plus-bold"],"tags":["Math"],"author":"Austin Andrews","version":"4.5.95"},{"id":"56B37BA8-E973-4B53-812A-7F47BCFF217A","name":"podcast","codepoint":"F0994","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"9C9AF6D4-1E8A-414A-9935-B7B8BE9F0962","name":"podium","codepoint":"F0D25","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"3.3.92"},{"id":"4F2BE6B3-071D-4EE3-8E86-71F0AF06619F","name":"podium-bronze","codepoint":"F0D26","aliases":["podium-third"],"tags":["Sport"],"author":"Michael Richins","version":"3.3.92"},{"id":"CB4B60CC-1B22-4288-997F-D59FE2AFC198","name":"podium-gold","codepoint":"F0D27","aliases":["podium-first"],"tags":["Sport"],"author":"Michael Richins","version":"3.3.92"},{"id":"FF783CFF-DD54-492C-A1E1-323AB6CAAFC1","name":"podium-silver","codepoint":"F0D28","aliases":["podium-second"],"tags":["Sport"],"author":"Michael Richins","version":"3.3.92"},{"id":"1DDDF76A-2C40-4BEE-87B1-0B95D4E233DA","name":"point-of-sale","codepoint":"F0D92","aliases":[],"tags":[],"author":"Contributors","version":"3.4.93"},{"id":"48329A9B-7B16-469C-9D64-B2E9381620BF","name":"pokeball","codepoint":"F041D","aliases":[],"tags":["Gaming \/ RPG"],"author":"Contributors","version":"1.5.54"},{"id":"A1D5B3DC-2A72-4548-AB36-985E98BB6FCE","name":"pokemon-go","codepoint":"F0A09","aliases":[],"tags":["Gaming \/ RPG"],"author":"Contributors","version":"2.5.94"},{"id":"D73F724D-EEE6-43EC-BA3A-E185ABD7A258","name":"poker-chip","codepoint":"F0830","aliases":["casino-chip","gambling-chip"],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"2.1.19"},{"id":"8408CE08-26C2-49B9-95CE-C5A9AAF4455E","name":"polaroid","codepoint":"F041E","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"80E26409-5A5C-4BDC-9722-8A8CC6981B90","name":"police-badge","codepoint":"F1167","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"9262CC3D-85E6-4881-AE14-B760E93DBBFE","name":"police-badge-outline","codepoint":"F1168","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"C4A1DAE5-04E0-47EF-84D8-CB81FA58EF87","name":"poll","codepoint":"F041F","aliases":["bar-chart"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"5FFF2FB6-08B2-4860-ACCF-72D614641882","name":"poll-box","codepoint":"F0420","aliases":["assessment","insert-chart"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"32388085-89F4-4C2C-BE98-1AEBED8F9B95","name":"poll-box-outline","codepoint":"F127B","aliases":[],"tags":[],"author":"Google","version":"4.7.95"},{"id":"5ACE4E72-9576-405A-A17F-314A1FF864C8","name":"polo","codepoint":"F14C3","aliases":[],"tags":["Sport"],"author":"Google","version":"5.3.45"},{"id":"528FF16A-C55C-43F9-8E0B-3879A209AEDE","name":"polymer","codepoint":"F0421","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"1.5.54"},{"id":"F42C2F0C-BEFC-46EB-A46C-665032BD6641","name":"pool","codepoint":"F0606","aliases":["swimming-pool"],"tags":["Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3401BCC7-DECF-4A92-9B6C-34AF063B2FED","name":"popcorn","codepoint":"F0422","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9B1DF082-5266-408A-A057-92E9AEB81BFA","name":"post","codepoint":"F1008","aliases":["blog"],"tags":[],"author":"Google","version":"4.0.96"},{"id":"A7CB61B3-B3C5-4EEE-AC94-D0B2347FFA1B","name":"post-outline","codepoint":"F1009","aliases":["blog-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"D76042A4-6370-4DF4-BF35-B00BE339805A","name":"postage-stamp","codepoint":"F0CBB","aliases":[],"tags":[],"author":"Simran","version":"3.2.89"},{"id":"267AF23F-D48A-493E-91BD-E78CD3EFCCBA","name":"pot","codepoint":"F02E5","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"1.5.54"},{"id":"C264A721-9CFD-4AE5-BD97-404E7DCDC6C2","name":"pot-mix","codepoint":"F065B","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"1.6.50"},{"id":"857C302E-0AC9-438D-A8E5-DE3DC9680FAB","name":"pot-mix-outline","codepoint":"F0677","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"1.7.12"},{"id":"EB68865A-2308-4667-9B2F-C550923180A9","name":"pot-outline","codepoint":"F02FF","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"1.5.54"},{"id":"444286FD-F41C-4945-BF9D-7C2913EC663E","name":"pot-steam","codepoint":"F065A","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"1.6.50"},{"id":"A6C14603-8189-4CC5-82CF-1231422B6F70","name":"pot-steam-outline","codepoint":"F0326","aliases":[],"tags":["Food \/ Drink"],"author":"Simran","version":"1.5.54"},{"id":"9344AA1D-FF8B-432F-A314-C416DFA37F12","name":"pound","codepoint":"F0423","aliases":["hashtag"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"597DF175-F0F5-4892-9F13-EA712DBC947E","name":"pound-box","codepoint":"F0424","aliases":["hashtag-box"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"BC212E3B-C9D9-4FC5-B73B-DDA77D94A5C9","name":"pound-box-outline","codepoint":"F117F","aliases":["hashtag-box-outline"],"tags":[],"author":"Michael Richins","version":"4.4.95"},{"id":"C945D203-9737-4C25-87CA-29D97B862DD2","name":"power","codepoint":"F0425","aliases":["power-settings-new","shutdown"],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"DD119EDC-92B2-48F6-8014-73AD2AB65DA7","name":"power-cycle","codepoint":"F0901","aliases":[],"tags":[],"author":"Michael Richins","version":"2.3.50"},{"id":"39D3928C-2739-4A57-A81C-3DF67328A160","name":"power-off","codepoint":"F0902","aliases":[],"tags":[],"author":"Michael Richins","version":"2.3.50"},{"id":"566141F9-DB64-4210-8384-EB77CFA9E8A0","name":"power-on","codepoint":"F0903","aliases":[],"tags":[],"author":"Michael Richins","version":"2.3.50"},{"id":"60E77DB8-2D58-462F-8512-41D9E0E42795","name":"power-plug","codepoint":"F06A5","aliases":[],"tags":["Home Automation"],"author":"Google","version":"1.7.12"},{"id":"ACF38F54-4726-4F8F-9916-8C582137FA69","name":"power-plug-off","codepoint":"F06A6","aliases":["power-off"],"tags":["Home Automation"],"author":"Simran","version":"1.7.12"},{"id":"D4F5AEAB-DD00-4101-8661-13260BE9D087","name":"power-plug-off-outline","codepoint":"F1424","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"E439723C-E8DA-4BD6-8AE8-F944FD96B31D","name":"power-plug-outline","codepoint":"F1425","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"B5587844-E70A-4F55-A2DA-CE85D8F79689","name":"power-settings","codepoint":"F0426","aliases":["settings-power"],"tags":["Settings"],"author":"Google","version":"1.5.54"},{"id":"AA011772-1BE4-4E00-A838-9D0D1DCA2773","name":"power-sleep","codepoint":"F0904","aliases":[],"tags":[],"author":"Michael Richins","version":"2.3.50"},{"id":"175A9E67-3723-4D49-85EC-8D34B4BA0C14","name":"power-socket","codepoint":"F0427","aliases":["plug-socket"],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"CFCF8409-65AC-4E1C-885B-107F9D8B4413","name":"power-socket-au","codepoint":"F0905","aliases":["plug-socket-au","power-socket-type-i","power-socket-cn","power-socket-ar","power-socket-nz","power-socket-pg","power-socket-australia","power-socket-china","power-socket-argentina","power-socket-new-zealand","power-socket-papua-new-guinea"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"14654BFB-0D87-43E0-8A47-7CF1EE1CF418","name":"power-socket-de","codepoint":"F1107","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"4.3.95"},{"id":"07F4FD1C-A171-4088-BE30-53758CFF45E5","name":"power-socket-eu","codepoint":"F07E7","aliases":["plug-socket-eu","power-socket-europe"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"85338D53-181D-46E9-AEA7-D524B0DFBA4A","name":"power-socket-fr","codepoint":"F1108","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"4.3.95"},{"id":"D7106221-1ABC-4E8E-9345-E2B23D5D74B9","name":"power-socket-it","codepoint":"F14FF","aliases":[],"tags":[],"author":"Contributors","version":"5.4.55"},{"id":"98D7A146-D68E-4E80-B8F1-5235DAECD976","name":"power-socket-jp","codepoint":"F1109","aliases":[],"tags":["Home Automation"],"author":"Haley Halcyon","version":"4.3.95"},{"id":"E9F0AC95-A660-4FB1-BE5D-20153B709E15","name":"power-socket-uk","codepoint":"F07E8","aliases":["plug-socket-uk","power-socket-type-g","power-socket-ie","power-socket-hk","power-socket-my","power-socket-cy","power-socket-mt","power-socket-sg","power-socket-united-kingdom","power-socket-ireland","power-socket-hong-kong","power-socket-malaysia","power-socket-cyprus","power-socket-malta","power-socket-singapore"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"C4F7F8FF-3465-4F85-B615-B852A6919100","name":"power-socket-us","codepoint":"F07E9","aliases":["plug-socket-us","power-socket-ca","power-socket-mx","power-socket-type-b","power-socket-united-states","power-socket-japan","power-socket-canada","power-socket-mexico"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"3AC74CF9-0EC1-475D-A164-7C9CA0D48B58","name":"power-standby","codepoint":"F0906","aliases":[],"tags":[],"author":"Michael Richins","version":"2.3.50"},{"id":"2DB269A5-0CD6-4139-8C24-A4A1F7D96596","name":"powershell","codepoint":"F0A0A","aliases":[],"tags":[],"author":"Contributors","version":"2.5.94"},{"id":"DEF7F9EA-ACA8-452E-B587-6524BE7D67EE","name":"prescription","codepoint":"F0706","aliases":[],"tags":["Medical \/ Hospital"],"author":"Roberto Graham","version":"1.8.36"},{"id":"DAEB5F87-858A-4677-B023-C9EC71F99F6C","name":"presentation","codepoint":"F0428","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E182F4B3-B2B0-41CD-90DC-5ADFBE25DA90","name":"presentation-play","codepoint":"F0429","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"607F7E94-DBF5-4D5D-8F3A-5E1F90E1FF61","name":"pretzel","codepoint":"F1562","aliases":[],"tags":["Food \/ Drink"],"author":"Nicolas Gres","version":"5.5.55"},{"id":"7365D689-4C10-4EBA-AD9A-09189B8091EE","name":"printer","codepoint":"F042A","aliases":["local-printshop","local-print-shop"],"tags":["Printer","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"86A3D6B7-6C8B-4883-B51B-753DEF0F4A62","name":"printer-3d","codepoint":"F042B","aliases":[],"tags":["Printer","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3A3AA67C-5DB4-40CA-9D0B-43843190CCDC","name":"printer-3d-nozzle","codepoint":"F0E5B","aliases":[],"tags":["Printer"],"author":"Contributors","version":"3.6.95"},{"id":"5AB50A00-46F7-4294-8462-EDD32EA7309A","name":"printer-3d-nozzle-alert","codepoint":"F11C0","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"4.5.95"},{"id":"5EEF9AB7-11DF-4612-A037-55705DA3AB19","name":"printer-3d-nozzle-alert-outline","codepoint":"F11C1","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"4.5.95"},{"id":"7B1B16E0-AB42-490D-8D84-62B9AA0AB4BD","name":"printer-3d-nozzle-outline","codepoint":"F0E5C","aliases":[],"tags":["Printer"],"author":"Contributors","version":"3.6.95"},{"id":"DD64AF52-2610-43D3-A992-9F3FCCB4A576","name":"printer-alert","codepoint":"F042C","aliases":["printer-warning","paper-jam"],"tags":["Printer","Home Automation","Alert \/ Error"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3C750D11-158A-4FED-A7A8-22B4D74DF4BC","name":"printer-check","codepoint":"F1146","aliases":[],"tags":["Printer"],"author":"Terren","version":"4.4.95"},{"id":"22BB79BD-B17E-4002-923E-5B6766B967DC","name":"printer-eye","codepoint":"F1458","aliases":["printer-preview","printer-view"],"tags":["Printer"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"328D470F-EEB4-486D-953B-6F84CE809C3C","name":"printer-off","codepoint":"F0E5D","aliases":[],"tags":["Printer"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"F9D30BAE-7AF6-4C02-83AD-18045895B8B0","name":"printer-pos","codepoint":"F1057","aliases":["printer-point-of-sale"],"tags":["Printer"],"author":"Michael Richins","version":"4.1.95"},{"id":"18383BEA-BF9A-43AD-87BB-F47CEC92F9C3","name":"printer-search","codepoint":"F1457","aliases":["printer-preview","printer-magnify"],"tags":["Printer"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"33E4D9A3-F8C1-4C58-9E88-977AE4F4E4CA","name":"printer-settings","codepoint":"F0707","aliases":[],"tags":["Settings","Printer"],"author":"Simran","version":"1.8.36"},{"id":"E9B8B42B-CA7D-4499-B610-CABBDCF51C0E","name":"printer-wireless","codepoint":"F0A0B","aliases":[],"tags":["Printer"],"author":"Michael Richins","version":"2.5.94"},{"id":"FA96A5AC-D499-4C13-93C7-7A422A5DE4B7","name":"priority-high","codepoint":"F0603","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DFC698A7-3040-48F4-A341-C1E667A4FE22","name":"priority-low","codepoint":"F0604","aliases":["low-priority"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"53EA516B-544D-4DC3-90BD-3A5C4838923C","name":"professional-hexagon","codepoint":"F042D","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"82FBA8C9-B8BE-4CA6-883C-E07C36723627","name":"progress-alert","codepoint":"F0CBC","aliases":["progress-warning"],"tags":["Alert \/ Error"],"author":"Michael Richins","version":"3.2.89"},{"id":"943E027B-964A-4CE2-BDD7-44A9703A73B1","name":"progress-check","codepoint":"F0995","aliases":["progress-tick"],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"D7A33F97-FA45-4719-901A-A1F91E671FC2","name":"progress-clock","codepoint":"F0996","aliases":[],"tags":["Date \/ Time"],"author":"Peter Noble","version":"2.4.85"},{"id":"294CC691-6D3C-47DB-B142-8F4DE633DE92","name":"progress-close","codepoint":"F110A","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"9D94B21B-52A0-4F73-AEFB-85FEA76C8624","name":"progress-download","codepoint":"F0997","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.4.85"},{"id":"DBF80F38-9B3D-4390-B366-51827F97CC0F","name":"progress-question","codepoint":"F1522","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"699B5A10-1C4C-448C-A3F4-36A3CACD82EA","name":"progress-upload","codepoint":"F0998","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.4.85"},{"id":"D0721C85-4507-43CE-8E0B-21522D641993","name":"progress-wrench","codepoint":"F0CBD","aliases":["progress-spanner"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"D23095BD-C1C0-4FED-B114-CE9CF9DD5DB6","name":"projector","codepoint":"F042E","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"A152DD64-B013-4AE7-B89F-49FC90B2E471","name":"projector-screen","codepoint":"F042F","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"F2AC4968-73F6-4D91-BF2B-D8653E6863E2","name":"projector-screen-outline","codepoint":"F1724","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"F6911BCA-14B1-4DD4-9407-20E138FAB878","name":"propane-tank","codepoint":"F1357","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"03A9105D-F79F-454C-9EE2-4E96A1BBA908","name":"propane-tank-outline","codepoint":"F1358","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"16D49AC9-5D43-4401-980B-C9DF4593838A","name":"protocol","codepoint":"F0FD8","aliases":[],"tags":[],"author":"Michael Richins","version":"4.0.96"},{"id":"7E1AC29D-46E3-4C7C-9A00-D8803E502795","name":"publish","codepoint":"F06A7","aliases":[],"tags":[],"author":"Google","version":"1.7.12"},{"id":"2A0F7B5D-5D23-4E76-B97D-9D2281D3C4EA","name":"pulse","codepoint":"F0430","aliases":["vitals"],"tags":["Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4FDD16EB-0E78-46BF-B077-A9C077C3C1B8","name":"pump","codepoint":"F1402","aliases":[],"tags":[],"author":"Contributors","version":"5.1.45"},{"id":"CAA05089-AC62-40FF-96F1-82E34B93F18F","name":"pumpkin","codepoint":"F0BBF","aliases":[],"tags":["Holiday"],"author":"Austin Andrews","version":"3.0.39"},{"id":"4B431C82-5923-49D9-8849-6E7EF6C7661D","name":"purse","codepoint":"F0F1C","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"3.8.95"},{"id":"16CB0045-C446-4384-8031-B3CEDDE555EE","name":"purse-outline","codepoint":"F0F1D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"3.8.95"},{"id":"0773D18C-C6A2-41B5-9685-F3E0507E1770","name":"puzzle","codepoint":"F0431","aliases":["extension","jigsaw"],"tags":["Gaming \/ RPG"],"author":"Google","version":"1.5.54"},{"id":"034B7820-702C-45F8-ABE3-473AC1770BB2","name":"puzzle-check","codepoint":"F1426","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"5.2.45"},{"id":"BA363BBC-F40B-4D14-B677-6FEFD1D48B87","name":"puzzle-check-outline","codepoint":"F1427","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"5.2.45"},{"id":"DA95A80F-202E-48F3-9BCD-302C5AAD3BA2","name":"puzzle-edit","codepoint":"F14D3","aliases":[],"tags":["Gaming \/ RPG","Edit \/ Modify"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"824D28CA-335E-4C36-BAD7-8685FF2FB8A7","name":"puzzle-edit-outline","codepoint":"F14D9","aliases":[],"tags":["Gaming \/ RPG","Edit \/ Modify"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"F489D7C7-0696-4970-86B0-6216D73177D0","name":"puzzle-heart","codepoint":"F14D4","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"B588380E-4BAD-4787-B699-906B8926068D","name":"puzzle-heart-outline","codepoint":"F14DA","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"8DAE6108-0411-473A-B835-528DC330D1DF","name":"puzzle-minus","codepoint":"F14D1","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"56014EED-5E51-46CE-B231-D48463CFBF30","name":"puzzle-minus-outline","codepoint":"F14D7","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"BBAC40CD-6A3A-4EEF-A381-DB7C8950995E","name":"puzzle-outline","codepoint":"F0A66","aliases":["jigsaw-outline","extension-outline"],"tags":["Gaming \/ RPG"],"author":"Google","version":"2.6.95"},{"id":"72A20545-216C-4CD8-B1E4-808B8B2B96B6","name":"puzzle-plus","codepoint":"F14D0","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"46577FE3-F2BF-4B41-B50D-3E6ABD7484B0","name":"puzzle-plus-outline","codepoint":"F14D6","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"29CE71EA-2734-48D2-9FFD-FEB8ADF50C12","name":"puzzle-remove","codepoint":"F14D2","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"05B602BB-4734-4D4B-A268-FE31171DBD66","name":"puzzle-remove-outline","codepoint":"F14D8","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"0DA18E4C-075B-4DE5-A428-31FB0BA791E4","name":"puzzle-star","codepoint":"F14D5","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"72BEE187-7B9C-4106-92EA-CD040D56815F","name":"puzzle-star-outline","codepoint":"F14DB","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"1F897ED3-17CC-43F5-9A0B-F7804A8DFABF","name":"qi","codepoint":"F0999","aliases":[],"tags":[],"author":"Contributors","version":"2.4.85"},{"id":"6EAADAE4-30AE-4F69-888F-364BBAFFF5E7","name":"qqchat","codepoint":"F0605","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"779E7DDE-0ACE-4752-9966-22761E2A128A","name":"qrcode","codepoint":"F0432","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"603BF7E7-03A6-4141-8A50-CA124B62C621","name":"qrcode-edit","codepoint":"F08B8","aliases":[],"tags":["Edit \/ Modify"],"author":"Michael Richins","version":"2.2.43"},{"id":"2DD6D091-2E48-41D6-A9E1-67BF485B103E","name":"qrcode-minus","codepoint":"F118C","aliases":[],"tags":[],"author":"Peter Noble","version":"4.4.95"},{"id":"B86DA56E-59D6-4B0B-BE63-D66496C8E6EB","name":"qrcode-plus","codepoint":"F118B","aliases":[],"tags":[],"author":"Peter Noble","version":"4.4.95"},{"id":"D41EE63E-AFC3-4A60-891F-841AF0AEBF22","name":"qrcode-remove","codepoint":"F118D","aliases":[],"tags":[],"author":"Peter Noble","version":"4.4.95"},{"id":"C8A7580B-5288-4A60-8033-797EB07A05AC","name":"qrcode-scan","codepoint":"F0433","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"E81082B7-E851-4407-B0D2-08CC105C6A5D","name":"quadcopter","codepoint":"F0434","aliases":["drone"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"C07BA504-080D-4B47-AD4D-7F772E5C92F3","name":"quality-high","codepoint":"F0435","aliases":["high-quality","hq"],"tags":["Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"51E44ABD-8132-4758-905E-4F46784ED768","name":"quality-low","codepoint":"F0A0C","aliases":["low-quality","lq"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"C987C0CA-2D23-427B-8F9C-F3E10B32156C","name":"quality-medium","codepoint":"F0A0D","aliases":["medium-quality","mq"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"F4C8FDC5-0F7D-4EDA-8242-B356F5E542A4","name":"quora","codepoint":"F0D29","aliases":[],"tags":[],"author":"Contributors","version":"3.3.92"},{"id":"1D7338F8-4F44-43E3-906B-571178E63E49","name":"rabbit","codepoint":"F0907","aliases":["bunny"],"tags":["Animal"],"author":"Augustin Ursu","version":"2.3.50"},{"id":"59B7D141-A76F-4794-A484-CE089FCF7C46","name":"racing-helmet","codepoint":"F0D93","aliases":[],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"0E46DC98-E185-4B26-A4E9-FC1CEC750172","name":"racquetball","codepoint":"F0D94","aliases":["lacrosse","squash"],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"73BD6C2A-0D5B-4DF6-9FA3-EC489AFBF947","name":"radar","codepoint":"F0437","aliases":["track-changes"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BFFA61BF-959B-4E15-BE31-4D9AFB5E3FDF","name":"radiator","codepoint":"F0438","aliases":["heater"],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"79B0F153-88BE-4FCD-94CB-E44D648DAAE2","name":"radiator-disabled","codepoint":"F0AD7","aliases":["heater-disabled"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"F1BF1F5D-82C7-41EA-B9CD-325265C3D760","name":"radiator-off","codepoint":"F0AD8","aliases":["heater-off"],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"2FA21C1E-99C3-4C9B-AF46-8DF6B9F2A8FC","name":"radio","codepoint":"F0439","aliases":[],"tags":["Audio","Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"D0AEFF89-C011-4445-B685-A1366099D920","name":"radio-am","codepoint":"F0CBE","aliases":[],"tags":["Audio"],"author":"Michael Richins","version":"3.2.89"},{"id":"55BADC53-06EE-4199-8761-80AF2240DE1D","name":"radio-fm","codepoint":"F0CBF","aliases":[],"tags":["Audio"],"author":"Michael Richins","version":"3.2.89"},{"id":"6EE69D5F-CF42-4257-B974-470E397E0DC1","name":"radio-handheld","codepoint":"F043A","aliases":[],"tags":["Device \/ Tech"],"author":"Simran","version":"1.5.54"},{"id":"B39962EE-105B-4093-9B4C-6078FEA43DA2","name":"radio-off","codepoint":"F121C","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"8E5FC366-E9F8-40ED-A16D-CD6C87B0C5B1","name":"radio-tower","codepoint":"F043B","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D70016AF-1FEE-4E66-8D51-3DE1BAAC0031","name":"radioactive","codepoint":"F043C","aliases":["radiation"],"tags":["Science"],"author":"Yasmina Lembachar","version":"1.5.54"},{"id":"3AD51A23-9040-4D23-AE50-B28C6DFF82F6","name":"radioactive-off","codepoint":"F0EC1","aliases":["radiation-off"],"tags":["Science"],"author":"TheChilliPL","version":"3.7.94"},{"id":"10BF2326-3190-4C27-9040-E2F8F4961238","name":"radiobox-blank","codepoint":"F043D","aliases":["radio-button-unchecked"],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"BA101E5E-CDA9-45AA-B249-BD176AF11D95","name":"radiobox-marked","codepoint":"F043E","aliases":["radio-button-checked","record"],"tags":["Form"],"author":"Google","version":"1.5.54"},{"id":"17B9888B-F36F-4D44-9318-BBB6ADA0F61B","name":"radiology-box","codepoint":"F14C5","aliases":["x-ray-box"],"tags":["Medical \/ Hospital"],"author":"Simran","version":"5.3.45"},{"id":"75708207-7E52-443D-B1DE-5BA088AED95E","name":"radiology-box-outline","codepoint":"F14C6","aliases":["x-ray-box-outline"],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"DFD4C66B-CD4A-4524-A6DB-E3C2331C5DC6","name":"radius","codepoint":"F0CC0","aliases":["circle-radius","sphere-radius"],"tags":["Math"],"author":"Michael Richins","version":"3.2.89"},{"id":"51C82800-F946-45C3-A88B-B5D52BD6B80B","name":"radius-outline","codepoint":"F0CC1","aliases":["circle-radius-outline","sphere-radius-outline"],"tags":["Math"],"author":"Michael Richins","version":"3.2.89"},{"id":"7FC3FA6E-ED0B-4BCD-AF44-1125CC2CE3C4","name":"railroad-light","codepoint":"F0F1E","aliases":[],"tags":["Transportation + Other"],"author":"Michael Richins","version":"3.8.95"},{"id":"0523157C-6328-499C-A114-FDAD94CFDDAE","name":"rake","codepoint":"F1544","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"AFC49CE3-9442-4F15-B3EE-6C841A226040","name":"raspberry-pi","codepoint":"F043F","aliases":["raspberrypi"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"935371AF-0FF0-4D1E-86F8-DB6E5C5510F9","name":"ray-end","codepoint":"F0440","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"16DEE563-B4C3-4B6D-A47F-B23151965007","name":"ray-end-arrow","codepoint":"F0441","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"932F0926-4F5D-4ACA-B4E3-461837361212","name":"ray-start","codepoint":"F0442","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"5D6F58F7-61B8-4461-B284-4B0D6B031CA2","name":"ray-start-arrow","codepoint":"F0443","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0C572F61-2EF1-4F4D-9B53-8FE285BC0BFB","name":"ray-start-end","codepoint":"F0444","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B911CCA3-1237-45C3-BCE1-34CB034F8739","name":"ray-start-vertex-end","codepoint":"F15D8","aliases":[],"tags":[],"author":"Google","version":"5.6.55"},{"id":"B391C303-5456-4746-83DD-7862952E281E","name":"ray-vertex","codepoint":"F0445","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"F13DC81C-DF03-4A33-99D6-489FBDB5B29C","name":"react","codepoint":"F0708","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"1.8.36"},{"id":"36EB4754-ADCF-47B6-9863-4EFFB819FC93","name":"read","codepoint":"F0447","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"80E9E435-2478-4B48-99B8-D8BEF353AE5F","name":"receipt","codepoint":"F0449","aliases":["invoice"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"F84F1E59-868C-42CE-80EA-159588E83462","name":"record","codepoint":"F044A","aliases":["fiber-manual-record"],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"4B8F147B-1AE7-4CB5-BAD1-4F6793B79303","name":"record-circle","codepoint":"F0EC2","aliases":[],"tags":[],"author":"Peter Noble","version":"3.7.94"},{"id":"E9D05E0B-362E-4D08-A812-D8A6C8D8F0DB","name":"record-circle-outline","codepoint":"F0EC3","aliases":[],"tags":[],"author":"Peter Noble","version":"3.7.94"},{"id":"E62E5C13-5DC0-4881-BBD6-EFDEF13B73BB","name":"record-player","codepoint":"F099A","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"2.4.85"},{"id":"8C452244-41D8-46F9-AF74-665F62EF5E50","name":"record-rec","codepoint":"F044B","aliases":[],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"795894B8-2599-4FC8-9B4C-0A0896C6BBB4","name":"rectangle","codepoint":"F0E5E","aliases":[],"tags":["Shape"],"author":"Terren","version":"3.6.95"},{"id":"14FABBBE-A903-4400-AC7A-338B46DA0342","name":"rectangle-outline","codepoint":"F0E5F","aliases":[],"tags":["Shape"],"author":"Terren","version":"3.6.95"},{"id":"93C67522-76EA-4A1D-8C9D-29B0901BE55A","name":"recycle","codepoint":"F044C","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E4222CF9-9449-4325-A296-1E2897AF0720","name":"recycle-variant","codepoint":"F139D","aliases":[],"tags":[],"author":"Moma Design Studio","version":"5.0.45"},{"id":"8CDBB9B4-921B-47CC-9A06-D0F391666654","name":"reddit","codepoint":"F044D","aliases":[],"tags":["Social Media","Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"C225AD71-CD53-4F22-8A24-7D055457E5A5","name":"redhat","codepoint":"F111B","aliases":[],"tags":[],"author":"Contributors","version":"4.3.95"},{"id":"7061BAB7-4413-4666-A919-9DD8C4F405F9","name":"redo","codepoint":"F044E","aliases":["arrow"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"72717CF3-6D1D-4032-9799-1F553CAD067E","name":"redo-variant","codepoint":"F044F","aliases":["arrow"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"345B3651-D634-4069-8D6F-CB4A2CAD63B9","name":"reflect-horizontal","codepoint":"F0A0E","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.5.94"},{"id":"998E1E1F-98A2-4DA8-9FAD-E31C2677B8D6","name":"reflect-vertical","codepoint":"F0A0F","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.5.94"},{"id":"AD3C7A2B-0B64-4183-9452-C96EAAF3E08E","name":"refresh","codepoint":"F0450","aliases":["loop"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"9D88AEE3-9749-4B74-8F60-2995BD811AAA","name":"refresh-circle","codepoint":"F1377","aliases":[],"tags":[],"author":"Fran\u00e7ois Risoud","version":"4.9.95"},{"id":"3313CE4A-E2EF-4E46-8110-C0BF297D0C16","name":"regex","codepoint":"F0451","aliases":["regular-expression"],"tags":[],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"7FDB507F-A062-479D-8401-AFD4B723BA60","name":"registered-trademark","codepoint":"F0A67","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"DBD21D6F-818C-46D0-860A-89257B1BAB90","name":"reiterate","codepoint":"F1588","aliases":[],"tags":["Arrow"],"author":"Nicolas Gres","version":"5.5.55"},{"id":"FF422947-C9DA-45C1-BEBF-47A450A035CA","name":"relation-many-to-many","codepoint":"F1496","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"DC16CBA8-F156-4EF8-A18C-56A0DBA8B2D5","name":"relation-many-to-one","codepoint":"F1497","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"A7E9839D-C578-4FE4-ABEB-84FA70BC1926","name":"relation-many-to-one-or-many","codepoint":"F1498","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"2F3ABDAA-9F84-45DC-8913-51EEE0769D13","name":"relation-many-to-only-one","codepoint":"F1499","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"187F026D-5528-4DDB-AEDD-B921AD57DEEF","name":"relation-many-to-zero-or-many","codepoint":"F149A","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"0389409A-7A71-49DC-8296-2F38C2A6E7FE","name":"relation-many-to-zero-or-one","codepoint":"F149B","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"C3AABB15-5720-463D-B37C-4552C1F4BE34","name":"relation-one-or-many-to-many","codepoint":"F149C","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"5EABC280-A332-4EA2-A6EE-D5D1E5DE6812","name":"relation-one-or-many-to-one","codepoint":"F149D","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"F6B51EA0-D90A-4B65-9B0C-8AD08392C943","name":"relation-one-or-many-to-one-or-many","codepoint":"F149E","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"2DC9A1E1-BE10-4643-B02E-7DE27F7F140C","name":"relation-one-or-many-to-only-one","codepoint":"F149F","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"E19D3A76-6993-4948-8F18-F777E3CA7383","name":"relation-one-or-many-to-zero-or-many","codepoint":"F14A0","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"F7CAF815-B3D6-490B-8AC6-B2FAB8F5134D","name":"relation-one-or-many-to-zero-or-one","codepoint":"F14A1","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"9FCECCB1-41CC-4569-9912-58256B627F37","name":"relation-one-to-many","codepoint":"F14A2","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"BDF61FAA-2D63-4114-93A8-5E13404E7B03","name":"relation-one-to-one","codepoint":"F14A3","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"757670CA-87BA-452B-A0D9-ECBB3EF21AA8","name":"relation-one-to-one-or-many","codepoint":"F14A4","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"56A95C81-F579-4D28-A5E5-32F44CF67BD3","name":"relation-one-to-only-one","codepoint":"F14A5","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"0FC49382-3ED0-437F-8522-29C5F5352C30","name":"relation-one-to-zero-or-many","codepoint":"F14A6","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"543B9D69-53A1-4DC3-8074-86123BC0CC70","name":"relation-one-to-zero-or-one","codepoint":"F14A7","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"55569D10-FC5C-4E3C-8A35-876DCC12D543","name":"relation-only-one-to-many","codepoint":"F14A8","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"26A310F2-347A-45E5-AD73-1D92443A1827","name":"relation-only-one-to-one","codepoint":"F14A9","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"57C9B4B7-CE27-4769-9D2F-50926D1F1A29","name":"relation-only-one-to-one-or-many","codepoint":"F14AA","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"23DF7622-E2D4-45E0-A646-CA10B71EBC10","name":"relation-only-one-to-only-one","codepoint":"F14AB","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"53287B7C-9B73-48F6-B558-BBFC529D1D48","name":"relation-only-one-to-zero-or-many","codepoint":"F14AC","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"F93B3000-FF04-4374-94AB-7E703AE780AD","name":"relation-only-one-to-zero-or-one","codepoint":"F14AD","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"3F67D802-700C-4692-9B30-88129AF5C954","name":"relation-zero-or-many-to-many","codepoint":"F14AE","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"8884AF49-A6E9-4442-A648-72C365E8B7B8","name":"relation-zero-or-many-to-one","codepoint":"F14AF","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"DB4A4065-5FCF-4563-A725-7FF82BF05524","name":"relation-zero-or-many-to-one-or-many","codepoint":"F14B0","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"D5FECDF0-F04F-40DA-A4EE-5F1659883460","name":"relation-zero-or-many-to-only-one","codepoint":"F14B1","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"1E86EED5-2458-46D6-8AD0-E14DC65FE7FA","name":"relation-zero-or-many-to-zero-or-many","codepoint":"F14B2","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"26C96921-576B-42F4-B424-2E3F3FF83346","name":"relation-zero-or-many-to-zero-or-one","codepoint":"F14B3","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"C09E5EAE-BC42-480C-842F-EBADFD035886","name":"relation-zero-or-one-to-many","codepoint":"F14B4","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"E262BBDE-079C-4DF6-8C5C-00F9FB3503B5","name":"relation-zero-or-one-to-one","codepoint":"F14B5","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"4A6CE6A7-7F49-42E3-8EC5-DEA80D1A2559","name":"relation-zero-or-one-to-one-or-many","codepoint":"F14B6","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"78BC5AAC-0D19-49F6-AF3F-523739CA933C","name":"relation-zero-or-one-to-only-one","codepoint":"F14B7","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"79676BBB-E83B-4661-AEAB-E3FC622BDD00","name":"relation-zero-or-one-to-zero-or-many","codepoint":"F14B8","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"1B446467-7655-425C-A7C1-ED97D7599D80","name":"relation-zero-or-one-to-zero-or-one","codepoint":"F14B9","aliases":[],"tags":["Database"],"author":"Michael Richins","version":"5.3.45"},{"id":"912AD329-9B77-4959-9407-0F64BABFAC7D","name":"relative-scale","codepoint":"F0452","aliases":["image-aspect-ratio"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8E25B2CE-4DAF-4BD1-9D3F-27F86DA55D21","name":"reload","codepoint":"F0453","aliases":["car-engine-start","loop"],"tags":["Automotive"],"author":"Austin Andrews","version":"1.5.54"},{"id":"01D5FD19-E2FA-4BD0-9F6C-ECA058F469F1","name":"reload-alert","codepoint":"F110B","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"1BD93F0A-87D1-4B55-A0EF-D9F05A8B3826","name":"reminder","codepoint":"F088C","aliases":[],"tags":[],"author":"Google","version":"2.1.99"},{"id":"49C7BBC2-6C7F-442E-A6EE-B58AB758A8D4","name":"remote","codepoint":"F0454","aliases":["settings-remote"],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"A237199B-0B22-475F-93D1-DB45FA4D3205","name":"remote-desktop","codepoint":"F08B9","aliases":[],"tags":[],"author":"Simran","version":"2.2.43"},{"id":"6DC5640C-42D8-45A0-8CEC-B78E045600FE","name":"remote-off","codepoint":"F0EC4","aliases":[],"tags":[],"author":"idevo89","version":"3.7.94"},{"id":"7B245C49-09E7-425A-AFF2-714E9634436E","name":"remote-tv","codepoint":"F0EC5","aliases":[],"tags":["Device \/ Tech"],"author":"GreenTurtwig","version":"3.7.94"},{"id":"D0485B00-63FF-44F5-8DE2-480F970D5ADD","name":"remote-tv-off","codepoint":"F0EC6","aliases":[],"tags":["Device \/ Tech"],"author":"idevo89","version":"3.7.94"},{"id":"1DFADA84-47E4-40EF-B1F8-D0A34D1482BA","name":"rename-box","codepoint":"F0455","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"08CB23B7-EC19-4FE5-9CBB-C308CC89C10B","name":"reorder-horizontal","codepoint":"F0688","aliases":[],"tags":[],"author":"Google","version":"1.7.12"},{"id":"F189DB12-9323-47A1-89C9-451EF2A886CB","name":"reorder-vertical","codepoint":"F0689","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.7.12"},{"id":"9AEE0CB7-46B9-414F-A8A8-AFB127CB7057","name":"repeat","codepoint":"F0456","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"06540FC6-0AF2-40C7-895A-B8C98BD143D1","name":"repeat-off","codepoint":"F0457","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D27E266C-5F69-4E4F-9DE3-65A47B5208F5","name":"repeat-once","codepoint":"F0458","aliases":["repeat-one"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A15D2CB0-E938-4894-8BF3-BC6C628E6433","name":"replay","codepoint":"F0459","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"CC3BEE2C-0FEA-46D2-BC53-F7D248AAF47C","name":"reply","codepoint":"F045A","aliases":[],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"0BDA0697-946D-4B4C-AD02-2FC6ECA4A528","name":"reply-all","codepoint":"F045B","aliases":[],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"C89953B0-3E41-4F03-B0C3-4ED8F96C1234","name":"reply-all-outline","codepoint":"F0F1F","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"25084C11-A1EE-4158-BC41-5E80E00E837E","name":"reply-circle","codepoint":"F11AE","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"7FBB6798-7E14-45FC-973A-8F4FD184F92A","name":"reply-outline","codepoint":"F0F20","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"A522A51F-EE61-473F-97D6-9D5106FD11CA","name":"reproduction","codepoint":"F045C","aliases":[],"tags":["Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"37D62FB9-6BB0-49D6-8C3E-DF75338DD275","name":"resistor","codepoint":"F0B44","aliases":[],"tags":[],"author":"Louistwee","version":"2.8.94"},{"id":"8DB0A5C4-31AD-42A8-A42E-4690B20D5AA0","name":"resistor-nodes","codepoint":"F0B45","aliases":[],"tags":[],"author":"Louistwee","version":"2.8.94"},{"id":"5D2EF9DD-38C1-4D2B-A24B-7270C66A6667","name":"resize","codepoint":"F0A68","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.6.95"},{"id":"84916A68-B413-4D71-B4E7-5FD64914B354","name":"resize-bottom-right","codepoint":"F045D","aliases":["drag"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0C72C131-779D-460F-A059-B9DF2B79E40C","name":"responsive","codepoint":"F045E","aliases":[],"tags":[],"author":"Gabriel","version":"1.5.54"},{"id":"15954B5D-3ADA-4B6B-BE15-F95B6A5D4659","name":"restart","codepoint":"F0709","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"08CBB3AA-B72C-4381-A295-37EC2550AF63","name":"restart-alert","codepoint":"F110C","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"CE31B2C3-939B-4039-9ADC-797509A68F35","name":"restart-off","codepoint":"F0D95","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"FF1CAAB4-2192-442F-88F1-08DEB67E21F0","name":"restore","codepoint":"F099B","aliases":["loop"],"tags":[],"author":"Google","version":"2.4.85"},{"id":"A9EF3AB2-700F-422A-AE07-0F6C3DB5BDB6","name":"restore-alert","codepoint":"F110D","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"28BCDF41-AA93-4C25-B87A-95A3F5DD8805","name":"rewind","codepoint":"F045F","aliases":["fast-rewind"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"3A7C53D9-B7BB-49A7-9393-38F16B0F5D52","name":"rewind-10","codepoint":"F0D2A","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.3.92"},{"id":"21F6D751-0E5A-41F8-980C-2C4385A59CC4","name":"rewind-30","codepoint":"F0D96","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.4.93"},{"id":"167E7244-A6F8-400E-8CF7-F71B3FAEEEBE","name":"rewind-5","codepoint":"F11F9","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"7C7A1566-44FB-4A53-AE61-95F5A03F6978","name":"rewind-60","codepoint":"F160C","aliases":[],"tags":[],"author":"Terren","version":"5.6.55"},{"id":"61E83433-F6D1-442D-9EDE-EDEF27AB789D","name":"rewind-outline","codepoint":"F070A","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"68CFD178-A6FE-4DB5-9C39-FCA6A3EA83A5","name":"rhombus","codepoint":"F070B","aliases":["diamond"],"tags":["Shape"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"F6FA48B9-85C9-4287-8883-6A549AC290D2","name":"rhombus-medium","codepoint":"F0A10","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"01D071A4-DA5C-4735-A72F-53D0B8EC9EDF","name":"rhombus-medium-outline","codepoint":"F14DC","aliases":[],"tags":["Shape"],"author":"Simran","version":"5.3.45"},{"id":"101A7558-A38E-48E8-93EA-A21F37238E78","name":"rhombus-outline","codepoint":"F070C","aliases":["diamond-outline"],"tags":["Shape"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"A19BB3EC-ED3D-41C6-9088-ACB372959E01","name":"rhombus-split","codepoint":"F0A11","aliases":["collection"],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"E9499838-BF7F-48DB-843A-F98796B0D8BB","name":"rhombus-split-outline","codepoint":"F14DD","aliases":[],"tags":["Shape"],"author":"Simran","version":"5.3.45"},{"id":"1C09CB9B-162B-486B-966C-1FCB18C0F633","name":"ribbon","codepoint":"F0460","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B90B4B7C-9FDD-427A-834C-F3DFB5EC1823","name":"rice","codepoint":"F07EA","aliases":[],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"2.0.46"},{"id":"5B4966BE-753B-4777-A8D8-B67B3BC57C0D","name":"rickshaw","codepoint":"F15BB","aliases":[],"tags":["Transportation + Road","Transportation + Other"],"author":"nilsfast","version":"5.6.55"},{"id":"8869DCB9-04E3-41B9-B56C-D4BC5CF2DD7A","name":"rickshaw-electric","codepoint":"F15BC","aliases":[],"tags":["Transportation + Road","Transportation + Other"],"author":"nilsfast","version":"5.6.55"},{"id":"7D845AED-5EA2-44C0-8F38-6A2C4E08C8A3","name":"ring","codepoint":"F07EB","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"2.0.46"},{"id":"DA8B7A3A-5971-4875-AA0A-ED17E8A69E22","name":"rivet","codepoint":"F0E60","aliases":[],"tags":["Hardware \/ Tools"],"author":"Simran","version":"3.6.95"},{"id":"2AA1C93A-17BE-4BB6-A85C-C477A4FF1069","name":"road","codepoint":"F0461","aliases":[],"tags":["Transportation + Road"],"author":"Simran","version":"1.5.54"},{"id":"0BBDD64A-3C67-43DD-9B3A-580E12DDA2D7","name":"road-variant","codepoint":"F0462","aliases":[],"tags":["Transportation + Road"],"author":"Austin Andrews","version":"1.5.54"},{"id":"45B05AE1-4E78-431F-AAB3-669A72AED11E","name":"robber","codepoint":"F1058","aliases":[],"tags":[],"author":"Andrew Nenakhov","version":"4.1.95"},{"id":"EC6C8D3D-0315-4C3A-B37A-97411758DF34","name":"robot","codepoint":"F06A9","aliases":[],"tags":[],"author":"GreenTurtwig","version":"1.7.12"},{"id":"D77B4057-E06B-49B7-BBC7-DD4A7B39BC2A","name":"robot-angry","codepoint":"F169D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"D922E043-E4B6-4FAA-9717-51C1935DD20A","name":"robot-angry-outline","codepoint":"F169E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"535C4A09-5555-45A6-8409-BF12E1CDA2DE","name":"robot-confused","codepoint":"F169F","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"8361794A-9B3E-44CA-9AA4-EA842227D7C2","name":"robot-confused-outline","codepoint":"F16A0","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"04405E02-7C38-409E-8F92-785431ECC76F","name":"robot-dead","codepoint":"F16A1","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"15D146E0-3683-43D8-8500-905EEAC98010","name":"robot-dead-outline","codepoint":"F16A2","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"B32D5968-FE0C-46FB-916E-52D0103DA2C7","name":"robot-excited","codepoint":"F16A3","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"8013E3FE-34B6-49F3-919B-85A5E0A5873C","name":"robot-excited-outline","codepoint":"F16A4","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"6AE4D050-1B64-4AAB-B57B-DD738276E82F","name":"robot-happy","codepoint":"F1719","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"62023A79-6DF7-4B3B-BDCA-FEEAE73C9F89","name":"robot-happy-outline","codepoint":"F171A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"C008FBCE-4D0A-4003-8811-FF15D08C3313","name":"robot-industrial","codepoint":"F0B46","aliases":["autonomous","assembly"],"tags":[],"author":"Michael Richins","version":"2.8.94"},{"id":"2EFA6B95-27BD-4A52-90AF-991A3574FD2C","name":"robot-love","codepoint":"F16A5","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"FA128C47-3C41-4B0D-8F18-8E28E9F3EA0C","name":"robot-love-outline","codepoint":"F16A6","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"2029DE02-EC25-4242-945F-D7495F35D071","name":"robot-mower","codepoint":"F11F7","aliases":["lawn-mower"],"tags":["Home Automation"],"author":"Contributors","version":"4.6.95"},{"id":"D40FCE9F-E14E-4F2E-83BD-39704B38E446","name":"robot-mower-outline","codepoint":"F11F3","aliases":["lawn-mower-outline"],"tags":["Home Automation"],"author":"Contributors","version":"4.5.95"},{"id":"B62D8FF2-AF07-4D20-8C8B-93E585EF6EFB","name":"robot-off","codepoint":"F16A7","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"0BA0757D-0E1F-4484-86AF-7476790AE21C","name":"robot-off-outline","codepoint":"F167B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"C0F3E15B-2DFB-4EAF-B41A-2D18EEA22C25","name":"robot-outline","codepoint":"F167A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"E091C285-7AA8-4907-9398-EBFDAC7A179D","name":"robot-vacuum","codepoint":"F070D","aliases":["roomba"],"tags":["Device \/ Tech","Home Automation"],"author":"Roberto Graham","version":"1.8.36"},{"id":"C7938632-FA58-4686-9B82-5E9CCDD0EC83","name":"robot-vacuum-variant","codepoint":"F0908","aliases":["neato"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"96BE0E43-42AB-4F93-8045-0C7B61BF69CC","name":"rocket","codepoint":"F0463","aliases":[],"tags":["Transportation + Flying","Science"],"author":"Google","version":"1.5.54"},{"id":"E2791217-9CAB-41CA-9899-9BD0964B4DF9","name":"rocket-launch","codepoint":"F14DE","aliases":[],"tags":["Science","Transportation + Flying"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"F6DA21B8-C4AD-48D1-9F97-9A59F721956B","name":"rocket-launch-outline","codepoint":"F14DF","aliases":[],"tags":["Science","Transportation + Flying"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"934FA95E-C5B3-4A5E-B99D-85B0E65CBDBA","name":"rocket-outline","codepoint":"F13AF","aliases":[],"tags":["Science","Transportation + Flying"],"author":"Google","version":"5.0.45"},{"id":"AA8B7EA9-2DB2-4591-94E0-A457373E64C1","name":"rodent","codepoint":"F1327","aliases":["mouse","rat"],"tags":["Animal"],"author":"Google","version":"4.9.95"},{"id":"6EFB213D-87A6-454A-AB37-AB87CE853E4B","name":"roller-skate","codepoint":"F0D2B","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"A6387660-7DB0-41DC-9ECF-EBBA5A78FC82","name":"roller-skate-off","codepoint":"F0145","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"366C920F-6DC6-46FF-94C6-44A8D22A7D1D","name":"rollerblade","codepoint":"F0D2C","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"BC1934AD-28E6-4E7C-8C7E-1557CE482CCB","name":"rollerblade-off","codepoint":"F002E","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"9BBAB3C0-02B2-436A-94C8-0EBD388289D8","name":"rollupjs","codepoint":"F0BC0","aliases":["rollup-js"],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"3.0.39"},{"id":"7E900912-C3AE-4D82-BCF0-1162ACC7EB15","name":"roman-numeral-1","codepoint":"F1088","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.2.95"},{"id":"76685845-20ED-49A8-A8ED-EA967F25B5CF","name":"roman-numeral-10","codepoint":"F1091","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.2.95"},{"id":"4C14E293-1951-4481-9ECC-3D868B764444","name":"roman-numeral-2","codepoint":"F1089","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"6594655A-5BB0-43B5-B3BD-CF04D4B59562","name":"roman-numeral-3","codepoint":"F108A","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"9D572A82-B0D2-4961-B467-32AD78FF551C","name":"roman-numeral-4","codepoint":"F108B","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"EF5F2939-4E4A-4688-B7F5-DD6BC5C14CD1","name":"roman-numeral-5","codepoint":"F108C","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Contributors","version":"4.2.95"},{"id":"8E746FAF-3C9D-48B9-8378-A73EAB7C69F4","name":"roman-numeral-6","codepoint":"F108D","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"D725A70F-2F5D-43B1-99B5-A70220CCAD7A","name":"roman-numeral-7","codepoint":"F108E","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"CD729113-BA16-44AE-A012-D8C5BE2D2D7F","name":"roman-numeral-8","codepoint":"F108F","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"A53BFEB9-4F94-42AA-928D-0A0A28A44FD9","name":"roman-numeral-9","codepoint":"F1090","aliases":[],"tags":["Alpha \/ Numeric"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"C525BD2B-2BA8-4158-AC0A-FAEE9E353047","name":"room-service","codepoint":"F088D","aliases":[],"tags":[],"author":"Google","version":"2.1.99"},{"id":"A94493FF-30FD-4490-8ABC-F6F03F958D17","name":"room-service-outline","codepoint":"F0D97","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"E288FD83-7397-4DF3-BAB8-DF7094955B83","name":"rotate-3d","codepoint":"F0EC7","aliases":[],"tags":[],"author":"Google","version":"3.7.94"},{"id":"D09D0551-14A0-470B-A24C-0AC38F739FFA","name":"rotate-3d-variant","codepoint":"F0464","aliases":["3d-rotation"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"1E960D83-0632-47D2-8CC9-D8A137887BAB","name":"rotate-left","codepoint":"F0465","aliases":["arrow-rotate-left"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"CC6E0E23-9F7B-40F5-B00F-0690A5F7B400","name":"rotate-left-variant","codepoint":"F0466","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"41DBDBBC-7E7A-4E2A-A7E9-A22707957334","name":"rotate-orbit","codepoint":"F0D98","aliases":["gyro","accelerometer"],"tags":[],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"5324E881-FACF-4CAC-9118-FD963EDCDD27","name":"rotate-right","codepoint":"F0467","aliases":["arrow-rotate-right"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"02105B39-715B-4989-93DC-1DDC338A4552","name":"rotate-right-variant","codepoint":"F0468","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"FEBD153A-F07E-4329-A727-D75F13F3133D","name":"rounded-corner","codepoint":"F0607","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"7D8AE8B4-4A72-45DE-9EA7-B4B6502C0FDD","name":"router","codepoint":"F11E2","aliases":[],"tags":[],"author":"Contributors","version":"4.5.95"},{"id":"8CCE5060-8983-4F75-B672-32B7599F1082","name":"router-network","codepoint":"F1087","aliases":[],"tags":[],"author":"Simran","version":"4.2.95"},{"id":"3244EAC8-8349-4CFB-BE35-A0812368CEDA","name":"router-wireless","codepoint":"F0469","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"E6CF3E53-C5EF-48AF-BA3B-AD339E6A3FA3","name":"router-wireless-off","codepoint":"F15A3","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"3881E4FA-15D1-4051-991C-B4B4F0791576","name":"router-wireless-settings","codepoint":"F0A69","aliases":[],"tags":["Settings"],"author":"Google","version":"2.6.95"},{"id":"4E7234E7-AB5F-491D-BA6F-674B3BAD9027","name":"routes","codepoint":"F046A","aliases":["sign-routes"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"70E2EE84-23BF-4C5A-9AE7-06D1156042CA","name":"routes-clock","codepoint":"F1059","aliases":[],"tags":["Date \/ Time"],"author":"Fran\u00e7ois Risoud","version":"4.1.95"},{"id":"72F11BA0-1557-4500-8235-2E3F2346FE69","name":"rowing","codepoint":"F0608","aliases":[],"tags":["Sport","Transportation + Water"],"author":"Google","version":"1.5.54"},{"id":"9E877D76-9BC5-496D-99E4-1E6029DE1B4D","name":"rss","codepoint":"F046B","aliases":["rss-feed"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"649343BD-3C91-43EA-9000-AE10520CAA2D","name":"rss-box","codepoint":"F046C","aliases":["rss-feed-box"],"tags":[],"author":"Gabriel","version":"1.5.54"},{"id":"45AA2B72-8538-41CB-BAD4-20C43E40D21C","name":"rss-off","codepoint":"F0F21","aliases":[],"tags":[],"author":"Michael Richins","version":"3.8.95"},{"id":"C43D28FD-C647-41B4-A710-E8FFE81D8EAF","name":"rug","codepoint":"F1475","aliases":["carpet"],"tags":["Home Automation"],"author":"Michael Richins","version":"5.2.45"},{"id":"19489FCE-DD25-4670-BC6F-4FC3AF1E66D3","name":"rugby","codepoint":"F0D99","aliases":["rugby-ball"],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"66A2EA92-0743-4740-B3F2-254C38E9027F","name":"ruler","codepoint":"F046D","aliases":[],"tags":["Hardware \/ Tools","Drawing \/ Art"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A94D1ED1-576F-4E2C-B165-ABAD797E8192","name":"ruler-square","codepoint":"F0CC2","aliases":["square","carpentry","architecture"],"tags":["Hardware \/ Tools","Drawing \/ Art"],"author":"Michael Richins","version":"3.2.89"},{"id":"2E24CF4F-2EC9-46C2-ABB9-341869D562EE","name":"ruler-square-compass","codepoint":"F0EBE","aliases":["mason","masonic","freemasonry"],"tags":["Hardware \/ Tools"],"author":"Michael Richins","version":"3.7.94"},{"id":"2A869029-60EB-4965-9BE4-9B3DB964C707","name":"run","codepoint":"F070E","aliases":["directions-run"],"tags":["Sport"],"author":"Google","version":"1.8.36"},{"id":"D541EB73-227A-419B-A5F7-7242EB02D916","name":"run-fast","codepoint":"F046E","aliases":[],"tags":["Home Automation","Sport"],"author":"Austin Andrews","version":"1.5.54"},{"id":"43C3E250-2842-4973-8D19-CA1E48BCF61C","name":"rv-truck","codepoint":"F11D4","aliases":["recreational-vehicle","campervan"],"tags":["Transportation + Road"],"author":"Michael Richins","version":"4.5.95"},{"id":"025FEA9C-17F9-4293-BD59-A8D53B7B4124","name":"sack","codepoint":"F0D2E","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"9DA8E933-0065-43E6-9416-0EAA104BEF6F","name":"sack-percent","codepoint":"F0D2F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"013E121E-A100-48D2-941B-854832E70793","name":"safe","codepoint":"F0A6A","aliases":[],"tags":["Banking"],"author":"GreenTurtwig","version":"2.6.95"},{"id":"B12FE612-BEB7-45A2-BB7D-B04C6F33AE1B","name":"safe-square","codepoint":"F127C","aliases":[],"tags":[],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"6F471894-793E-4F7F-848D-CE2AA2F4C67D","name":"safe-square-outline","codepoint":"F127D","aliases":[],"tags":[],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"438888DA-342B-4861-95EA-026A3F4E2F95","name":"safety-goggles","codepoint":"F0D30","aliases":["safety-glasses"],"tags":["Science"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"F1921E38-A25D-41F6-94B6-B6D01C3E0593","name":"sail-boat","codepoint":"F0EC8","aliases":["boat"],"tags":["Sport","Transportation + Water"],"author":"GreenTurtwig","version":"3.7.94"},{"id":"688543EC-EC01-474C-883C-C2EA2EDE75BF","name":"sale","codepoint":"F046F","aliases":["discount"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"D7963D7C-396F-45DB-A5D7-AA18AE32FE53","name":"salesforce","codepoint":"F088E","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.99"},{"id":"2AFE6E3E-61AB-48D2-A333-E5324AD534CD","name":"sass","codepoint":"F07EC","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"2.0.46"},{"id":"D77BED79-19CC-45A9-9940-5EB621E95C11","name":"satellite","codepoint":"F0470","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"9627DDC0-A33C-4B0E-A14F-915809E377AA","name":"satellite-uplink","codepoint":"F0909","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"3945E491-7E92-4A9F-BD2A-C436200B3716","name":"satellite-variant","codepoint":"F0471","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"191AE0C8-5DBD-4B51-8D52-2872CA89E376","name":"sausage","codepoint":"F08BA","aliases":[],"tags":["Food \/ Drink"],"author":"Nick","version":"2.2.43"},{"id":"65F29350-AC15-4F53-B3D0-B7304BA8791A","name":"saw-blade","codepoint":"F0E61","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"2C8473E2-22E8-4E6E-B929-99D2FCE9937B","name":"sawtooth-wave","codepoint":"F147A","aliases":[],"tags":["Audio"],"author":"Haley Halcyon","version":"5.2.45"},{"id":"64F494E1-5B39-488D-B46E-0FC1B9567478","name":"saxophone","codepoint":"F0609","aliases":[],"tags":["Music"],"author":"Google","version":"1.5.54"},{"id":"3FE1D769-A292-44DB-BB8A-E60F3A020D2A","name":"scale","codepoint":"F0472","aliases":[],"tags":["Food \/ Drink","Science"],"author":"Austin Andrews","version":"1.5.54"},{"id":"82048BA4-F949-4572-B59B-23197F9B36D6","name":"scale-balance","codepoint":"F05D1","aliases":[],"tags":["Science"],"author":"Simran","version":"1.5.54"},{"id":"F4501EC3-6AB0-4A69-B840-F07DDFC45A19","name":"scale-bathroom","codepoint":"F0473","aliases":[],"tags":["Home Automation","Medical \/ Hospital"],"author":"Austin Andrews","version":"1.5.54"},{"id":"69824E77-BE70-49EB-9F26-C06042E86F1D","name":"scale-off","codepoint":"F105A","aliases":[],"tags":["Science"],"author":"Michael Richins","version":"4.1.95"},{"id":"C74BA4DC-A838-471E-AA2D-A5C2D0B74BF3","name":"scan-helper","codepoint":"F13D8","aliases":[],"tags":[],"author":"Peter Noble","version":"5.1.45"},{"id":"BE9A1BD3-1DF7-407F-98B7-24070994D472","name":"scanner","codepoint":"F06AB","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"1.7.12"},{"id":"B2E1C852-B55A-40D0-969B-0CD7389660A4","name":"scanner-off","codepoint":"F090A","aliases":[],"tags":["Device \/ Tech"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"5DE8E9D7-420A-43BE-AF94-B1364BC46D41","name":"scatter-plot","codepoint":"F0EC9","aliases":[],"tags":[],"author":"Google","version":"3.7.94"},{"id":"C438C63A-0E60-4EA8-B795-EE6D329253F1","name":"scatter-plot-outline","codepoint":"F0ECA","aliases":[],"tags":[],"author":"Google","version":"3.7.94"},{"id":"A671C11E-0A75-4F41-AA32-EAA99955DEDE","name":"school","codepoint":"F0474","aliases":["graduation-cap","university","college","academic-cap","education","learn"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"282BA7AF-AFFD-491F-BA34-8DFD88378AFF","name":"school-outline","codepoint":"F1180","aliases":["academic-cap-outline","college-outline","graduation-cap-outline","university-outline","education-outline","learn-outline"],"tags":[],"author":"Google","version":"4.4.95"},{"id":"D5D8FF62-F955-4DB5-8EC3-1C314F401ECD","name":"scissors-cutting","codepoint":"F0A6B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"0299DD49-341B-4979-91A9-FB3BF6AEFB87","name":"scooter","codepoint":"F15BD","aliases":[],"tags":["Transportation + Other"],"author":"Google","version":"5.6.55"},{"id":"09653048-04BF-4EDE-A6F5-7DAAE4157D21","name":"scooter-electric","codepoint":"F15BE","aliases":[],"tags":["Transportation + Other"],"author":"Google","version":"5.6.55"},{"id":"C20508AC-CC67-48DF-9B05-72DE40E417AF","name":"scoreboard","codepoint":"F127E","aliases":[],"tags":["Sport"],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"3E4214BB-1283-436F-A658-7F6015745C88","name":"scoreboard-outline","codepoint":"F127F","aliases":[],"tags":["Sport"],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"913EA106-BCB3-410B-A5F4-6FAAA1B79880","name":"screen-rotation","codepoint":"F0475","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"0C15E49D-5D29-4A3D-803B-0B9695295E04","name":"screen-rotation-lock","codepoint":"F0478","aliases":["screen-lock-rotation"],"tags":["Lock"],"author":"Google","version":"1.5.54"},{"id":"744539B5-EC00-481D-9A78-274A157CF130","name":"screw-flat-top","codepoint":"F0DF3","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"34D5E55D-131E-4EB2-9053-53B10F6F40D5","name":"screw-lag","codepoint":"F0DF4","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"AD403C97-C12B-4590-A156-EEF43629F655","name":"screw-machine-flat-top","codepoint":"F0DF5","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"C19DAE9D-F5EE-4968-99AD-7F1C55B6ACB4","name":"screw-machine-round-top","codepoint":"F0DF6","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"AC9042F5-C2D0-4C97-AA6E-C364026950B0","name":"screw-round-top","codepoint":"F0DF7","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"2F75C2DC-FAAD-4D59-BAAB-3922EF9AF376","name":"screwdriver","codepoint":"F0476","aliases":[],"tags":["Hardware \/ Tools"],"author":"Simran","version":"1.5.54"},{"id":"89D63ACC-0EB2-4C0C-BAFF-65846D32B937","name":"script","codepoint":"F0BC1","aliases":["scroll"],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"6E18A0EA-1F19-47E3-83DD-25732C1D318D","name":"script-outline","codepoint":"F0477","aliases":["scroll-outline"],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"100A6987-09AC-4A60-B6D6-E9DA1E4FCBCE","name":"script-text","codepoint":"F0BC2","aliases":["scroll-text"],"tags":["Gaming \/ RPG"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"2789A595-8195-448F-BD8A-2FB71B712BD8","name":"script-text-key","codepoint":"F1725","aliases":[],"tags":[],"author":"Contributors","version":"5.9.55"},{"id":"1343F1A4-86DB-432D-BE9D-F3EFEB1321F8","name":"script-text-key-outline","codepoint":"F1726","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"DF9F9175-8E37-4241-8AFD-360606A444A5","name":"script-text-outline","codepoint":"F0BC3","aliases":["scroll-text-outline"],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"3.0.39"},{"id":"0F931BB6-3336-430E-85C2-9EDEDCC4E9B4","name":"script-text-play","codepoint":"F1727","aliases":[],"tags":[],"author":"Contributors","version":"5.9.55"},{"id":"7357F674-281E-49F1-8161-424877AC6DD3","name":"script-text-play-outline","codepoint":"F1728","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"68B68EDB-6CDA-4488-A213-5E6DF4146EA6","name":"sd","codepoint":"F0479","aliases":["sd-card","sd-storage"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"82C413A0-A055-4527-87B7-F977B6CD3F74","name":"seal","codepoint":"F047A","aliases":["ribbon","prize","award"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"9B878309-6513-4C41-B2F5-B69D24F6024B","name":"seal-variant","codepoint":"F0FD9","aliases":["ribbon","prize","award"],"tags":[],"author":"Contributors","version":"4.0.96"},{"id":"F6E7F332-1625-4A46-8E10-B6DEC4059E7E","name":"search-web","codepoint":"F070F","aliases":[],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"C9A796D6-1A7D-47AD-A036-B3B9035FBDA3","name":"seat","codepoint":"F0CC3","aliases":["event-seat","chair","chair-accent"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"FDDF112E-DFF5-4D31-9821-69902F92E6CF","name":"seat-flat","codepoint":"F047B","aliases":["airline-seat-flat"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"22BC78FF-895C-497C-B6F0-143F60901C20","name":"seat-flat-angled","codepoint":"F047C","aliases":["airline-seat-flat-angled"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A8F9F185-D2AE-4DEE-845C-3C74801E2CD0","name":"seat-individual-suite","codepoint":"F047D","aliases":["airline-seat-individual-suite"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"F73EE06A-6898-40A7-9B0E-784A4280C075","name":"seat-legroom-extra","codepoint":"F047E","aliases":["airline-seat-legroom-extra"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"1FC39B1E-567E-452C-B923-581F9A90F06D","name":"seat-legroom-normal","codepoint":"F047F","aliases":["airline-seat-legroom-normal"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4306743D-7833-44E7-88AB-659DD694C8B0","name":"seat-legroom-reduced","codepoint":"F0480","aliases":["airline-seat-legroom-reduced"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"2F61EAD1-DF0E-4E90-8260-875EA5221F35","name":"seat-outline","codepoint":"F0CC4","aliases":["event-seat-outline","chair-outline","chair-accent-outline"],"tags":[],"author":"Google","version":"3.2.89"},{"id":"BF015C93-A5AD-47BF-9451-A9B5DFFAD50C","name":"seat-passenger","codepoint":"F1249","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"EB83D5D9-0439-476C-9BFD-04B5D6789940","name":"seat-recline-extra","codepoint":"F0481","aliases":["airline-seat-recline-extra"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B6642D7A-EE36-4C22-945E-88A218708CB6","name":"seat-recline-normal","codepoint":"F0482","aliases":["airline-seat-recline-normal"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"00F06E5E-5A05-4D5E-9D07-0573CA62E0BA","name":"seatbelt","codepoint":"F0CC5","aliases":["seat-belt","safety-belt"],"tags":["Automotive"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"0C2F3617-9710-4265-AFB5-29C52AD2FBE0","name":"security","codepoint":"F0483","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"C9FA8517-7CD1-4AB7-86AD-0A2BF1016466","name":"security-network","codepoint":"F0484","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"75A03574-02AA-4377-8DE3-86CBE77A0957","name":"seed","codepoint":"F0E62","aliases":[],"tags":["Agriculture","Nature","Food \/ Drink"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"22CC568F-81CD-4DEA-A4E1-7DE207BD15F3","name":"seed-off","codepoint":"F13FD","aliases":[],"tags":["Nature","Food \/ Drink","Agriculture"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"372ACCAF-E322-40AC-8CE9-1F2066D3BF97","name":"seed-off-outline","codepoint":"F13FE","aliases":[],"tags":["Nature","Food \/ Drink","Agriculture"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"80AE8DF8-0E9B-4A56-B2EF-2CA1244D99D3","name":"seed-outline","codepoint":"F0E63","aliases":[],"tags":["Agriculture","Nature","Food \/ Drink"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"B2FB9E28-A275-4BC8-AFD9-8A8D90153ED9","name":"seesaw","codepoint":"F15A4","aliases":["playground-seesaw"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"5AFE282B-CAE1-4D7F-A2BF-37E8655537DD","name":"segment","codepoint":"F0ECB","aliases":[],"tags":[],"author":"Google","version":"3.7.94"},{"id":"B350D031-599B-4BB7-9D21-EC955B7FEF43","name":"select","codepoint":"F0485","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"7C2879B0-6BFE-42A3-9EDF-4A42AC3C9D70","name":"select-all","codepoint":"F0486","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8B757895-25B7-4C24-B6A2-7C71C9C12138","name":"select-color","codepoint":"F0D31","aliases":["select-colour"],"tags":["Color"],"author":"Google","version":"3.3.92"},{"id":"4BC4C702-7484-4B80-95EB-F98125F1332D","name":"select-compare","codepoint":"F0AD9","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"BA35374B-03BB-421D-ABCD-5F8C4B492C4C","name":"select-drag","codepoint":"F0A6C","aliases":[],"tags":[],"author":"Contributors","version":"2.6.95"},{"id":"FEDE670C-F1CD-493D-B201-0C0410DB04C8","name":"select-group","codepoint":"F0F82","aliases":[],"tags":[],"author":"Google","version":"3.9.97"},{"id":"DAA46B9D-9215-4BF8-BDA7-52E575817ABC","name":"select-inverse","codepoint":"F0487","aliases":["selection-invert"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"A312AB96-5A12-4223-AF67-7067653E17E5","name":"select-marker","codepoint":"F1280","aliases":[],"tags":[],"author":"Contributors","version":"4.7.95"},{"id":"1958E6ED-3D6C-4341-8F21-DDE80D030CEF","name":"select-multiple","codepoint":"F1281","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"0A8AB6EF-B388-4086-BF8D-1F0015ADC972","name":"select-multiple-marker","codepoint":"F1282","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"B2C462E1-44F0-456A-8A73-919DB480D978","name":"select-off","codepoint":"F0488","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0090BCFA-124B-484B-BFA1-AA39413F0156","name":"select-place","codepoint":"F0FDA","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"5D558A02-EC98-47D7-AD04-D02E225AF4C6","name":"select-search","codepoint":"F1204","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"33A5D3FF-E2A7-4E3A-95B5-86D4C6604911","name":"selection","codepoint":"F0489","aliases":[],"tags":[],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"62E94CCE-BCD0-4DF3-9AFB-B14169345612","name":"selection-drag","codepoint":"F0A6D","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.6.95"},{"id":"F1A52E3C-0E56-48FA-ADC4-A20A6CE2E4DF","name":"selection-ellipse","codepoint":"F0D32","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.3.92"},{"id":"DD7E2731-0D5F-42EC-8F73-99DC2E80398C","name":"selection-ellipse-arrow-inside","codepoint":"F0F22","aliases":[],"tags":[],"author":"Google","version":"3.8.95"},{"id":"DA670815-123E-4443-B813-5BB4A556AB1C","name":"selection-marker","codepoint":"F1283","aliases":[],"tags":[],"author":"Contributors","version":"4.7.95"},{"id":"31DDE08D-A49D-4B2D-9D90-3E79FDDF49C9","name":"selection-multiple","codepoint":"F1285","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"5B06BC81-DA70-41F2-B05C-31E9BD7F571E","name":"selection-multiple-marker","codepoint":"F1284","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"DE8BF55F-05A8-4CB8-86FC-63D6EAC57A6C","name":"selection-off","codepoint":"F0777","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"2123E467-F48C-4AC6-8061-FEEB686ADB19","name":"selection-search","codepoint":"F1205","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"43AB1D06-4033-4F02-8147-B692F4534174","name":"semantic-web","codepoint":"F1316","aliases":["rdf","resource-description-framework","owl","web-ontology-language","w3c"],"tags":["Developer \/ Languages","Brand \/ Logo"],"author":"Contributors","version":"4.8.95"},{"id":"6791A1E4-DBF8-471C-AA27-0D4540A23678","name":"send","codepoint":"F048A","aliases":["paper-airplane","paper-plane"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"688C66E3-B436-4900-83EF-ADCEBBEDE627","name":"send-check","codepoint":"F1161","aliases":[],"tags":[],"author":"Simran","version":"4.4.95"},{"id":"0C6541E7-CC47-4FF5-BEB4-F261296D7DAD","name":"send-check-outline","codepoint":"F1162","aliases":[],"tags":[],"author":"Simran","version":"4.4.95"},{"id":"52E3C504-34AB-4EE5-954F-768B1044B2A6","name":"send-circle","codepoint":"F0DF8","aliases":[],"tags":[],"author":"Contributors","version":"3.5.94"},{"id":"DE0BE96B-9A65-4B97-B3F3-67FBDF240B7A","name":"send-circle-outline","codepoint":"F0DF9","aliases":[],"tags":[],"author":"Contributors","version":"3.5.94"},{"id":"1225563F-5E41-4B85-8E01-FF53C5453B56","name":"send-clock","codepoint":"F1163","aliases":[],"tags":["Date \/ Time"],"author":"Google","version":"4.4.95"},{"id":"281F054F-8F0A-4790-9165-154E297B9283","name":"send-clock-outline","codepoint":"F1164","aliases":[],"tags":["Date \/ Time"],"author":"Google","version":"4.4.95"},{"id":"343A4B08-D77B-453B-A8A7-AF40D1A98DD2","name":"send-lock","codepoint":"F07ED","aliases":["send-secure"],"tags":["Lock"],"author":"Michael Richins","version":"2.0.46"},{"id":"23F855E5-3F55-48BA-8C2A-7FBA5EAE8CED","name":"send-lock-outline","codepoint":"F1166","aliases":[],"tags":["Lock"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"B4F0331A-3E21-40C4-AED4-A28FD929AD21","name":"send-outline","codepoint":"F1165","aliases":["paper-airplane-outline","paper-plane-outline"],"tags":[],"author":"Simran","version":"4.4.95"},{"id":"5D18BB49-3214-49C0-BD5C-B4581172C650","name":"serial-port","codepoint":"F065C","aliases":["vga"],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"692F85E2-79A8-4207-ACF7-DEC8D675BE38","name":"server","codepoint":"F048B","aliases":["storage"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"09F53FF1-31D7-44CA-A00E-8CDDF55DB716","name":"server-minus","codepoint":"F048C","aliases":["server-remove"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"21F268BE-CC44-49CE-B59A-121D073ADBA5","name":"server-network","codepoint":"F048D","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E01B3638-DE80-4D1E-93D1-1A0C5E9AFCF4","name":"server-network-off","codepoint":"F048E","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"578A1213-5F0D-4C6B-A929-9157D126A9F8","name":"server-off","codepoint":"F048F","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"99AC1D59-A2F0-4B53-872D-0374D0804E0A","name":"server-plus","codepoint":"F0490","aliases":["server-add"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"C7C1A659-403B-44E0-9EF5-94B5C722CAFD","name":"server-remove","codepoint":"F0491","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E42A523C-D28D-4AAB-8A86-4816DD872B78","name":"server-security","codepoint":"F0492","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"501D1421-A50E-470A-A05B-87864461C4ED","name":"set-all","codepoint":"F0778","aliases":["set-union","set-or","full-outer-join","sql-full-outer-join"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"0267D77C-9968-45EF-87FC-CD3368D56383","name":"set-center","codepoint":"F0779","aliases":["set-centre","set-intersection","set-and","inner-join","sql-inner-join"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"614D2F8D-5170-4FE8-87C7-419903F205CB","name":"set-center-right","codepoint":"F077A","aliases":["set-centre-right","outer-join-right","sql-right-outer-join"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"FB4645C1-DF04-49E0-BA0B-7C02C87AF3A9","name":"set-left","codepoint":"F077B","aliases":["difference-left"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"9C04991C-6A68-4634-885F-A4D6E2816AFF","name":"set-left-center","codepoint":"F077C","aliases":["set-left-centre","outer-join-left","sql-left-outer-join"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"E1BE2EC4-D5D5-475C-A562-9855DA1612FB","name":"set-left-right","codepoint":"F077D","aliases":["exclusion","set-xor"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"414C136F-7BB5-47BB-BB58-136C5E1C2E5B","name":"set-merge","codepoint":"F14E0","aliases":[],"tags":[],"author":"Contributors","version":"5.3.45"},{"id":"9674B809-B544-45E8-BBD8-4E8D9E1A966E","name":"set-none","codepoint":"F077E","aliases":["set-null","set-not"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"27D4B799-E231-49DF-AB06-0201493C83E9","name":"set-right","codepoint":"F077F","aliases":["difference-right"],"tags":["Database"],"author":"Simran","version":"1.9.32"},{"id":"7100DDA3-3A7A-4A02-A717-D33D1A170E41","name":"set-split","codepoint":"F14E1","aliases":[],"tags":[],"author":"Contributors","version":"5.3.45"},{"id":"C57170BC-B363-470F-B209-D713700B7C89","name":"set-square","codepoint":"F145D","aliases":[],"tags":["Hardware \/ Tools"],"author":"Google","version":"5.2.45"},{"id":"944304C3-3513-4544-8DC2-B14307049311","name":"set-top-box","codepoint":"F099F","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"2.4.85"},{"id":"6AE3B6F5-8896-4AED-A4B2-B1B021DE1DE9","name":"settings-helper","codepoint":"F0A6E","aliases":[],"tags":["Settings"],"author":"Peter Noble","version":"2.6.95"},{"id":"4E49931C-2FF9-4957-942A-F2F0B8485E68","name":"shaker","codepoint":"F110E","aliases":["pepper","fish-food"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"1A2E13B0-421D-460F-87C2-63C1DEC6525A","name":"shaker-outline","codepoint":"F110F","aliases":["salt","fish-food-outline"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"B29246C8-6014-4019-8CCC-F803DBC0FA95","name":"shape","codepoint":"F0831","aliases":["category","theme"],"tags":["Shape"],"author":"Google","version":"2.1.19"},{"id":"C989421F-7F77-45D9-9BB4-97D3DE8C8FB4","name":"shape-circle-plus","codepoint":"F065D","aliases":["shape-circle-add"],"tags":["Shape"],"author":"Kai Faust","version":"1.6.50"},{"id":"FC3A1E7D-F8CD-443E-A685-9C7F0FA9FC10","name":"shape-outline","codepoint":"F0832","aliases":["theme-outline","category-outline"],"tags":["Shape"],"author":"Google","version":"2.1.19"},{"id":"CE4CFCD5-20D8-4248-A3E8-0B1EFDCC8EC4","name":"shape-oval-plus","codepoint":"F11FA","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.6.95"},{"id":"C91D9DCD-5ADA-4D48-857C-39D38CD37A6B","name":"shape-plus","codepoint":"F0495","aliases":["shape-add"],"tags":["Shape"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CFE631FF-AAD1-49D9-BA22-84BAC90B8787","name":"shape-polygon-plus","codepoint":"F065E","aliases":["shape-polygon-add"],"tags":["Shape"],"author":"Kai Faust","version":"1.6.50"},{"id":"C92D4248-E908-4B39-A6D0-296E6FB5FFE1","name":"shape-rectangle-plus","codepoint":"F065F","aliases":["shape-rectangle-add"],"tags":["Shape"],"author":"Kai Faust","version":"1.6.50"},{"id":"56A31026-C5C6-45D5-A9D4-1C660357F430","name":"shape-square-plus","codepoint":"F0660","aliases":["shape-square-add"],"tags":["Shape"],"author":"Kai Faust","version":"1.6.50"},{"id":"783621A3-B8D0-4340-BE29-0399B02EAE6B","name":"shape-square-rounded-plus","codepoint":"F14FA","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.4.55"},{"id":"F0053E35-64B2-45D5-92D6-EE9F8A8839A1","name":"share","codepoint":"F0496","aliases":["forward"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"3A9176D6-A724-4E82-9F8B-00CEEC8A9D64","name":"share-all","codepoint":"F11F4","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"E9397228-BC9E-4B65-9301-948CBB1D0905","name":"share-all-outline","codepoint":"F11F5","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"2381C112-2883-4B31-829E-D656430AB707","name":"share-circle","codepoint":"F11AD","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"8F694E89-2460-4790-820F-BCFA1A4CB660","name":"share-off","codepoint":"F0F23","aliases":["forward-off"],"tags":["Arrow"],"author":"GreenTurtwig","version":"3.8.95"},{"id":"E65D2036-B0D1-4957-B114-A6FA6DFC67A5","name":"share-off-outline","codepoint":"F0F24","aliases":["forward-off-outline"],"tags":["Arrow"],"author":"GreenTurtwig","version":"3.8.95"},{"id":"B8DDA534-033E-42FF-9F81-62EC636DD3C6","name":"share-outline","codepoint":"F0932","aliases":["forward-outline"],"tags":["Arrow"],"author":"Nick","version":"2.3.54"},{"id":"C25D5913-39C7-4215-B372-88F90EE2B6E5","name":"share-variant","codepoint":"F0497","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"82009437-57EA-4B83-97A2-A6AA6F305CBE","name":"share-variant-outline","codepoint":"F1514","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"7A618386-2E3E-4B23-BF63-184B76C9CF61","name":"shark-fin","codepoint":"F1673","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"15736C41-B312-436C-B081-67F0C561A97A","name":"shark-fin-outline","codepoint":"F1674","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"DEA01DF4-6FBD-45B7-AC58-CBF70545FBBA","name":"sheep","codepoint":"F0CC6","aliases":[],"tags":["Animal","Agriculture"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"A3709A80-3219-4E83-9D4F-EF74F31EEAAE","name":"shield","codepoint":"F0498","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CA71D276-C056-45E5-883E-B3D15868D859","name":"shield-account","codepoint":"F088F","aliases":["security-account","shield-user","shield-person"],"tags":["Account \/ User"],"author":"Michael Richins","version":"2.1.99"},{"id":"E74ADD51-598F-4194-868C-3A9F7B62BCFA","name":"shield-account-outline","codepoint":"F0A12","aliases":["security-account-outline","shield-user-outline","shield-person-outline"],"tags":["Account \/ User"],"author":"GreenTurtwig","version":"2.5.94"},{"id":"54FF705E-9453-4D1A-B2AC-1EB2F815F518","name":"shield-account-variant","codepoint":"F15A7","aliases":[],"tags":["Account \/ User"],"author":"Google","version":"5.5.55"},{"id":"8229B887-45A8-496A-9A8D-0140F438CB65","name":"shield-account-variant-outline","codepoint":"F15A8","aliases":[],"tags":["Account \/ User"],"author":"Google","version":"5.5.55"},{"id":"B8FB8784-2E21-4D35-9DE8-95E8E2A42591","name":"shield-airplane","codepoint":"F06BB","aliases":["shield-aeroplane","shield-plane","plane-shield"],"tags":["Transportation + Flying"],"author":"GreenTurtwig","version":"1.7.22"},{"id":"C14BAFFB-948A-45C3-ABFD-4F6215318D65","name":"shield-airplane-outline","codepoint":"F0CC7","aliases":["shield-aeroplane-outline","shield-plane-outline"],"tags":["Transportation + Flying"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"B5DC36AC-6F79-4CDE-B1CD-02F221BF8CE4","name":"shield-alert","codepoint":"F0ECC","aliases":["shield-warning"],"tags":["Alert \/ Error"],"author":"Peter Noble","version":"3.7.94"},{"id":"51584101-DF6C-49FF-8ACB-13F7064DEE89","name":"shield-alert-outline","codepoint":"F0ECD","aliases":["shield-warning-outline"],"tags":["Alert \/ Error"],"author":"Peter Noble","version":"3.7.94"},{"id":"1FB00AC4-94AE-4677-8F7F-0B6A47F7382C","name":"shield-bug","codepoint":"F13DA","aliases":["antivirus"],"tags":[],"author":"Michael Richins","version":"5.1.45"},{"id":"DCD9B7FB-8730-4C65-8805-50B6B51A5EF7","name":"shield-bug-outline","codepoint":"F13DB","aliases":["antivirus-outline"],"tags":[],"author":"Contributors","version":"5.1.45"},{"id":"2A7B43E0-4BA1-41EB-9040-F943AA9FD02C","name":"shield-car","codepoint":"F0F83","aliases":["car-security","car-insurance"],"tags":["Automotive"],"author":"Nick","version":"3.9.97"},{"id":"FC112FD8-5338-49C0-B4E0-FE1816A71E74","name":"shield-check","codepoint":"F0565","aliases":["verified-user","shield-tick","verified"],"tags":["Account \/ User"],"author":"Google","version":"1.5.54"},{"id":"26E9DF2C-21C8-48FF-B402-733E33673C7E","name":"shield-check-outline","codepoint":"F0CC8","aliases":["shield-tick-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"8D47ED6A-831A-49F2-8E43-67F16F8351E6","name":"shield-cross","codepoint":"F0CC9","aliases":["shield-templar","shield-christianity"],"tags":["Gaming \/ RPG","Religion"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"6C722CF2-67CA-4CEC-9197-56C4F99D2866","name":"shield-cross-outline","codepoint":"F0CCA","aliases":["shield-templar-outline","shield-christianity-outline"],"tags":["Gaming \/ RPG","Religion"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"8CF352CF-2ED0-4DFB-ADCF-AD77FDA6DD25","name":"shield-edit","codepoint":"F11A0","aliases":[],"tags":["Edit \/ Modify"],"author":"Fran\u00e7ois Risoud","version":"4.5.95"},{"id":"F55E4962-5730-4735-B362-42FFB640F202","name":"shield-edit-outline","codepoint":"F11A1","aliases":[],"tags":["Edit \/ Modify"],"author":"Fran\u00e7ois Risoud","version":"4.5.95"},{"id":"DC82606F-2ABB-4C09-BAC5-1C3C4DA38BEC","name":"shield-half","codepoint":"F1360","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"9E908727-9325-4FC6-B8B8-C5CA52A7A827","name":"shield-half-full","codepoint":"F0780","aliases":[],"tags":[],"author":"GreenTurtwig","version":"1.9.32"},{"id":"2A5A98F5-ED95-40DE-8EC5-1293795CF661","name":"shield-home","codepoint":"F068A","aliases":["security-home","shield-house"],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.7.12"},{"id":"4D4B922B-D9AA-47AC-8E02-33F88EC69B38","name":"shield-home-outline","codepoint":"F0CCB","aliases":["shield-house-outline"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"9894EABF-10A1-4A07-BB4B-D94F596F5D6A","name":"shield-key","codepoint":"F0BC4","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"90122FEA-99CC-4B64-BD21-E3DD8CB83948","name":"shield-key-outline","codepoint":"F0BC5","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"9F5D8008-32E1-4A90-B040-2C8AF2C00F81","name":"shield-link-variant","codepoint":"F0D33","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"8A6D2649-CF2C-43AF-A90B-79B554B1385A","name":"shield-link-variant-outline","codepoint":"F0D34","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"C2E5EBC9-F1AD-4D93-BA3F-C81E18411E09","name":"shield-lock","codepoint":"F099D","aliases":["security-lock"],"tags":["Lock"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"7F797AEE-648F-4FB8-BA7F-4EF60235A061","name":"shield-lock-outline","codepoint":"F0CCC","aliases":[],"tags":["Lock"],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"BC537F52-4A49-433B-A031-5C698A234A35","name":"shield-off","codepoint":"F099E","aliases":["security-off"],"tags":[],"author":"Michael Richins","version":"2.4.85"},{"id":"8ED2BB68-83C4-49BE-A730-1853C228781B","name":"shield-off-outline","codepoint":"F099C","aliases":[],"tags":[],"author":"Michael Richins","version":"2.4.85"},{"id":"A8FF94DD-6BA5-4DBA-AE23-59BB22DD733B","name":"shield-outline","codepoint":"F0499","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"872F02FE-ABEF-4187-B6B2-87A548988EAA","name":"shield-plus","codepoint":"F0ADA","aliases":["shield-add"],"tags":[],"author":"Google","version":"2.7.94"},{"id":"4348C9BA-B7EE-4DC9-9B75-102726C978F7","name":"shield-plus-outline","codepoint":"F0ADB","aliases":["shield-add-outline"],"tags":[],"author":"Google","version":"2.7.94"},{"id":"2E0E0624-1F5D-4998-B0F9-A957EC2ADD49","name":"shield-refresh","codepoint":"F00AA","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"D3FD64E5-2836-4527-8861-29D53D101672","name":"shield-refresh-outline","codepoint":"F01E0","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"F6E9D9DF-7266-4D03-BE3E-4F3B4612B77F","name":"shield-remove","codepoint":"F0ADC","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.7.94"},{"id":"4C54DF65-6F23-4FEE-A579-C329A32192BA","name":"shield-remove-outline","codepoint":"F0ADD","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.7.94"},{"id":"89E736DC-2E57-413E-A044-40871A51CB72","name":"shield-search","codepoint":"F0D9A","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"9C6B0512-02BF-4C33-ADAF-54D75B3AD2FB","name":"shield-star","codepoint":"F113B","aliases":["badge"],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"122D14B5-1EB6-4ED3-8765-7C8A58D6071B","name":"shield-star-outline","codepoint":"F113C","aliases":["badge-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"144E5B1F-A406-440D-B8B0-CC662F359D12","name":"shield-sun","codepoint":"F105D","aliases":["sun-protection"],"tags":[],"author":"Perth Totty","version":"4.1.95"},{"id":"36B9C70C-5576-459A-AF44-A8E8F97B5DA8","name":"shield-sun-outline","codepoint":"F105E","aliases":["sun-protection-outline"],"tags":[],"author":"Perth Totty","version":"4.1.95"},{"id":"AE87ED6F-DF56-449E-A3EF-D010AB6F4D17","name":"shield-sync","codepoint":"F11A2","aliases":[],"tags":[],"author":"Fran\u00e7ois Risoud","version":"4.5.95"},{"id":"55F6BCDE-A55A-4206-B079-1684F6E1FF0F","name":"shield-sync-outline","codepoint":"F11A3","aliases":[],"tags":[],"author":"Fran\u00e7ois Risoud","version":"4.5.95"},{"id":"1F35A20C-CF6C-4C2A-9A72-82269F4ECCF7","name":"ship-wheel","codepoint":"F0833","aliases":["voyager","helm"],"tags":["Transportation + Water"],"author":"Google","version":"2.1.19"},{"id":"B5B68323-60DD-45BF-83FC-892B436D0400","name":"shoe-ballet","codepoint":"F15CA","aliases":["slippers-ballet"],"tags":["Sport","Clothing"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"F6831C58-3C18-44F4-A2A8-4AD96444F012","name":"shoe-cleat","codepoint":"F15C7","aliases":[],"tags":["Sport","Clothing"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"DFEA1FD2-F6A5-4670-83D6-9861A0FA272C","name":"shoe-formal","codepoint":"F0B47","aliases":[],"tags":["Clothing"],"author":"SarinManS","version":"2.8.94"},{"id":"E97AD67E-DD75-4FD8-9E25-44F3042B4172","name":"shoe-heel","codepoint":"F0B48","aliases":[],"tags":["Clothing"],"author":"SarinManS","version":"2.8.94"},{"id":"4008AB1C-4D92-4D8B-9423-5182FC505664","name":"shoe-print","codepoint":"F0DFA","aliases":["footprints"],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"EA78AFA5-70F2-4878-A1D5-746B410E1DA0","name":"shoe-sneaker","codepoint":"F15C8","aliases":["shoe-running"],"tags":["Sport","Clothing"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"7A5ED547-B142-4921-8050-647B2B9F4DC0","name":"shopping","codepoint":"F049A","aliases":["local-mall","marketplace"],"tags":["Shopping"],"author":"Google","version":"1.5.54"},{"id":"E3FDDEB1-6D36-4E18-914E-06E2887E7D96","name":"shopping-music","codepoint":"F049B","aliases":[],"tags":["Shopping"],"author":"Austin Andrews","version":"1.5.54"},{"id":"EBE771F9-2EF2-41D9-AE7D-8FDBA1B4C684","name":"shopping-outline","codepoint":"F11D5","aliases":["local-mall-outline","marketplace-outline"],"tags":["Shopping"],"author":"Google","version":"4.5.95"},{"id":"6FB38390-3C7C-423A-AC1C-691C3358E04B","name":"shopping-search","codepoint":"F0F84","aliases":[],"tags":["Shopping"],"author":"Michael Richins","version":"3.9.97"},{"id":"9F0501F0-7F2C-4806-8AC4-F8D76AA194CD","name":"shore","codepoint":"F14F9","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.4.55"},{"id":"16D35D19-90C2-42DD-9E83-8F47E21A53DF","name":"shovel","codepoint":"F0710","aliases":["gardening"],"tags":["Hardware \/ Tools"],"author":"Michael Richins","version":"1.8.36"},{"id":"01E7F800-E769-4A3F-9A30-D1B8E96F617B","name":"shovel-off","codepoint":"F0711","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Richins","version":"1.8.36"},{"id":"1F29D513-0EFE-454A-B766-579A010C51B6","name":"shower","codepoint":"F09A0","aliases":[],"tags":["Home Automation"],"author":"Augustin Ursu","version":"2.4.85"},{"id":"F0E6B2EB-7E10-42C8-AEF1-84A461E1E2B3","name":"shower-head","codepoint":"F09A1","aliases":[],"tags":["Home Automation"],"author":"Augustin Ursu","version":"2.4.85"},{"id":"BCE4CF23-0A2B-430F-89C9-7597F1132919","name":"shredder","codepoint":"F049C","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"99537665-2115-40D6-9725-0F4B4730C99A","name":"shuffle","codepoint":"F049D","aliases":[],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"DAA3B240-E394-46A8-83FE-6EE6712BF806","name":"shuffle-disabled","codepoint":"F049E","aliases":[],"tags":["Arrow"],"author":"Simran","version":"1.5.54"},{"id":"84D958BE-5145-4490-BA8F-D00E6870CC9D","name":"shuffle-variant","codepoint":"F049F","aliases":[],"tags":["Arrow"],"author":"Simran","version":"1.5.54"},{"id":"70BBF348-E5D1-4C4C-AD93-17246A78DE13","name":"shuriken","codepoint":"F137F","aliases":[],"tags":[],"author":"Michael Richins","version":"4.9.95"},{"id":"59A98F47-9067-492A-8454-42BEFA2391C1","name":"sigma","codepoint":"F04A0","aliases":["summation"],"tags":["Math"],"author":"Google","version":"1.5.54"},{"id":"DD1EAF89-C6AC-4E61-BF78-93425B16DD24","name":"sigma-lower","codepoint":"F062B","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"159F7B23-A336-4F8C-A3BB-D8AB143D6661","name":"sign-caution","codepoint":"F04A1","aliases":["barrier"],"tags":["Transportation + Road"],"author":"Austin Andrews","version":"1.5.54"},{"id":"93E3355E-36F9-4B26-A337-C5F794D98941","name":"sign-direction","codepoint":"F0781","aliases":["milestone"],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"110700C4-EF32-4835-B9C6-ECE259438B80","name":"sign-direction-minus","codepoint":"F1000","aliases":["milestone-minus"],"tags":[],"author":"Michael Richins","version":"4.0.96"},{"id":"298F86D9-24E7-4780-A891-1A7C36D65D77","name":"sign-direction-plus","codepoint":"F0FDC","aliases":["milestone-plus","sign-direction-add","milestone-add"],"tags":[],"author":"Michael Richins","version":"4.0.96"},{"id":"93DA424E-0D38-4DD4-B06A-2E3D0754EEC0","name":"sign-direction-remove","codepoint":"F0FDD","aliases":["milestone-remove"],"tags":[],"author":"Michael Richins","version":"4.0.96"},{"id":"AE565EF0-BC09-44FB-B94A-A5F2CF2B2CB2","name":"sign-pole","codepoint":"F14F8","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.4.55"},{"id":"A24BD314-F1AF-4BAF-A33B-F9BAD9D54089","name":"sign-real-estate","codepoint":"F1118","aliases":[],"tags":[],"author":"Michael Richins","version":"4.3.95"},{"id":"6AC6C6C2-8925-4ECC-BD95-6B961B2CD0A5","name":"sign-text","codepoint":"F0782","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"7099FDF8-B653-4C49-BE2B-5B96147A709D","name":"signal","codepoint":"F04A2","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Simran","version":"1.5.54"},{"id":"C281EBBF-23FD-4F0A-8908-BFBA18F75FDD","name":"signal-2g","codepoint":"F0712","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"1.8.36"},{"id":"F0ACC092-8F79-43C9-9F8F-72E41AE557F2","name":"signal-3g","codepoint":"F0713","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"1.8.36"},{"id":"7D633D1D-C265-4D2F-860E-43263B34A06F","name":"signal-4g","codepoint":"F0714","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"1.8.36"},{"id":"5E2711B0-C417-434F-BE9A-F4FA6A666A56","name":"signal-5g","codepoint":"F0A6F","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"2.6.95"},{"id":"F5CC42C0-FA38-488C-AD3F-DCF5329DFBB8","name":"signal-cellular-1","codepoint":"F08BC","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"2.2.43"},{"id":"5E21DB8A-BFFC-4038-8EBF-D3E462A43CD9","name":"signal-cellular-2","codepoint":"F08BD","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"2.2.43"},{"id":"85A2D38F-5AB3-430C-9794-032E991A4956","name":"signal-cellular-3","codepoint":"F08BE","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"2.2.43"},{"id":"AA11AD00-4A6D-4D7F-911C-137CDDCF34B6","name":"signal-cellular-outline","codepoint":"F08BF","aliases":["signal-cellular-0"],"tags":["Cellphone \/ Phone"],"author":"Michael Richins","version":"2.2.43"},{"id":"D0767E67-DC33-4B2B-9715-7408FD4F502D","name":"signal-distance-variant","codepoint":"F0E64","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.6.95"},{"id":"A960C38F-7EFE-4FE6-94AB-C7B0CD07DD50","name":"signal-hspa","codepoint":"F0715","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"1.8.36"},{"id":"CDCB7012-AD69-4B80-A64E-FDA1375271AD","name":"signal-hspa-plus","codepoint":"F0716","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"1.8.36"},{"id":"9DAFE242-BF4B-43F8-8A6E-89EBB0EEDCAA","name":"signal-off","codepoint":"F0783","aliases":[],"tags":["Cellphone \/ Phone"],"author":"GreenTurtwig","version":"1.9.32"},{"id":"F4D628E8-ADAA-48B7-9ED2-83560FF4583F","name":"signal-variant","codepoint":"F060A","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"CA1E5FB5-D8FA-4B61-9C96-988F6829C4F5","name":"signature","codepoint":"F0DFB","aliases":[],"tags":["Form"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"4DD4EB10-012B-4A70-8C9A-256B3F575BD5","name":"signature-freehand","codepoint":"F0DFC","aliases":[],"tags":["Form"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"3A24A33E-C173-4E3C-8D8B-BA7E7E3E093A","name":"signature-image","codepoint":"F0DFD","aliases":[],"tags":["Form"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"70DE882E-E115-42F9-A023-FBEE394DA396","name":"signature-text","codepoint":"F0DFE","aliases":[],"tags":["Form"],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"73A40E8E-7F62-454C-BFD9-A10796BA4A0A","name":"silo","codepoint":"F0B49","aliases":["farm"],"tags":["Agriculture"],"author":"Contributors","version":"2.8.94"},{"id":"F7C26535-863F-4295-9E48-9847B740FEE7","name":"silverware","codepoint":"F04A3","aliases":["local-dining","restaurant-menu","local-restaurant"],"tags":["Food \/ Drink"],"author":"Google","version":"1.5.54"},{"id":"57F11CAE-4E4B-4406-A5A8-2F5A283ABF99","name":"silverware-clean","codepoint":"F0FDE","aliases":["silverware-shimmer"],"tags":["Food \/ Drink"],"author":"Simran","version":"4.0.96"},{"id":"7B00A99C-3766-4939-993F-657333EE430B","name":"silverware-fork","codepoint":"F04A4","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C3D19BD6-D474-4F86-94AA-1A4B04FE8E3A","name":"silverware-fork-knife","codepoint":"F0A70","aliases":["restaurant","fortnite"],"tags":["Food \/ Drink"],"author":"Google","version":"2.6.95"},{"id":"5FCBB812-F381-4E83-B60E-E126992910FB","name":"silverware-spoon","codepoint":"F04A5","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A91FC6E1-2613-41E7-A8CA-58740B3322DA","name":"silverware-variant","codepoint":"F04A6","aliases":[],"tags":["Food \/ Drink","Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"93020F21-A0FE-427D-8685-B74EE39B9921","name":"sim","codepoint":"F04A7","aliases":["sim-card","subscriber-identity-module","subscriber-identification-module"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"43CD286A-D183-474F-9B8A-93D43A355117","name":"sim-alert","codepoint":"F04A8","aliases":["sim-warning","sim-card-alert"],"tags":["Alert \/ Error","Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"23E2DADA-D539-422C-B925-9DCB1445B344","name":"sim-alert-outline","codepoint":"F15D3","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"65B6C060-C1A9-4049-A6B6-FEAC02A899D3","name":"sim-off","codepoint":"F04A9","aliases":["signal-cellular-no-sim"],"tags":["Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"D7CAB5D9-2494-4528-B45E-A8EA49EA8262","name":"sim-off-outline","codepoint":"F15D4","aliases":[],"tags":["Cellphone \/ Phone"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"C886D757-3CAE-4BAF-9F51-0747142FC508","name":"sim-outline","codepoint":"F15D5","aliases":["sim-card-outline","subscriber-identity-module-outline","subscriber-identification-module-outline"],"tags":["Cellphone \/ Phone"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"A062A6A1-E475-41CD-AFB2-283199B67CC8","name":"simple-icons","codepoint":"F131D","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"4.8.95"},{"id":"2AA993E0-4C1C-4993-84E6-D0BA0AC89EB0","name":"sina-weibo","codepoint":"F0ADF","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.7.94"},{"id":"2099C23C-E6F6-4C9B-AA3C-49A693E73E2E","name":"sine-wave","codepoint":"F095B","aliases":["alternating-current","current-ac","wave","analog"],"tags":["Audio"],"author":"Nick","version":"2.4.85"},{"id":"673CE0A7-8AA2-4BFD-9308-B51589FBF520","name":"sitemap","codepoint":"F04AA","aliases":["workflow","flowchart"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"81D1F53A-2A63-4C9A-9CA9-547E68BB1329","name":"size-l","codepoint":"F13A6","aliases":["size-large"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"D0FECA65-0432-4231-AFA5-EDD331188CD6","name":"size-m","codepoint":"F13A5","aliases":["size-medium"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"AE5079DB-D7D6-4F38-85C1-FAE6CDF14CC2","name":"size-s","codepoint":"F13A4","aliases":["size-small"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"E7FCE878-E3CA-4EF8-B0B5-D926ACE33122","name":"size-xl","codepoint":"F13A7","aliases":["size-extra-large"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"D0173A61-33D3-43A2-8DB3-2E95EEEF7D7E","name":"size-xs","codepoint":"F13A3","aliases":["size-extra-small"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"5E24686F-4675-4E74-93B4-DA7886270F3B","name":"size-xxl","codepoint":"F13A8","aliases":["size-extra-extra-large"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"97AAC6A1-8F86-49CD-AAE2-3F9CFDDCBD82","name":"size-xxs","codepoint":"F13A2","aliases":["size-extra-extra-small"],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"3B3E6BCE-E0D1-4A4E-B720-D73C03C88C64","name":"size-xxxl","codepoint":"F13A9","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"CB0C6DC2-0A4E-41C8-9E6A-9A8531F754CF","name":"skate","codepoint":"F0D35","aliases":["ice-skate"],"tags":["Sport"],"author":"Google","version":"3.3.92"},{"id":"56BF6222-BEC1-44B6-845C-AD6F84552D90","name":"skateboard","codepoint":"F14C2","aliases":[],"tags":["Sport"],"author":"Google","version":"5.3.45"},{"id":"43E5E22F-AEEB-406D-BEF3-898BE3C91FC1","name":"skew-less","codepoint":"F0D36","aliases":["skew-decrease"],"tags":["Math"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"D84076D2-8C7C-4CD7-98EA-05108B10FF1A","name":"skew-more","codepoint":"F0D37","aliases":["skew-increase"],"tags":["Math"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"197B0D1A-34DB-4FD7-825B-FFE5C28297BB","name":"ski","codepoint":"F1304","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"BD9C05A6-55EA-4F72-A216-85F990F65EDA","name":"ski-cross-country","codepoint":"F1305","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"51D8DB1F-FA7C-4527-AD8E-495024CD4E2D","name":"ski-water","codepoint":"F1306","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"45260E4C-E8EB-4E35-85A8-F19A91FE1A2C","name":"skip-backward","codepoint":"F04AB","aliases":["title-backward","previous-title"],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"22E55747-AE80-4DE9-8BC8-10B61C69F161","name":"skip-backward-outline","codepoint":"F0F25","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"760EA0AB-7906-4FA4-86E0-CD18A4073302","name":"skip-forward","codepoint":"F04AC","aliases":["title-forward","next-title"],"tags":["Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"1EB18C03-3143-42C6-ACA9-D62086DA371D","name":"skip-forward-outline","codepoint":"F0F26","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"D2F19A25-4EF4-41A7-A91A-C03C77E32186","name":"skip-next","codepoint":"F04AD","aliases":[],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"0D688B5D-27F8-47CF-9234-87DB3F25D28E","name":"skip-next-circle","codepoint":"F0661","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"5AE3DE91-B2E8-48DD-A170-1F26E391F830","name":"skip-next-circle-outline","codepoint":"F0662","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"FB14BE1B-5BAD-44CD-9E68-CABE4A79F527","name":"skip-next-outline","codepoint":"F0F27","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"8D8B924F-0AD5-4458-9BCE-0A5887D935B6","name":"skip-previous","codepoint":"F04AE","aliases":[],"tags":["Home Automation"],"author":"Google","version":"1.5.54"},{"id":"3584845F-971C-45BB-8184-CFEBE0044474","name":"skip-previous-circle","codepoint":"F0663","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"FF83529F-FAA5-4FAD-9EE8-9F9A74409F93","name":"skip-previous-circle-outline","codepoint":"F0664","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"F1415D50-592B-4480-94D6-1FA82CDBA7B9","name":"skip-previous-outline","codepoint":"F0F28","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"AD1B00BA-C98D-4961-A444-9484EF434BEC","name":"skull","codepoint":"F068C","aliases":[],"tags":["Holiday","Gaming \/ RPG"],"author":"Haley Halcyon","version":"1.7.12"},{"id":"C85F31B5-3C18-480D-B3A6-7F4FB7095273","name":"skull-crossbones","codepoint":"F0BC6","aliases":["jolly-roger"],"tags":["Gaming \/ RPG","Holiday"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"5DBA18AE-EED4-4F73-A0FD-ACC5E731A70C","name":"skull-crossbones-outline","codepoint":"F0BC7","aliases":["jolly-roger-outline"],"tags":["Gaming \/ RPG","Holiday"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"31E17B6D-1AD2-43C5-9FF3-6A8D2FA32C17","name":"skull-outline","codepoint":"F0BC8","aliases":[],"tags":["Holiday","Gaming \/ RPG"],"author":"Michael Irigoyen","version":"3.0.39"},{"id":"3FF20BCB-0BFF-4F46-ABE9-954C8F2EB154","name":"skull-scan","codepoint":"F14C7","aliases":["x-ray","radiology"],"tags":["Medical \/ Hospital"],"author":"Simran","version":"5.3.45"},{"id":"FFA72D4C-C2EE-4492-B556-95C873FF1677","name":"skull-scan-outline","codepoint":"F14C8","aliases":["x-ray-outline","radiology-outline"],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"07E9D89D-2D58-40C6-9D41-49722CFC0DAE","name":"skype","codepoint":"F04AF","aliases":["microsoft-skype"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"813333B0-4A34-4AC6-819C-0FBEABC06246","name":"skype-business","codepoint":"F04B0","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"EA0E061F-B48E-4443-BBE8-6080C2258730","name":"slack","codepoint":"F04B1","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"355F6D86-E6B6-4EA4-91BA-95370240E9CF","name":"slash-forward","codepoint":"F0FDF","aliases":["divide","division"],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"D6A5CF49-38A9-4911-ACAC-FF9A09BBEC76","name":"slash-forward-box","codepoint":"F0FE0","aliases":["divide-box","division-box"],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"C9CF20D8-55F4-4997-8019-F8056ED86702","name":"sleep","codepoint":"F04B2","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"0801B02C-2187-40D1-8A03-D521D0214662","name":"sleep-off","codepoint":"F04B3","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"799D9561-AC12-4E30-8CA8-2FBF9E5597B8","name":"slide","codepoint":"F15A5","aliases":["playground-slide"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"34D7190A-2B00-4B61-9A55-1E97E6F962A5","name":"slope-downhill","codepoint":"F0DFF","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"99641F5F-1036-4092-B230-C1CBC7E6A746","name":"slope-uphill","codepoint":"F0E00","aliases":[],"tags":[],"author":"Michael Richins","version":"3.5.94"},{"id":"8DAEB736-3A62-475D-81A5-47BD881EA912","name":"slot-machine","codepoint":"F1114","aliases":["casino","gambling"],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"5A083823-77FD-4C5E-98B8-EF320E8493CD","name":"slot-machine-outline","codepoint":"F1115","aliases":["casino-outline","gambling-outline"],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"9682A6D2-A7FA-47BF-A94E-6CDEC8B55446","name":"smart-card","codepoint":"F10BD","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.2.95"},{"id":"D5EED689-19F3-4198-9A00-27C6DAE518E7","name":"smart-card-outline","codepoint":"F10BE","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.2.95"},{"id":"143C16AD-B22C-4E1D-915D-3FE9C962DD2F","name":"smart-card-reader","codepoint":"F10BF","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.2.95"},{"id":"FCC195C4-2DB3-45DE-B9D2-4535A63EDB0E","name":"smart-card-reader-outline","codepoint":"F10C0","aliases":[],"tags":["Account \/ User"],"author":"Michael Richins","version":"4.2.95"},{"id":"FD344F98-3CED-4CDD-88FF-8A21A1DFDE47","name":"smog","codepoint":"F0A71","aliases":[],"tags":[],"author":"Simran","version":"2.6.95"},{"id":"1DDC71A0-A86A-4E8F-BF1D-CD33C0B0BEA4","name":"smoke-detector","codepoint":"F0392","aliases":["nest-protect","subwoofer"],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"20A9F2BB-C53E-410E-A433-4CEE2305AD49","name":"smoking","codepoint":"F04B4","aliases":["cigarette","smoking-area","smoking-rooms"],"tags":["Automotive"],"author":"Google","version":"1.5.54"},{"id":"5F974B83-AEEC-4C52-B281-1A8663B70027","name":"smoking-off","codepoint":"F04B5","aliases":["no-smoking","cigarette-off","smoke-free"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8F75261A-E650-4B58-84AE-C805677DCC44","name":"smoking-pipe","codepoint":"F140D","aliases":[],"tags":[],"author":"Haley Halcyon","version":"5.1.45"},{"id":"D43EF949-5B56-488A-91AE-1B19CDE64ED8","name":"smoking-pipe-off","codepoint":"F1428","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"529CCAF2-D35F-4A40-BEF2-213159AE5DD9","name":"snail","codepoint":"F1677","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"C525609F-8CAF-40A8-A3FC-724F6C699E0A","name":"snake","codepoint":"F150E","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"6DA57C23-2ADA-4CA1-8D1D-AFBBFA59C4FA","name":"snapchat","codepoint":"F04B6","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"C2A03E16-166E-4FAA-A5DB-462CE38C44FE","name":"snowboard","codepoint":"F1307","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"5675A747-D467-473E-9A1D-1C61E1B5C619","name":"snowflake","codepoint":"F0717","aliases":[],"tags":["Weather","Holiday","Automotive"],"author":"Google","version":"1.8.36"},{"id":"5F856EA3-F987-439D-AAFF-ED545ECBBA75","name":"snowflake-alert","codepoint":"F0F29","aliases":["cold-alert","snow-advisory","freeze-advisory"],"tags":["Weather","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"017BAEB6-E5B4-4BEF-8CA3-D0ABA689DE2C","name":"snowflake-melt","codepoint":"F12CB","aliases":["defrost"],"tags":["Weather"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"C80A9F84-F736-4E92-8D93-05F9F72D32B8","name":"snowflake-off","codepoint":"F14E3","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"50B6D484-E7DC-4B88-9981-9C962C9A9EB6","name":"snowflake-variant","codepoint":"F0F2A","aliases":[],"tags":["Holiday","Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"06497E01-D87F-479B-90DC-B4E33497C8D8","name":"snowman","codepoint":"F04B7","aliases":[],"tags":["Holiday"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B4AFB6A4-C315-4B06-AE4D-AC633F3ED0A7","name":"soccer","codepoint":"F04B8","aliases":["football"],"tags":["Sport"],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"C24D4262-700B-46E1-82C1-01449C16205E","name":"soccer-field","codepoint":"F0834","aliases":["football-pitch"],"tags":["Sport"],"author":"GreenTurtwig","version":"2.1.19"},{"id":"D6384EF6-9386-4287-BE34-7038841AABD5","name":"social-distance-2-meters","codepoint":"F1579","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"59F69A6A-5DB4-4938-A90A-B186655409C5","name":"social-distance-6-feet","codepoint":"F157A","aliases":[],"tags":["Medical \/ Hospital"],"author":"Google","version":"5.5.55"},{"id":"5560ABF9-E635-4D73-A39B-5404443F099F","name":"sofa","codepoint":"F04B9","aliases":["couch"],"tags":[],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"37B31F21-3190-4E2D-A824-C5CC4FF66493","name":"sofa-outline","codepoint":"F156D","aliases":["couch-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"61A9F431-1946-4F8F-9DB4-19E75151D397","name":"sofa-single","codepoint":"F156E","aliases":["loveseat","love-seat","couch","chair-accent"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"C4595FA1-E495-4BFE-900A-A1D764B6019E","name":"sofa-single-outline","codepoint":"F156F","aliases":["loveseat-outline","love-seat-outline","couch-outline","chair-accent-outline"],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"46CD8278-94CE-46F4-B2A5-01D4595E48A0","name":"solar-panel","codepoint":"F0D9B","aliases":[],"tags":[],"author":"Contributors","version":"3.4.93"},{"id":"13BD6DBE-90E0-42A0-8FE6-A168974483CA","name":"solar-panel-large","codepoint":"F0D9C","aliases":[],"tags":[],"author":"Contributors","version":"3.4.93"},{"id":"727F32FC-051B-43FE-9888-4616927AE828","name":"solar-power","codepoint":"F0A72","aliases":[],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"4A90CB52-2637-4E5D-8333-467DD85B36F6","name":"soldering-iron","codepoint":"F1092","aliases":[],"tags":[],"author":"Simran","version":"4.2.95"},{"id":"F0E0017F-DD8C-4811-9428-613238CA66A4","name":"solid","codepoint":"F068D","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.7.12"},{"id":"FF92F5A9-DE89-4E7D-BCAB-98920EA96FFE","name":"sony-playstation","codepoint":"F0414","aliases":["sony-playstation","playstation-network"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.5.54"},{"id":"3052FDE9-791A-43E8-ACF4-A5EB7DF8296F","name":"sort","codepoint":"F04BA","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"1.5.54"},{"id":"496476A3-F614-4925-90E6-3BB83C1C4E37","name":"sort-alphabetical-ascending","codepoint":"F05BD","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"1.5.54"},{"id":"96571AB7-B3D4-4A76-ADE0-47D931FF1F0A","name":"sort-alphabetical-ascending-variant","codepoint":"F1148","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Contributors","version":"4.4.95"},{"id":"7F545D3A-5E66-42D4-88AB-8A2BD817D731","name":"sort-alphabetical-descending","codepoint":"F05BF","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"1.5.54"},{"id":"D4F8234D-4EE3-4825-861E-C46E8FE6F438","name":"sort-alphabetical-descending-variant","codepoint":"F1149","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Contributors","version":"4.4.95"},{"id":"C2687EF2-6AEB-48BC-98E5-9A010C6E2BE7","name":"sort-alphabetical-variant","codepoint":"F04BB","aliases":["sort-by-alpha","sort-alphabetically"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"F36D1111-54BF-4BB8-AE34-DE4809105551","name":"sort-ascending","codepoint":"F04BC","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"1.5.54"},{"id":"BDB3C0CD-D017-4895-82AD-41FEE4351FA6","name":"sort-bool-ascending","codepoint":"F1385","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"5.0.45"},{"id":"9F0F11BF-8F55-45CD-B185-7C8BC278954C","name":"sort-bool-ascending-variant","codepoint":"F1386","aliases":["sort-checkbox-ascending"],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"5.0.45"},{"id":"36E782AF-0396-45C7-B5C2-61FB37C01E2F","name":"sort-bool-descending","codepoint":"F1387","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"5.0.45"},{"id":"549371B9-36F9-45E7-918A-72EEB98F9572","name":"sort-bool-descending-variant","codepoint":"F1388","aliases":["sort-checkbox-descending"],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"5.0.45"},{"id":"87CE4E85-7911-415C-89AB-133A2AB8BC57","name":"sort-calendar-ascending","codepoint":"F1547","aliases":["sort-date-ascending"],"tags":["Text \/ Content \/ Format","Date \/ Time"],"author":"Austin Andrews","version":"5.4.55"},{"id":"D01B3C7C-64DC-4486-A656-55F7024C96AA","name":"sort-calendar-descending","codepoint":"F1548","aliases":["sort-date-descending"],"tags":["Text \/ Content \/ Format","Date \/ Time"],"author":"Austin Andrews","version":"5.4.55"},{"id":"2A4F548A-F4C1-48F2-BFB1-A6A1ACB794A6","name":"sort-clock-ascending","codepoint":"F1549","aliases":["sort-time-ascending"],"tags":["Text \/ Content \/ Format","Date \/ Time"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"85579FDA-7E54-483B-B1DD-A1920DFBEED6","name":"sort-clock-ascending-outline","codepoint":"F154A","aliases":["sort-time-ascending-outline"],"tags":["Text \/ Content \/ Format","Date \/ Time"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"8064DE58-939A-4179-A65E-0F5FA4AD6A18","name":"sort-clock-descending","codepoint":"F154B","aliases":["sort-time-descending"],"tags":["Text \/ Content \/ Format","Date \/ Time"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"B574E857-7AE0-493E-82E1-36DC10882508","name":"sort-clock-descending-outline","codepoint":"F154C","aliases":["sort-time-descending-outline"],"tags":["Text \/ Content \/ Format","Date \/ Time"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"F0028BDF-0589-400F-8596-100CCB029D6E","name":"sort-descending","codepoint":"F04BD","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"1.5.54"},{"id":"68CF5B27-ACB2-468B-BD75-1DAE92A7D242","name":"sort-numeric-ascending","codepoint":"F1389","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"5.0.45"},{"id":"D3472197-9E32-440B-9F56-E84F2D35C657","name":"sort-numeric-ascending-variant","codepoint":"F090D","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.3.50"},{"id":"E0ABC4A1-3840-48EF-82F8-BFF825D02F64","name":"sort-numeric-descending","codepoint":"F138A","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"frankgrinaert","version":"5.0.45"},{"id":"618ED59F-832C-4DA8-A8F6-421CC6A10305","name":"sort-numeric-descending-variant","codepoint":"F0AD2","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"2CD8E0F3-0AF4-4BBD-B1C8-EEF6391F62C3","name":"sort-numeric-variant","codepoint":"F04BE","aliases":["sort-numerically"],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"A00FD3F3-01E7-489E-AB22-66F3B94AF6C0","name":"sort-reverse-variant","codepoint":"F033C","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Simran","version":"1.5.54"},{"id":"9E32B54D-9759-4233-B358-C00A11300713","name":"sort-variant","codepoint":"F04BF","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"1.5.54"},{"id":"450895A4-8BFF-4F63-A567-2010226F7464","name":"sort-variant-lock","codepoint":"F0CCD","aliases":[],"tags":["Text \/ Content \/ Format","Lock"],"author":"Christopher Schreiner","version":"3.2.89"},{"id":"30DC202C-F695-4A76-B3BB-293BCC995A6E","name":"sort-variant-lock-open","codepoint":"F0CCE","aliases":[],"tags":["Text \/ Content \/ Format","Lock"],"author":"Christopher Schreiner","version":"3.2.89"},{"id":"51D1A98E-7CD7-4BD7-88C9-333B5435C580","name":"sort-variant-remove","codepoint":"F1147","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Contributors","version":"4.4.95"},{"id":"5952089F-872D-454C-AD1F-18B205938245","name":"soundcloud","codepoint":"F04C0","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"AADA1B60-0161-4417-9726-75AFB5C7AC31","name":"source-branch","codepoint":"F062C","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.6.50"},{"id":"66701C6C-D1D4-42FF-AA03-74C3F4E65AC1","name":"source-branch-check","codepoint":"F14CF","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"288DC509-ABA1-436D-8D8D-F54FEE2DA4B8","name":"source-branch-minus","codepoint":"F14CB","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"D5EAA72B-6FF0-4520-8207-A7E3E47B35F5","name":"source-branch-plus","codepoint":"F14CA","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"58A72E01-DBCC-4C66-AAFE-FB37845FB50E","name":"source-branch-refresh","codepoint":"F14CD","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"EB47CC8C-8EF2-4FE2-9530-2360C26378B6","name":"source-branch-remove","codepoint":"F14CC","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"0A420930-2315-468C-B639-0D7E96D6937A","name":"source-branch-sync","codepoint":"F14CE","aliases":[],"tags":["Developer \/ Languages"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"B0400135-C84A-47D8-AD30-B6BD8292E6A4","name":"source-commit","codepoint":"F0718","aliases":[],"tags":[],"author":"Case Sandberg","version":"1.8.36"},{"id":"5558E497-77AD-48F4-9456-E6D6B4CA991B","name":"source-commit-end","codepoint":"F0719","aliases":[],"tags":[],"author":"Case Sandberg","version":"1.8.36"},{"id":"5681B6C8-CC7F-42B0-9B6F-B53D9A72D12F","name":"source-commit-end-local","codepoint":"F071A","aliases":[],"tags":[],"author":"Case Sandberg","version":"1.8.36"},{"id":"DF889541-FEF0-42C0-BF6E-E29D4503C3FB","name":"source-commit-local","codepoint":"F071B","aliases":[],"tags":[],"author":"Case Sandberg","version":"1.8.36"},{"id":"42A5B80B-C7A6-42F4-8437-458F504B7AF5","name":"source-commit-next-local","codepoint":"F071C","aliases":[],"tags":[],"author":"Case Sandberg","version":"1.8.36"},{"id":"6647D5DC-4BF4-47FB-9B11-F1ABB94B3769","name":"source-commit-start","codepoint":"F071D","aliases":[],"tags":[],"author":"Case Sandberg","version":"1.8.36"},{"id":"64F8200C-7866-46A6-9E8B-1CAF621517CC","name":"source-commit-start-next-local","codepoint":"F071E","aliases":[],"tags":[],"author":"Case Sandberg","version":"1.8.36"},{"id":"F2A480EB-B06A-4472-88B9-C881754675FE","name":"source-fork","codepoint":"F04C1","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C4A094D6-A68C-41F8-A2EC-C87997DACE70","name":"source-merge","codepoint":"F062D","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.6.50"},{"id":"6555FD23-E5EE-4F40-91CF-B72476ADED54","name":"source-pull","codepoint":"F04C2","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.5.54"},{"id":"1D318024-029E-4654-A318-6647D265CDD9","name":"source-repository","codepoint":"F0CCF","aliases":[],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"3.2.89"},{"id":"16D37AE7-409E-48A5-BE24-9DCBA0792FD7","name":"source-repository-multiple","codepoint":"F0CD0","aliases":["source-repositories"],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"3.2.89"},{"id":"62A5E551-73E0-4C84-89E4-C0F34BDACEFA","name":"soy-sauce","codepoint":"F07EE","aliases":["soya-sauce"],"tags":["Food \/ Drink"],"author":"Colton Wiscombe","version":"2.0.46"},{"id":"31D89882-A6D2-4E79-B441-582B1497C3D2","name":"soy-sauce-off","codepoint":"F13FC","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"84F00C86-0380-4554-B142-286C3B80BA3A","name":"spa","codepoint":"F0CD1","aliases":["flower-lotus","plant"],"tags":["Nature"],"author":"Google","version":"3.2.89"},{"id":"B0D344FE-8924-48EF-BFBA-93DB1C77DFD1","name":"spa-outline","codepoint":"F0CD2","aliases":["flower-lotus-outline","plant"],"tags":["Nature"],"author":"Google","version":"3.2.89"},{"id":"0C50BCF5-076C-4DBB-BBFC-8B74B3CC64E7","name":"space-invaders","codepoint":"F0BC9","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"3.0.39"},{"id":"0F961F30-F687-4232-98E7-C27F2FC64293","name":"space-station","codepoint":"F1383","aliases":[],"tags":[],"author":"nilsfast","version":"4.9.95"},{"id":"7D15FB8A-6AD7-47C9-93AD-4E968C39CDBF","name":"spade","codepoint":"F0E65","aliases":[],"tags":["Hardware \/ Tools"],"author":"GreenTurtwig","version":"3.6.95"},{"id":"C09567B5-B5C0-4C51-A246-0CA46C928F96","name":"sparkles","codepoint":"F1545","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.4.55"},{"id":"43C37FC5-E271-40FA-BB50-C139DDD5B15B","name":"speaker","codepoint":"F04C3","aliases":[],"tags":["Audio","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"E9F560A8-FFD9-44CD-8736-00C627756591","name":"speaker-bluetooth","codepoint":"F09A2","aliases":[],"tags":["Audio"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"6CBEB113-DF44-4DCE-A490-5AAD4766CE28","name":"speaker-multiple","codepoint":"F0D38","aliases":["speakers"],"tags":["Audio"],"author":"Michael Richins","version":"3.3.92"},{"id":"9B55ECCE-270B-4A52-9A96-80BEECAD1E0B","name":"speaker-off","codepoint":"F04C4","aliases":[],"tags":["Audio","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F9EA980F-2C75-48DE-9D56-9A15CFE52865","name":"speaker-wireless","codepoint":"F071F","aliases":[],"tags":["Audio","Home Automation"],"author":"Simran","version":"1.8.36"},{"id":"F0EE6F6A-2B43-4880-8DC9-6E7515B3BEDE","name":"speedometer","codepoint":"F04C5","aliases":[],"tags":["Automotive"],"author":"Austin Andrews","version":"1.5.54"},{"id":"86833899-057F-4099-AF77-0EECD2BAE698","name":"speedometer-medium","codepoint":"F0F85","aliases":[],"tags":["Automotive"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"9500D7AF-3917-41AB-8694-94FABA5F94ED","name":"speedometer-slow","codepoint":"F0F86","aliases":[],"tags":["Automotive"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"72253002-9545-40A4-95A4-49401269B553","name":"spellcheck","codepoint":"F04C6","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BCDD4A6F-3064-4FF3-9172-0BBF8BED2D2C","name":"spider","codepoint":"F11EA","aliases":["arachnid"],"tags":["Holiday","Nature","Animal"],"author":"Michael Richins","version":"4.5.95"},{"id":"1F613123-9D4B-4C5A-84FB-F6B804BBFB21","name":"spider-thread","codepoint":"F11EB","aliases":["arachnid-thread"],"tags":["Holiday","Nature","Animal"],"author":"Michael Richins","version":"4.5.95"},{"id":"8464C75D-EA57-4E89-80E9-BE6A48793809","name":"spider-web","codepoint":"F0BCA","aliases":["cobweb","arachnid-web"],"tags":["Holiday"],"author":"Austin Andrews","version":"3.0.39"},{"id":"B647E730-0D7E-4F13-A051-74D92C2A6F0A","name":"spirit-level","codepoint":"F14F1","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"D68EF8DE-C9F5-47FB-BCD4-C0DD4D7FCBFD","name":"spoon-sugar","codepoint":"F1429","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"51C1DE39-1C25-49B7-A295-DD13B874C48B","name":"spotify","codepoint":"F04C7","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"A4956491-730F-4BC9-A6C1-03AF3C54C134","name":"spotlight","codepoint":"F04C8","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"13AE04D2-BB67-4CA4-89F6-11C88C2A217E","name":"spotlight-beam","codepoint":"F04C9","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"0CDAFE95-E28B-4A8D-9634-C6BBB99EE598","name":"spray","codepoint":"F0665","aliases":["paint","aerosol"],"tags":["Agriculture","Drawing \/ Art","Color"],"author":"Austin Andrews","version":"1.6.50"},{"id":"997059BA-96F4-456C-8B53-8355521AE536","name":"spray-bottle","codepoint":"F0AE0","aliases":["cleaning"],"tags":[],"author":"Google","version":"2.7.94"},{"id":"3B348D41-66D2-4CC7-894A-1C2E9EE64C7F","name":"sprinkler","codepoint":"F105F","aliases":["irrigation"],"tags":["Home Automation","Agriculture"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"4CE94553-ECA2-4C72-B66B-EEE5106F1438","name":"sprinkler-variant","codepoint":"F1060","aliases":["irrigation"],"tags":["Home Automation","Agriculture"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"58F40CA4-567A-42EF-A5D9-DD6A1BB42437","name":"sprout","codepoint":"F0E66","aliases":["seedling","plant"],"tags":["Agriculture","Nature"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"DDE9D3A4-FF81-4182-8FEE-3A0DD30F88F8","name":"sprout-outline","codepoint":"F0E67","aliases":["seedling-outline","plant-outline"],"tags":["Agriculture","Nature"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"5659F8EC-377D-41D2-AB3A-52DC40815DC7","name":"square","codepoint":"F0764","aliases":[],"tags":["Shape"],"author":"Austin Andrews","version":"1.9.32"},{"id":"F49668FC-6B0F-43E9-BB4E-044C3C9229AA","name":"square-circle","codepoint":"F1500","aliases":["vegetarian","lacto-vegetarian"],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"22469E65-F1CB-408D-B6B5-1E599A85E368","name":"square-edit-outline","codepoint":"F090C","aliases":[],"tags":["Edit \/ Modify"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"0267FB77-EB23-41D4-92B4-FF65796BDF40","name":"square-medium","codepoint":"F0A13","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"1EC70A02-36D5-4C3B-A721-018653864C6D","name":"square-medium-outline","codepoint":"F0A14","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"19F3DC9F-4861-4220-944C-8BE8D543902B","name":"square-off","codepoint":"F12EE","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"32823532-5FAC-4894-8577-EAED930DE4C2","name":"square-off-outline","codepoint":"F12EF","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"5ED659B5-F175-445F-950D-0B4DDAB3F8B3","name":"square-outline","codepoint":"F0763","aliases":[],"tags":["Shape"],"author":"Austin Andrews","version":"1.9.32"},{"id":"D0835CDD-0255-4A0D-B86F-DAB300C5ADCC","name":"square-root","codepoint":"F0784","aliases":[],"tags":["Math"],"author":"Austin Andrews","version":"1.9.32"},{"id":"4DD48496-5BE6-4866-A298-1D9D399651B0","name":"square-root-box","codepoint":"F09A3","aliases":[],"tags":[],"author":"Nick","version":"2.4.85"},{"id":"56B32490-2AEB-4EF7-B0F8-72D918829BE2","name":"square-rounded","codepoint":"F14FB","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.4.55"},{"id":"9E46259E-F519-4CCA-BE7E-0DAC8230B3A4","name":"square-rounded-outline","codepoint":"F14FC","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.4.55"},{"id":"E4490267-ACAE-4E86-8747-8D2D620DC707","name":"square-small","codepoint":"F0A15","aliases":["bullet"],"tags":[],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"F55F6161-5EE4-4168-881C-A50E671AC25F","name":"square-wave","codepoint":"F147B","aliases":[],"tags":["Audio"],"author":"Haley Halcyon","version":"5.2.45"},{"id":"363A0CD3-194D-4F7F-9287-82B8D565B064","name":"squeegee","codepoint":"F0AE1","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"EC87D6AA-77FC-462A-82AC-715550CD98AB","name":"ssh","codepoint":"F08C0","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.2.43"},{"id":"D76A8752-ED97-4E90-95EC-B1D6E81ABA9E","name":"stack-exchange","codepoint":"F060B","aliases":["stackexchange"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"72E7037B-1C3B-44BB-A9EC-FC2D6B3EA745","name":"stack-overflow","codepoint":"F04CC","aliases":["stackoverflow"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"7FB125A0-875A-4766-BFAF-02CC45226530","name":"stackpath","codepoint":"F0359","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"5FDB24B6-FF16-4575-A794-E5CCEB95CC81","name":"stadium","codepoint":"F0FF9","aliases":[],"tags":[],"author":"Google","version":"4.0.96"},{"id":"0407BE27-099D-4170-BA1C-A87A4239F9DA","name":"stadium-variant","codepoint":"F0720","aliases":["arena"],"tags":["Places","Sport"],"author":"Alex Efremo","version":"1.8.36"},{"id":"D5BBEF8B-FC7A-4FA5-9DA6-4D970AC6A530","name":"stairs","codepoint":"F04CD","aliases":[],"tags":["Transportation + Other"],"author":"Simran","version":"1.5.54"},{"id":"58C2BC63-FCF5-445B-B351-23CF48253FEF","name":"stairs-box","codepoint":"F139E","aliases":[],"tags":[],"author":"Moma Design Studio","version":"5.0.45"},{"id":"5B344682-C177-40CC-97EC-418D010EAE07","name":"stairs-down","codepoint":"F12BE","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"4.8.95"},{"id":"8F09C6B0-DFE8-4700-A90A-476EFA6454F4","name":"stairs-up","codepoint":"F12BD","aliases":[],"tags":["Transportation + Other"],"author":"Austin Andrews","version":"4.8.95"},{"id":"2D9C68D6-6DFA-42CC-B69C-E28011FC2BF7","name":"stamper","codepoint":"F0D39","aliases":[],"tags":[],"author":"Nick","version":"3.3.92"},{"id":"DAA79A7B-03FB-431A-85DD-AB9749783DC0","name":"standard-definition","codepoint":"F07EF","aliases":[],"tags":["Video \/ Movie"],"author":"Austin Andrews","version":"2.0.46"},{"id":"53D81A11-D8FF-46F4-A0CB-B7F668BA720D","name":"star","codepoint":"F04CE","aliases":["grade","star-rate"],"tags":["Shape"],"author":"Google","version":"1.5.54"},{"id":"07CA9ED6-5D94-4145-AB3E-EA9FD7283E0A","name":"star-box","codepoint":"F0A73","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.6.95"},{"id":"9270C3C4-1ADB-4965-9DAE-444F9448B39E","name":"star-box-multiple","codepoint":"F1286","aliases":[],"tags":[],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"2B9ACC0A-EA3D-478D-935E-EAFA8F8580CF","name":"star-box-multiple-outline","codepoint":"F1287","aliases":[],"tags":[],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"B22FEE66-3EC9-466A-9014-EF53030FA3D9","name":"star-box-outline","codepoint":"F0A74","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.6.95"},{"id":"6AB2A77F-C9ED-4EF1-BDD3-4E060E690A7E","name":"star-check","codepoint":"F1566","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"94E37A05-1F0E-49EE-92D8-5FE57B54123F","name":"star-check-outline","codepoint":"F156A","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"76D19C8B-0302-436A-A19F-5AC5EE8AC88C","name":"star-circle","codepoint":"F04CF","aliases":["stars"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"9E034CD9-F400-4D4A-A2CB-6030313F2CED","name":"star-circle-outline","codepoint":"F09A4","aliases":["feature-highlight"],"tags":[],"author":"Google","version":"2.4.85"},{"id":"82407F8C-2E0B-4F79-9409-0C267A248470","name":"star-cog","codepoint":"F1668","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"D1100539-0788-4C74-AD03-8C5F8383DF2E","name":"star-cog-outline","codepoint":"F1669","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"20FBE06D-72C3-4E1C-945D-C7E69DC0736D","name":"star-face","codepoint":"F09A5","aliases":[],"tags":["Gaming \/ RPG"],"author":"Google","version":"2.4.85"},{"id":"4F7E1FD5-FE11-4509-8253-D0B2EB7E3CFF","name":"star-four-points","codepoint":"F0AE2","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"F74484E2-76FB-4671-9960-AE18E95F04FA","name":"star-four-points-outline","codepoint":"F0AE3","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"E86BFC0D-B4A4-41F2-A8E3-D1AE79072A45","name":"star-half","codepoint":"F0246","aliases":[],"tags":["Shape"],"author":"Simran","version":"1.5.54"},{"id":"52E97617-C7F4-45D0-98E0-E9B4407EC179","name":"star-half-full","codepoint":"F04D0","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"CA24758C-3B0C-44DE-9395-C5CAF2981E5D","name":"star-minus","codepoint":"F1564","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"24A0E7F1-32AA-4B4B-B0BC-93AD9F7E2F8A","name":"star-minus-outline","codepoint":"F1568","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"3CE96C58-D12F-474D-916F-D0509E3BA408","name":"star-off","codepoint":"F04D1","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"297E76E3-B7A2-44A1-A340-F479AEFEF282","name":"star-off-outline","codepoint":"F155B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"D443AD2F-291D-496E-ACD2-109891446FF2","name":"star-outline","codepoint":"F04D2","aliases":["star-border"],"tags":["Shape"],"author":"Google","version":"1.5.54"},{"id":"A782B3BE-28DC-4BF8-A209-42DC8F1CE287","name":"star-plus","codepoint":"F1563","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"0CBFD9AD-12B1-4AAF-A9CC-9CA46FEB47FD","name":"star-plus-outline","codepoint":"F1567","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"49254980-CD72-42B5-A87B-F24EFC2E4EA5","name":"star-remove","codepoint":"F1565","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"40769B91-9676-413A-8D6D-9D21132637E2","name":"star-remove-outline","codepoint":"F1569","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"30D8C8F6-3BDE-40B8-A015-6E607C370360","name":"star-settings","codepoint":"F166A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"AA6C9E76-AC9C-4373-8AC4-F5C706741FC9","name":"star-settings-outline","codepoint":"F166B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.7.55"},{"id":"18267D80-A569-4013-84F4-7024F3990F47","name":"star-shooting","codepoint":"F1741","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"27A6F1B6-E095-494B-8CC7-660695DC6E70","name":"star-shooting-outline","codepoint":"F1742","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"815B35DE-0C4D-46AD-90EC-2AFEE0A5FC17","name":"star-three-points","codepoint":"F0AE4","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"3BA12DC6-1D79-4B2A-BCF2-52FAF2160E23","name":"star-three-points-outline","codepoint":"F0AE5","aliases":[],"tags":["Shape"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"77FB59F8-81D3-4919-BBEE-3B897EC24C4E","name":"state-machine","codepoint":"F11EF","aliases":[],"tags":[],"author":"frankgrinaert","version":"4.5.95"},{"id":"FBD721A3-7CD8-4769-902C-2B434CA107EE","name":"steam","codepoint":"F04D3","aliases":[],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.5.54"},{"id":"A2FE9DC5-BC17-4265-9D2C-4CA20135C4BB","name":"steering","codepoint":"F04D4","aliases":["search-hands-free"],"tags":["Automotive"],"author":"Google","version":"1.5.54"},{"id":"1489D950-AD3A-47BD-A0CD-2E0A33943F54","name":"steering-off","codepoint":"F090E","aliases":["search-hands-free-off"],"tags":["Automotive"],"author":"Google","version":"2.3.50"},{"id":"3056B0E6-E30C-4F6D-8647-AC5559FD7DCF","name":"step-backward","codepoint":"F04D5","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"9815CAC2-7390-4AE1-AE72-2B49546987EC","name":"step-backward-2","codepoint":"F04D6","aliases":["frame-backward"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"6773EDAB-CBAA-4C56-80D6-E029EB45115E","name":"step-forward","codepoint":"F04D7","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"890D584F-45C1-4D2C-96C0-373465DB6477","name":"step-forward-2","codepoint":"F04D8","aliases":["frame-forward"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"641202BA-294A-4A0F-851D-FB83FEC9D7EE","name":"stethoscope","codepoint":"F04D9","aliases":[],"tags":["Medical \/ Hospital"],"author":"Simran","version":"1.5.54"},{"id":"D2115A9A-4F13-4F9E-888D-3E8CE835A7C3","name":"sticker","codepoint":"F1364","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"6E585638-20B9-4347-B991-62027390FCE4","name":"sticker-alert","codepoint":"F1365","aliases":[],"tags":["Alert \/ Error"],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"795CD51D-0887-4AC1-B7C1-137248AE0EB3","name":"sticker-alert-outline","codepoint":"F1366","aliases":[],"tags":["Alert \/ Error"],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"A972E9E6-C525-4162-96DA-6A66951A2547","name":"sticker-check","codepoint":"F1367","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"4239323B-AA14-4177-8F94-AB7F1577D111","name":"sticker-check-outline","codepoint":"F1368","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"F4C92E8A-A238-4F7C-B2FC-CBA914C5CE04","name":"sticker-circle-outline","codepoint":"F05D0","aliases":[],"tags":[],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"9E28CC83-5155-4620-80C1-62875D117A79","name":"sticker-emoji","codepoint":"F0785","aliases":[],"tags":["Emoji"],"author":"Google","version":"1.9.32"},{"id":"D0DB0495-F23A-4DF1-AE7B-704259C648F1","name":"sticker-minus","codepoint":"F1369","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"F8C4F362-C8D2-40FD-A631-B79E0341572C","name":"sticker-minus-outline","codepoint":"F136A","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"6F7361D9-E44F-4BBC-B5E6-D6862467A849","name":"sticker-outline","codepoint":"F136B","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"48F11F1C-7501-4EDB-B4C9-FEA63EF1C090","name":"sticker-plus","codepoint":"F136C","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"A28B1EF0-2538-4104-980A-D6F044F461AF","name":"sticker-plus-outline","codepoint":"F136D","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"27A4E71C-CF92-4AA2-9B1B-4CC6FC06B58C","name":"sticker-remove","codepoint":"F136E","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"CA6D437A-FDC6-48F6-9414-A5B7832053F1","name":"sticker-remove-outline","codepoint":"F136F","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"4.9.95"},{"id":"3C90040A-0B3F-4849-B21D-E16240D7A699","name":"stocking","codepoint":"F04DA","aliases":[],"tags":["Holiday"],"author":"Austin Andrews","version":"1.5.54"},{"id":"675A613A-F713-458A-970C-86883FF6C2B0","name":"stomach","codepoint":"F1093","aliases":[],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"F1057179-EA45-4D87-A14D-D05442C06503","name":"stop","codepoint":"F04DB","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"EC57EC60-1C8E-45CE-BF4A-D019AFD1F148","name":"stop-circle","codepoint":"F0666","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"B343DEEB-A0ED-41BF-8C86-37D04A1040A6","name":"stop-circle-outline","codepoint":"F0667","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"3C3AEDE0-B6DA-4CB9-A686-869634678D5D","name":"store","codepoint":"F04DC","aliases":["shop","store-mall-directory"],"tags":["Places","Shopping"],"author":"Google","version":"1.5.54"},{"id":"417393DA-3C7F-4BF2-9283-AB1429FFA068","name":"store-24-hour","codepoint":"F04DD","aliases":["local-convenience-store","shop-24-hour"],"tags":["Places","Shopping"],"author":"Google","version":"1.5.54"},{"id":"D52803B6-8580-4C06-AA9F-96B4748286DB","name":"store-minus","codepoint":"F165E","aliases":[],"tags":[],"author":"Contributors","version":"5.7.55"},{"id":"6BF9FB77-DF50-40B5-9A93-43E2A22E8633","name":"store-outline","codepoint":"F1361","aliases":["shop-outline","store-mall-directory-outline"],"tags":["Places","Shopping"],"author":"Google","version":"4.9.95"},{"id":"00DB5451-A5BF-4F9C-AC74-041916EACCB6","name":"store-plus","codepoint":"F165F","aliases":[],"tags":[],"author":"Contributors","version":"5.7.55"},{"id":"FB5C0EA4-DAA2-4415-856F-2A4E6FA78BA5","name":"store-remove","codepoint":"F1660","aliases":[],"tags":[],"author":"Contributors","version":"5.7.55"},{"id":"8ABE8FB2-F704-4095-9E65-F614F86FCE99","name":"storefront","codepoint":"F07C7","aliases":["awning"],"tags":[],"author":"Simran","version":"2.0.46"},{"id":"CFC9D5C9-A60F-48D0-880E-71F2A06BB94D","name":"storefront-outline","codepoint":"F10C1","aliases":["awning"],"tags":["Shopping"],"author":"Google","version":"4.2.95"},{"id":"18EF6E1E-8EF9-4A62-AAB9-6E8BE591408A","name":"stove","codepoint":"F04DE","aliases":["cooker","oven"],"tags":["Food \/ Drink","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"854C16E8-58EA-49E3-B1AE-7EC84B313005","name":"strategy","codepoint":"F11D6","aliases":["football-play"],"tags":["Sport"],"author":"Michael Richins","version":"4.5.95"},{"id":"8E85E624-D1D8-4BA3-A99C-3067863D355C","name":"stretch-to-page","codepoint":"F0F2B","aliases":[],"tags":["Text \/ Content \/ Format","Arrow"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"7F50D690-0790-42F3-B9C3-B0AB9338DAC7","name":"stretch-to-page-outline","codepoint":"F0F2C","aliases":[],"tags":["Text \/ Content \/ Format","Arrow"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"6CCDB34F-9B02-4712-B615-A7E1056B534D","name":"string-lights","codepoint":"F12BA","aliases":["italian-lights","christmas-lights","fairy-lights"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"F1B6F6EB-6D20-4C27-A631-8FAF759D183A","name":"string-lights-off","codepoint":"F12BB","aliases":["italian-lights-off","christmas-lights-off","fairy-lights-off"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"FC46F7BD-E8E2-452C-868C-E168E13B278D","name":"subdirectory-arrow-left","codepoint":"F060C","aliases":[],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"AFD661FE-31E3-4BB5-8977-10113C7AC3F4","name":"subdirectory-arrow-right","codepoint":"F060D","aliases":[],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"C6D1D0D8-7FEF-4F4B-B0E8-1B87B9413209","name":"submarine","codepoint":"F156C","aliases":[],"tags":[],"author":"Contributors","version":"5.5.55"},{"id":"9808EEC5-35FB-45B1-AFCB-065E9CF469E4","name":"subtitles","codepoint":"F0A16","aliases":[],"tags":[],"author":"Google","version":"2.5.94"},{"id":"451E9683-F30C-4B0A-95EE-5AD92B012F26","name":"subtitles-outline","codepoint":"F0A17","aliases":[],"tags":[],"author":"Google","version":"2.5.94"},{"id":"769FB684-BA81-4E2A-B623-4C8B6F3DCD2C","name":"subway","codepoint":"F06AC","aliases":["metro","tube","underground"],"tags":["Transportation + Other"],"author":"Google","version":"1.7.12"},{"id":"486507F3-9E59-4037-B0EA-8EE514AFFABB","name":"subway-alert-variant","codepoint":"F0D9D","aliases":["subway-warning-variant"],"tags":["Alert \/ Error","Transportation + Other"],"author":"Austin Andrews","version":"3.4.93"},{"id":"EBD55581-BE34-4D0D-A151-974FD5FD7D92","name":"subway-variant","codepoint":"F04DF","aliases":["metro-variant","tube-variant","underground-variant","directions-subway","directions-transit"],"tags":["Transportation + Other"],"author":"Google","version":"1.5.54"},{"id":"052D93D8-A1F1-450C-99F3-AEEE07D77CF4","name":"summit","codepoint":"F0786","aliases":["peak"],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"E52FC33A-09BD-4B34-AF94-92C891020CDC","name":"sunglasses","codepoint":"F04E0","aliases":[],"tags":["Clothing"],"author":"Simran","version":"1.5.54"},{"id":"AB38BBD9-58A6-4D21-8A76-8940B7717550","name":"surround-sound","codepoint":"F05C5","aliases":[],"tags":["Audio"],"author":"Google","version":"1.5.54"},{"id":"13009B66-7459-4C86-8EB0-3CAED977BB98","name":"surround-sound-2-0","codepoint":"F07F0","aliases":["stereo"],"tags":["Audio"],"author":"Austin Andrews","version":"2.0.46"},{"id":"901A06AA-7C77-43B3-90CD-10B329C42DB7","name":"surround-sound-2-1","codepoint":"F1729","aliases":[],"tags":[],"author":"GreenTurtwig","version":"5.9.55"},{"id":"4B744BE0-A739-44FF-ADA6-CFC9BC520B1D","name":"surround-sound-3-1","codepoint":"F07F1","aliases":[],"tags":["Audio"],"author":"Austin Andrews","version":"2.0.46"},{"id":"CFD48DE8-0DA8-455C-9C4C-337EDC54D7C0","name":"surround-sound-5-1","codepoint":"F07F2","aliases":[],"tags":["Audio"],"author":"Austin Andrews","version":"2.0.46"},{"id":"0CA5BC19-D66A-4126-B2DB-A90546826760","name":"surround-sound-5-1-2","codepoint":"F172A","aliases":[],"tags":[],"author":"GreenTurtwig","version":"5.9.55"},{"id":"BC85CD47-E52C-4A7D-8E05-DD45596C5822","name":"surround-sound-7-1","codepoint":"F07F3","aliases":[],"tags":["Audio"],"author":"Austin Andrews","version":"2.0.46"},{"id":"5E34C73B-E200-4BD3-A10E-A00D1D47BFF4","name":"svg","codepoint":"F0721","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"D1E543C5-6ECA-43AA-B04D-438319BC5562","name":"swap-horizontal","codepoint":"F04E1","aliases":["arrow-left-right"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"3082F9ED-7ADE-491E-9FA5-39BC937D1F95","name":"swap-horizontal-bold","codepoint":"F0BCD","aliases":["arrow-left-right-bold"],"tags":["Arrow"],"author":"Google","version":"3.0.39"},{"id":"11867345-3F46-40E5-91A4-4EBBE393226D","name":"swap-horizontal-circle","codepoint":"F0FE1","aliases":[],"tags":["Arrow"],"author":"Google","version":"4.0.96"},{"id":"4A41DEBC-9D40-4C27-A48E-EDF8E64ADBC2","name":"swap-horizontal-circle-outline","codepoint":"F0FE2","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"23A48C18-9950-436D-9948-29EE7EE13054","name":"swap-horizontal-variant","codepoint":"F08C1","aliases":[],"tags":["Arrow"],"author":"Google","version":"2.2.43"},{"id":"DA7FB76D-58FA-4AED-9DF9-033E994AE000","name":"swap-vertical","codepoint":"F04E2","aliases":["import-export","arrow-up-down"],"tags":["Arrow"],"author":"Google","version":"1.5.54"},{"id":"0903A829-EB64-4B39-B066-FECF7908DA8A","name":"swap-vertical-bold","codepoint":"F0BCE","aliases":["arrow-up-down-bold","import-export-bold"],"tags":["Arrow"],"author":"Google","version":"3.0.39"},{"id":"F47E2ADA-9203-4D5A-9537-D0C93E45F1B3","name":"swap-vertical-circle","codepoint":"F0FE3","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"3B14BF34-4B82-4CAD-8F11-55E4013F7734","name":"swap-vertical-circle-outline","codepoint":"F0FE4","aliases":[],"tags":["Arrow"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"FC1C62DB-A06D-48F8-962F-F60FE41E4F65","name":"swap-vertical-variant","codepoint":"F08C2","aliases":["swap-calls"],"tags":["Arrow"],"author":"Google","version":"2.2.43"},{"id":"668BF75C-2B3B-46CB-8731-AE6BF10244BD","name":"swim","codepoint":"F04E3","aliases":[],"tags":["Sport"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A2ED8CF0-EAE1-4B83-9469-448260288DDE","name":"switch","codepoint":"F04E4","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D73618B2-062C-40B2-BF8D-43DC48809F9B","name":"sword","codepoint":"F04E5","aliases":[],"tags":["Gaming \/ RPG"],"author":"Austin Andrews","version":"1.5.54"},{"id":"37B336A5-5827-4929-93B5-C12373966731","name":"sword-cross","codepoint":"F0787","aliases":[],"tags":["Gaming \/ RPG"],"author":"Michael Richins","version":"1.9.32"},{"id":"9201098E-A360-4BF2-8EC7-683EB2AA7FEF","name":"syllabary-hangul","codepoint":"F1333","aliases":["writing-system-hangul"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"8B8AF349-F9B5-483B-90CC-387F3791AF69","name":"syllabary-hiragana","codepoint":"F1334","aliases":["writing-system-hiragana"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"220577A0-1D92-46EA-8116-DF964F6C57F0","name":"syllabary-katakana","codepoint":"F1335","aliases":["writing-system-katakana"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"BEDFC0D3-5AC2-46E4-BD69-07048CC47710","name":"syllabary-katakana-halfwidth","codepoint":"F1336","aliases":["writing-system-katakana-half-width"],"tags":["Alpha \/ Numeric"],"author":"Haley Halcyon","version":"4.9.95"},{"id":"6A604429-C9A6-45F3-8042-D29AB7828789","name":"symbol","codepoint":"F1501","aliases":[],"tags":[],"author":"Haley Halcyon","version":"5.4.55"},{"id":"2BCCEE64-583D-4EC7-9BBA-72FF58354181","name":"symfony","codepoint":"F0AE6","aliases":[],"tags":[],"author":"Contributors","version":"2.7.94"},{"id":"E8CE455E-8C08-48F4-B989-8D91E185E8AE","name":"sync","codepoint":"F04E6","aliases":["loop","counterclockwise-arrows","circular-arrows","circle-arrows"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"66A07118-4C78-44D0-8B73-930144C74BD1","name":"sync-alert","codepoint":"F04E7","aliases":["sync-warning","sync-problem"],"tags":["Alert \/ Error"],"author":"Google","version":"1.5.54"},{"id":"26250B6D-8879-4DAA-8DFA-A04738E855FE","name":"sync-circle","codepoint":"F1378","aliases":[],"tags":[],"author":"Fran\u00e7ois Risoud","version":"4.9.95"},{"id":"538457F5-44DB-404B-92FE-5FB8597B258E","name":"sync-off","codepoint":"F04E8","aliases":["sync-disabled"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"76D6AAA9-7D7F-4C7A-818E-D9947744A23C","name":"tab","codepoint":"F04E9","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BA5FCCBE-ED06-4819-B2F3-532034AB09BB","name":"tab-minus","codepoint":"F0B4B","aliases":[],"tags":[],"author":"Michael Richins","version":"2.8.94"},{"id":"9E23B225-E972-4369-A94A-C2AAF4C93870","name":"tab-plus","codepoint":"F075C","aliases":["tab-add"],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"D851AFED-34E5-4166-9923-CC4A5D6A1A44","name":"tab-remove","codepoint":"F0B4C","aliases":[],"tags":[],"author":"Michael Richins","version":"2.8.94"},{"id":"9A9059F0-CADA-47EF-82DC-4B1FB2B9E4C5","name":"tab-unselected","codepoint":"F04EA","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"984D8348-AB61-4DD8-838C-3F2542577F73","name":"table","codepoint":"F04EB","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"4E3E7C78-5217-4B8A-8B95-9DE8433CFADA","name":"table-account","codepoint":"F13B9","aliases":["table-user"],"tags":["Account \/ User"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"5957DCA4-9A4D-4BC1-98EC-58065564EBFF","name":"table-alert","codepoint":"F13BA","aliases":[],"tags":["Alert \/ Error"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"846F0539-E30D-40E8-BC00-3F10A0C0321E","name":"table-arrow-down","codepoint":"F13BB","aliases":["table-download"],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"44768ACF-C1A3-477D-91BC-74DA3B0A746E","name":"table-arrow-left","codepoint":"F13BC","aliases":["table-import"],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"A4A68FD7-82B8-4BE8-8110-DA54D1A888D4","name":"table-arrow-right","codepoint":"F13BD","aliases":["table-share","table-export"],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"2A9EE017-5EDD-4A0B-A531-E552D4C8AB66","name":"table-arrow-up","codepoint":"F13BE","aliases":["table-upload"],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"4AB13D38-7B5C-49E6-B41C-C48C0F8E7DA3","name":"table-border","codepoint":"F0A18","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.5.94"},{"id":"989D1B4B-5D28-4335-B410-8DAF917F788F","name":"table-cancel","codepoint":"F13BF","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"6EB52FC2-32D9-427D-80DE-32C60C8F78AD","name":"table-chair","codepoint":"F1061","aliases":["restaurant","kitchen","dining"],"tags":["Home Automation"],"author":"Michael Richins","version":"4.1.95"},{"id":"15FE548D-D08F-44C4-AF25-B853452E1AFE","name":"table-check","codepoint":"F13C0","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"8C3DCF5F-7E50-48A6-A596-0BA2D299B37F","name":"table-clock","codepoint":"F13C1","aliases":[],"tags":["Date \/ Time"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"540E0DD7-BA28-46B1-A0A7-2A0820E73432","name":"table-cog","codepoint":"F13C2","aliases":["table-settings"],"tags":["Settings"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"D45D7513-AA4C-43CA-8435-CA6AD2B7F868","name":"table-column","codepoint":"F0835","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.1.19"},{"id":"0EB91CE4-3223-4799-9BB7-3BA0C923BC40","name":"table-column-plus-after","codepoint":"F04EC","aliases":["table-column-add-after"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"67B4875F-B08F-4006-AFE1-9C243F8B873A","name":"table-column-plus-before","codepoint":"F04ED","aliases":["table-column-add-before"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"455B9D6F-1842-434F-8C31-16F68A2C1BA9","name":"table-column-remove","codepoint":"F04EE","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"2343FF2B-E5D3-4BEC-90EA-FB3F5291D4B0","name":"table-column-width","codepoint":"F04EF","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DDC0FFBC-73D2-49E8-8B8C-22D65A5719A6","name":"table-edit","codepoint":"F04F0","aliases":[],"tags":["Edit \/ Modify","Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6F81B89D-EBF1-41BF-9619-90E148AD9951","name":"table-eye","codepoint":"F1094","aliases":[],"tags":[],"author":"Terren","version":"4.2.95"},{"id":"2F3C45C9-277B-4751-8F5C-4356739AC3A4","name":"table-eye-off","codepoint":"F13C3","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"9A7A9F69-9BC4-4619-981D-DF8423A22FF2","name":"table-furniture","codepoint":"F05BC","aliases":[],"tags":[],"author":"nilsfast","version":"1.5.54"},{"id":"9AB8E55A-A51C-4384-A6C6-1F88BFBBD63B","name":"table-headers-eye","codepoint":"F121D","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"2F8C23A5-717B-4483-9C22-A8C5D4F7C31A","name":"table-headers-eye-off","codepoint":"F121E","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"550B70E0-414F-44F5-A09F-DF418ABB7D26","name":"table-heart","codepoint":"F13C4","aliases":["table-favorite"],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"8B04C6AF-6886-4693-8806-6C4BC8D60E9A","name":"table-key","codepoint":"F13C5","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"99BE0AB4-A123-4745-839F-DC355DA8C3D4","name":"table-large","codepoint":"F04F1","aliases":[],"tags":["Text \/ Content \/ Format","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3C206937-03CF-4690-B022-30099AEAE0F3","name":"table-large-plus","codepoint":"F0F87","aliases":["table-large-add"],"tags":["Text \/ Content \/ Format","Geographic Information System"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"E6F6EF7E-C78C-4670-9E96-43AD92F24429","name":"table-large-remove","codepoint":"F0F88","aliases":[],"tags":["Text \/ Content \/ Format","Geographic Information System"],"author":"Michael Irigoyen","version":"3.9.97"},{"id":"370E7D91-6ACA-464F-A30C-DCB35B8DFC55","name":"table-lock","codepoint":"F13C6","aliases":[],"tags":["Lock"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"BE891E33-2018-4619-BF4C-C006B4063785","name":"table-merge-cells","codepoint":"F09A6","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Google","version":"2.4.85"},{"id":"C40DA2CA-4FCA-4144-AD38-0DD457D6D6CF","name":"table-minus","codepoint":"F13C7","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"FB123A84-A0AE-41F6-8C61-B86E93EEA08C","name":"table-multiple","codepoint":"F13C8","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"94745B4E-14D8-4B8C-B8C4-E25D1A123B27","name":"table-network","codepoint":"F13C9","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"70A0953D-9FEF-4858-8ACB-A90C5613360A","name":"table-of-contents","codepoint":"F0836","aliases":["toc"],"tags":[],"author":"Google","version":"2.1.19"},{"id":"AF58D08D-14CD-41F6-9CF1-53D002D7EEB1","name":"table-off","codepoint":"F13CA","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"68ABC903-3D76-4C38-8165-4DB5F0353A20","name":"table-picnic","codepoint":"F1743","aliases":[],"tags":[],"author":"Jeff Hilnbrand","version":"5.9.55"},{"id":"4547E3CF-042C-431F-8B99-4DBE22F1ADEC","name":"table-plus","codepoint":"F0A75","aliases":["table-add"],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"202CC1A0-B339-493E-99B0-607A209E8A53","name":"table-refresh","codepoint":"F13A0","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"E04307B8-EA93-41C0-B7B8-6AAC6C9B580F","name":"table-remove","codepoint":"F0A76","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"8EA23E11-D670-4D09-8AA6-7DAFBEAA54FD","name":"table-row","codepoint":"F0837","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"2.1.19"},{"id":"5B9A6186-2C24-4D16-9FE4-F0E23C8E5B5F","name":"table-row-height","codepoint":"F04F2","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"0B2B45F7-3597-4049-9643-9E972826F67C","name":"table-row-plus-after","codepoint":"F04F3","aliases":["table-row-add-after"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"784BF375-370F-4DAE-985D-7BEF2FDA6951","name":"table-row-plus-before","codepoint":"F04F4","aliases":["table-row-add-before"],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"017D1949-234A-4C27-A653-FF0EAF33AD92","name":"table-row-remove","codepoint":"F04F5","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6053118D-7921-45FC-BC83-9F08BF2AE6DF","name":"table-search","codepoint":"F090F","aliases":[],"tags":[],"author":"Michael Richins","version":"2.3.50"},{"id":"B506843C-4832-4F30-8266-9B02632AB582","name":"table-settings","codepoint":"F0838","aliases":[],"tags":["Settings"],"author":"Contributors","version":"2.1.19"},{"id":"6E502BA0-5D71-4607-BA94-CDEF31BBF07C","name":"table-split-cell","codepoint":"F142A","aliases":[],"tags":["Text \/ Content \/ Format"],"author":"Contributors","version":"5.2.45"},{"id":"646B67D0-16F5-429C-93ED-C57131031B63","name":"table-star","codepoint":"F13CB","aliases":["table-favorite"],"tags":[],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"DEC516BA-2102-4CE7-B77E-6D95A9A525EC","name":"table-sync","codepoint":"F13A1","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.0.45"},{"id":"4E13AA68-FF88-415B-A813-A9D5023F71E3","name":"table-tennis","codepoint":"F0E68","aliases":[],"tags":["Sport"],"author":"Google","version":"3.6.95"},{"id":"703B639C-E17D-40F1-8025-2B2950B1961D","name":"tablet","codepoint":"F04F6","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"179831B0-F175-4694-9313-3B745C133F96","name":"tablet-android","codepoint":"F04F7","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"804E3CCD-99B5-4F54-898A-9477D69E6951","name":"tablet-cellphone","codepoint":"F09A7","aliases":["mobile-devices","tablet-mobile-phone","tablet-smartphone"],"tags":["Cellphone \/ Phone","Device \/ Tech"],"author":"Google","version":"2.4.85"},{"id":"71DAA530-D02E-45D9-84AB-68CE1CD1E44E","name":"tablet-dashboard","codepoint":"F0ECE","aliases":[],"tags":["Device \/ Tech"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"A7147BE3-0B04-4B61-94F3-48B0D9C5551E","name":"tablet-ipad","codepoint":"F04F8","aliases":["tablet-mac"],"tags":["Device \/ Tech"],"author":"Google","version":"1.5.54","deprecated":true},{"id":"9E259FF6-513C-44B0-BB10-7F930DFA47DD","name":"taco","codepoint":"F0762","aliases":[],"tags":["Food \/ Drink"],"author":"Austin Andrews","version":"1.9.32"},{"id":"0BE85AB2-0D51-411C-B119-789E9E317216","name":"tag","codepoint":"F04F9","aliases":["local-offer"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"141B8C02-DA96-4054-AA99-C83CF2B10118","name":"tag-arrow-down","codepoint":"F172B","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"8C304479-B37A-4837-8887-F4880359C9BB","name":"tag-arrow-down-outline","codepoint":"F172C","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"56E3ECFD-CE76-4CE2-9075-7673ABEA78D1","name":"tag-arrow-left","codepoint":"F172D","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"BCD665AC-5B08-4E99-8BF4-7F43030447F6","name":"tag-arrow-left-outline","codepoint":"F172E","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"98AEA4C4-D0E2-4B94-9EE3-47F97A7AFC0D","name":"tag-arrow-right","codepoint":"F172F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"B9FED1D0-B219-4483-A30E-AA201561DCB4","name":"tag-arrow-right-outline","codepoint":"F1730","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"5040B027-3283-413C-8424-E2E02108E69D","name":"tag-arrow-up","codepoint":"F1731","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"A632F2B8-4D1B-4F60-AB06-EB79D45E13A3","name":"tag-arrow-up-outline","codepoint":"F1732","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.9.55"},{"id":"5DCE0F4D-F740-4D9A-AC93-281D3477E9AF","name":"tag-faces","codepoint":"F04FA","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"2D9E735C-EA23-4EB2-9AC4-C92D69218577","name":"tag-heart","codepoint":"F068B","aliases":["loyalty"],"tags":[],"author":"Google","version":"1.7.12"},{"id":"1A877919-79F5-4B22-A309-6681E10B4A06","name":"tag-heart-outline","codepoint":"F0BCF","aliases":[],"tags":[],"author":"Google","version":"3.0.39"},{"id":"1F2E41E2-6509-4C1B-B95B-145C9A8375DA","name":"tag-minus","codepoint":"F0910","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.3.50"},{"id":"E8EF5D5C-B3EE-459C-9C6D-B6A045B8052C","name":"tag-minus-outline","codepoint":"F121F","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"408AB5A3-F100-4175-96CD-8602BE101150","name":"tag-multiple","codepoint":"F04FB","aliases":["tags"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"340D1192-13CE-4752-86C3-186FEA8DC315","name":"tag-multiple-outline","codepoint":"F12F7","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"A85425D5-61FC-46C8-B604-4105C407967B","name":"tag-off","codepoint":"F1220","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"E6157F0C-1143-4F4D-B308-CCA13CC24BFC","name":"tag-off-outline","codepoint":"F1221","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"2022546E-45D4-4AC5-B24F-6D6AAEA0F452","name":"tag-outline","codepoint":"F04FC","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"83C0C7C5-26FF-4EF7-A05B-B05472FC40FC","name":"tag-plus","codepoint":"F0722","aliases":["tag-add"],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"0BCB9F00-8D30-4DD7-85CB-31930035DF0E","name":"tag-plus-outline","codepoint":"F1222","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"E90C088F-8DFD-4B7D-962C-BE2DD9DB61BD","name":"tag-remove","codepoint":"F0723","aliases":[],"tags":[],"author":"Michael Richins","version":"1.8.36"},{"id":"DD1E4B8E-E8C2-4B72-A56D-F42B3259AD49","name":"tag-remove-outline","codepoint":"F1223","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"92B97B44-052D-48B5-993F-1AB16F76DC65","name":"tag-text","codepoint":"F1224","aliases":[],"tags":[],"author":"Michael Richins","version":"4.6.95"},{"id":"8ED927D3-84B9-43D1-82B4-3859653006D6","name":"tag-text-outline","codepoint":"F04FD","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"7D58F2F1-A97E-4EBE-A0E6-E8F9999F1799","name":"tailwind","codepoint":"F13FF","aliases":[],"tags":[],"author":"Contributors","version":"5.1.45"},{"id":"C673D464-FC7A-4574-8EE6-6CCF7E39902F","name":"tank","codepoint":"F0D3A","aliases":[],"tags":[],"author":"Contributors","version":"3.3.92"},{"id":"E7134093-7DFD-48A0-A687-299B70E6D42D","name":"tanker-truck","codepoint":"F0FE5","aliases":["fuel-truck","oil-truck","water-truck","tanker"],"tags":["Transportation + Road"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"76B2D13C-4AA4-4AA1-A0CA-F4E5CA53FFE2","name":"tape-drive","codepoint":"F16DF","aliases":[],"tags":[],"author":"Contributors","version":"5.8.55"},{"id":"C9C3F657-65A6-418E-91EF-E6FD8F0357C1","name":"tape-measure","codepoint":"F0B4D","aliases":["measuring-tape"],"tags":["Hardware \/ Tools"],"author":"GreenTurtwig","version":"2.8.94"},{"id":"363D29C5-9F0F-43EA-BE7E-D1C2C1418517","name":"target","codepoint":"F04FE","aliases":["registration-mark"],"tags":[],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"9B5EC357-642F-4790-BD58-E45A217DD9B9","name":"target-account","codepoint":"F0BD0","aliases":["crosshairs-account","target-user"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"3.0.39"},{"id":"C8208D76-55E5-41A2-9540-AF3731D16D74","name":"target-variant","codepoint":"F0A77","aliases":["registration-mark"],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"32F3835A-EBD0-4927-9497-6F67F7075EAF","name":"taxi","codepoint":"F04FF","aliases":["local-taxi","cab"],"tags":["Transportation + Road","Navigation"],"author":"Google","version":"1.5.54"},{"id":"D1759BBF-821F-4902-AAF5-8323A179912F","name":"tea","codepoint":"F0D9E","aliases":[],"tags":["Food \/ Drink"],"author":"Google","version":"3.4.93"},{"id":"002B1000-5D8B-4EC1-9D10-21E9EE62EE4C","name":"tea-outline","codepoint":"F0D9F","aliases":[],"tags":["Food \/ Drink"],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"A989F68B-23B9-4B50-BE4D-E3DF6E9420C9","name":"teach","codepoint":"F0890","aliases":["teacher","teaching","lecture","college","blackboard","whiteboard","human-male-board"],"tags":[],"author":"Michael Richins","version":"2.1.99"},{"id":"3335C183-CD35-4D66-87AB-C5E3A7FCAFBF","name":"teamviewer","codepoint":"F0500","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"47F1C290-ED78-4459-B33C-6E2ACC867CC6","name":"telegram","codepoint":"F0501","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54","deprecated":true},{"id":"66FE04C6-5941-4728-A256-17F9B25534F1","name":"telescope","codepoint":"F0B4E","aliases":[],"tags":["Science"],"author":"SarinManS","version":"2.8.94"},{"id":"1B699A99-578E-450C-9523-934F4D281F72","name":"television","codepoint":"F0502","aliases":["tv"],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"09374787-27B8-43D7-92CA-B35050B1FA63","name":"television-ambient-light","codepoint":"F1356","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.9.95"},{"id":"CB446614-AE63-403E-BBF8-0B0ED3E367AE","name":"television-box","codepoint":"F0839","aliases":["tv-box","tv-guide"],"tags":[],"author":"Google","version":"2.1.19"},{"id":"EB7FD483-EAF9-4FEE-8B82-25186D26827A","name":"television-classic","codepoint":"F07F4","aliases":["tv-classic"],"tags":["Device \/ Tech","Home Automation"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"C8E89001-2566-4676-B12B-7AAFAFCA0276","name":"television-classic-off","codepoint":"F083A","aliases":["tv-classic-off"],"tags":["Device \/ Tech","Home Automation"],"author":"Austin Andrews","version":"2.1.19"},{"id":"9132E544-8FAA-43BA-98B4-8D752CB3E251","name":"television-clean","codepoint":"F1110","aliases":[],"tags":["Device \/ Tech"],"author":"Contributors","version":"4.3.95"},{"id":"6E5CAF6F-F00B-4613-B520-BDC1E5DD2832","name":"television-guide","codepoint":"F0503","aliases":[],"tags":["Device \/ Tech","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9E9D949B-13EC-43FB-9068-2BED76224BD8","name":"television-off","codepoint":"F083B","aliases":["tv-off"],"tags":["Device \/ Tech","Home Automation"],"author":"Austin Andrews","version":"2.1.19"},{"id":"EE3F2E38-D8CD-42BD-B50F-187A77FBC630","name":"television-pause","codepoint":"F0F89","aliases":[],"tags":["Device \/ Tech"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"BFCE431D-2F97-4023-A690-F34199CA79F8","name":"television-play","codepoint":"F0ECF","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"3.7.94"},{"id":"52228864-9BDD-4D12-82EC-AF730D68E47B","name":"television-stop","codepoint":"F0F8A","aliases":[],"tags":["Device \/ Tech"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"A94E333D-F8C5-4726-B81A-6DDF4CC37FD0","name":"temperature-celsius","codepoint":"F0504","aliases":["temperature-centigrade"],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9A1DF8BB-627A-47C9-B609-BAC145D320DF","name":"temperature-fahrenheit","codepoint":"F0505","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DF9D47EE-157B-4E1E-85CE-A043E5F2AE51","name":"temperature-kelvin","codepoint":"F0506","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CE166270-170C-4292-8D6F-FE787AF6B021","name":"tennis","codepoint":"F0DA0","aliases":["tennis-racquet","tennis-racket"],"tags":["Sport"],"author":"Google","version":"3.4.93"},{"id":"DE92B1F1-31FB-4551-84A2-32F5B5D842EC","name":"tennis-ball","codepoint":"F0507","aliases":[],"tags":["Sport"],"author":"Google","version":"1.5.54"},{"id":"688277DE-082A-4BE2-8E59-129245E02DD7","name":"tent","codepoint":"F0508","aliases":["camping"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"D3339724-6ECB-4328-83C8-7E956C0271C0","name":"terraform","codepoint":"F1062","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"4.1.95"},{"id":"1F98A781-6023-4368-AC06-5A421D166FCC","name":"terrain","codepoint":"F0509","aliases":[],"tags":["Nature"],"author":"Google","version":"1.5.54"},{"id":"0B88F54B-7522-4D7D-85EC-3C0C3E7D36FE","name":"test-tube","codepoint":"F0668","aliases":[],"tags":["Science"],"author":"Kai Faust","version":"1.6.50"},{"id":"A6F17875-0B9B-467B-85F5-4C4804D3A367","name":"test-tube-empty","codepoint":"F0911","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"2.3.50"},{"id":"8B2E6A86-9CC3-4F9B-8B77-F5DD9BAE7898","name":"test-tube-off","codepoint":"F0912","aliases":[],"tags":["Science"],"author":"Austin Andrews","version":"2.3.50"},{"id":"E56EAB24-6D70-49E0-BEC8-D9164A93CB63","name":"text","codepoint":"F09A8","aliases":["notes"],"tags":[],"author":"Google","version":"2.4.85"},{"id":"15B2BA3F-53A2-4151-9B90-20000264FE54","name":"text-account","codepoint":"F1570","aliases":["biography","text-user"],"tags":["Account \/ User"],"author":"Brooke Clifton","version":"5.5.55"},{"id":"32E03B3D-EAFA-4483-AE94-E43944F0F0AE","name":"text-box","codepoint":"F021A","aliases":["drive-document","file-document-box"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"291424C4-8874-4D0D-8D89-0C3349C021ED","name":"text-box-check","codepoint":"F0EA6","aliases":["file-document-box-tick","file-document-box-check"],"tags":["Files \/ Folders"],"author":"Contributors","version":"3.7.94"},{"id":"A24C1161-73F2-43F0-B955-7D4E5F398372","name":"text-box-check-outline","codepoint":"F0EA7","aliases":["file-document-box-tick-outline","file-document-box-check-outline"],"tags":["Files \/ Folders"],"author":"Contributors","version":"3.7.94"},{"id":"60E9BECF-1FDF-4077-9BD7-F7B1863C2F66","name":"text-box-minus","codepoint":"F0EA8","aliases":["file-document-box-minus"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"89E44C7C-4A52-4BBE-8EF4-2127A320E444","name":"text-box-minus-outline","codepoint":"F0EA9","aliases":["file-document-box-minus-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"3F7FCD03-4E12-4D4D-AB63-C8D51F938284","name":"text-box-multiple","codepoint":"F0AB7","aliases":["file-document-boxes","file-document-box-multiple"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"02EF54D9-4D5D-463C-A3E8-0B44BDCB9523","name":"text-box-multiple-outline","codepoint":"F0AB8","aliases":["file-document-boxes-outline","file-document-box-multiple-outline"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"2.7.94"},{"id":"E12AE178-0546-4CD3-81F6-BD1F17AA50EE","name":"text-box-outline","codepoint":"F09ED","aliases":["file-document-box-outline"],"tags":["Files \/ Folders"],"author":"GreenTurtwig","version":"2.5.94"},{"id":"8979EEB0-B475-4229-A7D8-F5D48A58DB85","name":"text-box-plus","codepoint":"F0EAA","aliases":["file-document-box-plus"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"467C2198-D7C5-4B95-88F1-71B269D2AEAC","name":"text-box-plus-outline","codepoint":"F0EAB","aliases":["file-document-box-plus-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"B599787B-9A9F-45C1-AD76-45FB4B00EFFC","name":"text-box-remove","codepoint":"F0EAC","aliases":["file-document-box-remove"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"C822984D-33BC-4A48-A9A3-E679ABF13595","name":"text-box-remove-outline","codepoint":"F0EAD","aliases":["file-document-box-remove-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"08B85EF9-81EC-4DEE-B1C7-1C14D4CBECA5","name":"text-box-search","codepoint":"F0EAE","aliases":["file-document-box-search"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"3.7.94"},{"id":"D32F390E-2888-4C63-99FA-9662902B6694","name":"text-box-search-outline","codepoint":"F0EAF","aliases":["file-document-box-search-outline"],"tags":["Files \/ Folders"],"author":"Austin Andrews","version":"3.7.94"},{"id":"8F37BBCB-35D2-4FAF-88ED-59252659885D","name":"text-recognition","codepoint":"F113D","aliases":[],"tags":[],"author":"Haley Halcyon","version":"4.4.95"},{"id":"3C1714C4-ACE1-45F2-ADE8-D90DD2E9742C","name":"text-search","codepoint":"F13B8","aliases":[],"tags":[],"author":"Austin Andrews","version":"5.1.45"},{"id":"4595BB97-16B7-4B19-8AC5-9C33167A6D20","name":"text-shadow","codepoint":"F0669","aliases":[],"tags":[],"author":"Simran","version":"1.6.50"},{"id":"F80F249A-898B-4690-888A-EC11F79B4E56","name":"text-short","codepoint":"F09A9","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"CA8CE1CF-1F6E-4B8B-9972-B3F36E865E67","name":"text-subject","codepoint":"F09AA","aliases":[],"tags":[],"author":"Google","version":"2.4.85"},{"id":"5B1FA77D-0384-4931-AFD8-C4FF5D73D372","name":"text-to-speech","codepoint":"F050A","aliases":["tts","microphone-message"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"1AE8F7A9-5454-44D2-B16D-1D383E33978D","name":"text-to-speech-off","codepoint":"F050B","aliases":["tts-off","microphone-message-off"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E3A06403-51B5-4D00-9349-53517553A324","name":"texture","codepoint":"F050C","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"7B46F16A-AF86-4A7A-B3AB-1D2297831078","name":"texture-box","codepoint":"F0FE6","aliases":["surface-area"],"tags":["Math"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"37350655-CB4D-4D9F-8C90-B8049CA0E48E","name":"theater","codepoint":"F050D","aliases":["cinema","theatre"],"tags":["Places"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AE66BEF4-7040-4A15-8BF3-639B116853CC","name":"theme-light-dark","codepoint":"F050E","aliases":["sun-moon-stars"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"F41863ED-B66A-4FF4-B436-0876C8D3665B","name":"thermometer","codepoint":"F050F","aliases":["temperature"],"tags":["Weather","Home Automation","Automotive"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DB3D5088-E7A7-47AD-87E3-43D5B41BF0C2","name":"thermometer-alert","codepoint":"F0E01","aliases":["thermometer-warning","temperature-alert","temperature-warning"],"tags":["Home Automation","Weather","Alert \/ Error"],"author":"Michael Richins","version":"3.5.94"},{"id":"C888E2C1-306A-4BCB-821E-5B33AC93572D","name":"thermometer-chevron-down","codepoint":"F0E02","aliases":["temperature-chevron-down","temperature-decrease","thermometer-decrease"],"tags":["Home Automation","Weather"],"author":"Michael Richins","version":"3.5.94"},{"id":"79E7C071-7AEE-48B1-802E-922925E94247","name":"thermometer-chevron-up","codepoint":"F0E03","aliases":["temperature-chevron-up","temperature-increase","thermometer-increase"],"tags":["Home Automation","Weather"],"author":"Michael Richins","version":"3.5.94"},{"id":"DF51BF5D-831D-4FD1-8786-498CAC97DBB6","name":"thermometer-high","codepoint":"F10C2","aliases":["temperature-high"],"tags":["Home Automation","Weather"],"author":"Michael Richins","version":"4.2.95"},{"id":"A9FC898C-8CC5-44F2-822D-05C5625E95C8","name":"thermometer-lines","codepoint":"F0510","aliases":["temperature-lines"],"tags":["Weather","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DBD8C754-85C4-43C4-BEA8-BCFEDB30B382","name":"thermometer-low","codepoint":"F10C3","aliases":["temperature-low"],"tags":["Home Automation","Weather"],"author":"Michael Richins","version":"4.2.95"},{"id":"310F50E9-D74E-4753-A6D8-60EDBFC332B7","name":"thermometer-minus","codepoint":"F0E04","aliases":["temperature-minus","thermometer-decrease","temperature-decrease"],"tags":["Home Automation","Weather"],"author":"Michael Richins","version":"3.5.94"},{"id":"BF73A396-DB1C-46BC-8078-3CF0D7E0277F","name":"thermometer-off","codepoint":"F1531","aliases":["temperature-off"],"tags":["Weather"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"511387A0-FD3A-4335-B82E-9C68E02BABDD","name":"thermometer-plus","codepoint":"F0E05","aliases":["thermometer-add","thermometer-increase","temperature-plus","temperature-add","temperature-increase"],"tags":["Home Automation","Weather"],"author":"Michael Richins","version":"3.5.94"},{"id":"628D16E2-7E57-43CA-8451-012B8AB852DA","name":"thermostat","codepoint":"F0393","aliases":["nest"],"tags":["Device \/ Tech","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"E0A6898F-3F08-4E13-8B61-DA63E5CBF949","name":"thermostat-box","codepoint":"F0891","aliases":[],"tags":["Home Automation","Device \/ Tech"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"46ACA864-4B1C-4DBD-94FB-7A0D6B9A500E","name":"thought-bubble","codepoint":"F07F6","aliases":["comic-bubble","thinking"],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"2C82E0CA-9872-431C-8739-0EA33825EBF7","name":"thought-bubble-outline","codepoint":"F07F7","aliases":["comic-thought-bubble-outline","thinking-outline","think-outline"],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"83D606E3-69A1-4583-854D-5C44477D038D","name":"thumb-down","codepoint":"F0511","aliases":["dislike","thumbs-down"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"00EE8027-00FE-43B8-ACEC-7779E39D6E29","name":"thumb-down-outline","codepoint":"F0512","aliases":["dislike-outline","thumbs-down-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"C32E4FC9-F3DC-4C67-81FB-62648E3F1AB5","name":"thumb-up","codepoint":"F0513","aliases":["like","thumbs-up"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BFA3B3A3-0D00-459A-8BDB-DAC2D4233023","name":"thumb-up-outline","codepoint":"F0514","aliases":["like-outline","thumbs-up-outline"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"C38D6CEC-4D8E-44DB-B704-9A76552733D4","name":"thumbs-up-down","codepoint":"F0515","aliases":["like-dislike"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"18F55984-07FD-4630-BB11-8285F83AA838","name":"ticket","codepoint":"F0516","aliases":["local-activity","local-play","local-attraction"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DE2E8A6C-33F1-4148-A228-C512C26B3159","name":"ticket-account","codepoint":"F0517","aliases":["ticket-user"],"tags":["Account \/ User"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F19DA1EC-CBDA-456E-BC19-F03C635C886F","name":"ticket-confirmation","codepoint":"F0518","aliases":["confirmation-number"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A1B45743-22F5-49E8-B466-120024F2C4C3","name":"ticket-confirmation-outline","codepoint":"F13AA","aliases":["confirmation-number-outline"],"tags":[],"author":"Google","version":"5.0.45"},{"id":"6D7F0E99-A86F-4AAB-A468-F1D3214E1B60","name":"ticket-outline","codepoint":"F0913","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.3.50"},{"id":"297864D0-935F-4EF0-9A2C-28F018544581","name":"ticket-percent","codepoint":"F0724","aliases":["coupon","voucher"],"tags":[],"author":"GreenTurtwig","version":"1.8.36"},{"id":"43EDCFCF-4AFB-45E7-8F83-56CC40FC93B7","name":"ticket-percent-outline","codepoint":"F142B","aliases":["coupon-outline","voucher-outline"],"tags":[],"author":"\u00d6zg\u00fcr G\u00f6rg\u00fcl\u00fc","version":"5.2.45"},{"id":"475062F1-407D-43B6-8FBF-1E0D4C7D690C","name":"tie","codepoint":"F0519","aliases":[],"tags":["Clothing"],"author":"Austin Andrews","version":"1.5.54"},{"id":"708986EE-2BC9-401D-8ACD-0BC5A3E20EA3","name":"tilde","codepoint":"F0725","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"348DB89A-B4E2-4CB9-A7A4-B86973243ADE","name":"timelapse","codepoint":"F051A","aliases":[],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"087D891A-1B90-42FA-97E4-9381D8D7CCF8","name":"timeline","codepoint":"F0BD1","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"3965A310-F8FE-4077-8DAB-722CF2A44E78","name":"timeline-alert","codepoint":"F0F95","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"3.9.97"},{"id":"E6B39705-7058-4C26-BE2B-D85FAF69F614","name":"timeline-alert-outline","codepoint":"F0F98","aliases":[],"tags":["Alert \/ Error"],"author":"Austin Andrews","version":"3.9.97"},{"id":"56EABFF0-9689-4078-98F6-8E0EDAAD6A19","name":"timeline-check","codepoint":"F1532","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"0A75C1CB-0AF6-4A5E-BBE2-C14C31DDBBB6","name":"timeline-check-outline","codepoint":"F1533","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"2671B127-348C-47F5-B016-F30389D649CF","name":"timeline-clock","codepoint":"F11FB","aliases":[],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"4.6.95"},{"id":"2C73EA7B-CAD0-439D-8D8F-8779B100F927","name":"timeline-clock-outline","codepoint":"F11FC","aliases":[],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"4.6.95"},{"id":"92637DDF-E9A3-43E1-986D-DA5DE7FA8CDE","name":"timeline-help","codepoint":"F0F99","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.9.97"},{"id":"E844C160-56F3-431B-B971-00178D4B5D59","name":"timeline-help-outline","codepoint":"F0F9A","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.9.97"},{"id":"4086C75B-4BB4-4307-A953-22F4F7AEDE9F","name":"timeline-minus","codepoint":"F1534","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"E984C3EB-C8F3-4357-BAA4-93F9ED3049BC","name":"timeline-minus-outline","codepoint":"F1535","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"82363A48-4E61-4594-A3DA-AA94FBBA4BE8","name":"timeline-outline","codepoint":"F0BD2","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"6DDA8E22-8819-4EA4-A239-57349E7B1C7C","name":"timeline-plus","codepoint":"F0F96","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.9.97"},{"id":"230196A7-AFE4-4722-810C-B845246A42A8","name":"timeline-plus-outline","codepoint":"F0F97","aliases":[],"tags":[],"author":"Austin Andrews","version":"3.9.97"},{"id":"1855D5A7-8C35-4621-BFFB-E10D9F0C0726","name":"timeline-remove","codepoint":"F1536","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"748EF30E-992C-41C9-94DA-A95F4F80A4EF","name":"timeline-remove-outline","codepoint":"F1537","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"DBC01596-0759-4095-9BAA-3D582324A836","name":"timeline-text","codepoint":"F0BD3","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"F949D410-50B0-49DD-B4CE-E2FA9160052F","name":"timeline-text-outline","codepoint":"F0BD4","aliases":[],"tags":[],"author":"Michael Richins","version":"3.0.39"},{"id":"7F6AFDDE-8C90-44FB-A000-D5F6EF93A943","name":"timer","codepoint":"F13AB","aliases":["stopwatch"],"tags":["Sport"],"author":"Michael Irigoyen","version":"5.0.45"},{"id":"BDC89918-A38F-41C6-997E-DE9F779D4435","name":"timer-10","codepoint":"F051C","aliases":["timer-ten"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"3DEFEFB6-57CE-4C82-9D0C-16DBDBEF5950","name":"timer-3","codepoint":"F051D","aliases":["timer-three"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"CC698648-1A71-4EC8-A1E3-B5ACC42F2FDB","name":"timer-off","codepoint":"F13AC","aliases":["stopwatch-off"],"tags":[],"author":"Michael Irigoyen","version":"5.0.45"},{"id":"BE74C70B-7E47-4E25-957C-C83CFEB73D6D","name":"timer-off-outline","codepoint":"F051E","aliases":["stopwatch-off-outline"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"017E0965-CD2E-4B39-B0C5-410335848B12","name":"timer-outline","codepoint":"F051B","aliases":["stopwatch-outline"],"tags":["Date \/ Time"],"author":"Google","version":"1.5.54"},{"id":"64EFBA89-F8CB-4193-8656-A83CCBC66A76","name":"timer-sand","codepoint":"F051F","aliases":["hourglass"],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DD31FFF2-A93B-41F5-BA6C-1732E8A8DEFF","name":"timer-sand-empty","codepoint":"F06AD","aliases":["hourglass-empty"],"tags":["Date \/ Time"],"author":"Google","version":"1.7.12"},{"id":"E603301B-7DF4-43C2-9035-0DDB2A50B88E","name":"timer-sand-full","codepoint":"F078C","aliases":["hourglass-full"],"tags":["Date \/ Time"],"author":"Google","version":"1.9.32"},{"id":"F06ED6E0-0EB1-4B39-8E85-1A82A273F473","name":"timetable","codepoint":"F0520","aliases":[],"tags":["Date \/ Time"],"author":"Austin Andrews","version":"1.5.54"},{"id":"5042FF4E-78E5-43D5-B992-1AAEAE51AB25","name":"toaster","codepoint":"F1063","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"4.1.95"},{"id":"97660B13-F700-455E-9C04-CACAC4450118","name":"toaster-off","codepoint":"F11B7","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"BA8D8327-7F94-4BB9-8199-9C012BAAF549","name":"toaster-oven","codepoint":"F0CD3","aliases":[],"tags":["Home Automation","Food \/ Drink"],"author":"GreenTurtwig","version":"3.2.89"},{"id":"D1AD4F4E-3CFE-4F51-932D-D3942A26C418","name":"toggle-switch","codepoint":"F0521","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A54ADA14-0917-432E-9288-3364FBAEBCE2","name":"toggle-switch-off","codepoint":"F0522","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"1DCEDC73-941F-4412-B0B7-B7042888F91A","name":"toggle-switch-off-outline","codepoint":"F0A19","aliases":[],"tags":[],"author":"Google","version":"2.5.94"},{"id":"2645C66C-41C1-4536-9BB5-4530B8C8E89B","name":"toggle-switch-outline","codepoint":"F0A1A","aliases":[],"tags":[],"author":"Google","version":"2.5.94"},{"id":"5A1815F9-FC9E-4420-B723-AF4B324262A4","name":"toilet","codepoint":"F09AB","aliases":[],"tags":["Home Automation"],"author":"Augustin Ursu","version":"2.4.85"},{"id":"79D1B3B8-FC3E-4978-AA8E-C78A1360B880","name":"toolbox","codepoint":"F09AC","aliases":[],"tags":["Hardware \/ Tools"],"author":"Google","version":"2.4.85"},{"id":"F016813A-4390-482A-8FFF-D081FDD21362","name":"toolbox-outline","codepoint":"F09AD","aliases":["service-toolbox"],"tags":["Hardware \/ Tools"],"author":"Google","version":"2.4.85"},{"id":"CF5ABC25-55E6-4B19-B338-85F45926DEE1","name":"tools","codepoint":"F1064","aliases":["wrench","screwdriver"],"tags":["Hardware \/ Tools"],"author":"Michael Richins","version":"4.1.95"},{"id":"D6AD70EE-33F4-4C3A-8ED1-3CD3236222F8","name":"tooltip","codepoint":"F0523","aliases":[],"tags":["Tooltip"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CA087C29-F27F-4DBE-8617-1369C18DF51D","name":"tooltip-account","codepoint":"F000C","aliases":["tooltip-user","tooltip-person","account-location"],"tags":["Account \/ User","Tooltip"],"author":"Google","version":"1.5.54"},{"id":"B2FDABD3-4E66-461C-8DC0-10D9A18441B8","name":"tooltip-check","codepoint":"F155C","aliases":[],"tags":["Tooltip"],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"255D95B4-1A63-408F-9CED-17AE2D05F38B","name":"tooltip-check-outline","codepoint":"F155D","aliases":[],"tags":["Tooltip"],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"C1684CDD-9C71-4A10-B3BA-5B26706B3B28","name":"tooltip-edit","codepoint":"F0524","aliases":[],"tags":["Tooltip","Edit \/ Modify"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"B9D8D642-EFDD-4AFF-B1CD-86AB7E914347","name":"tooltip-edit-outline","codepoint":"F12C5","aliases":[],"tags":["Edit \/ Modify","Tooltip"],"author":"Michael Irigoyen","version":"4.8.95"},{"id":"1DF33E50-EBEA-4A62-8455-84C28271C8D2","name":"tooltip-image","codepoint":"F0525","aliases":[],"tags":["Tooltip"],"author":"Austin Andrews","version":"1.5.54"},{"id":"9E49D099-C7CD-42A3-BFA1-8AC8966898B5","name":"tooltip-image-outline","codepoint":"F0BD5","aliases":[],"tags":["Tooltip"],"author":"Austin Andrews","version":"3.0.39"},{"id":"A8D3907B-9528-4EB0-AB75-EA6013F042F1","name":"tooltip-minus","codepoint":"F155E","aliases":[],"tags":["Tooltip"],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"674242D7-81B2-4C9E-BC60-3F96AD379C52","name":"tooltip-minus-outline","codepoint":"F155F","aliases":[],"tags":["Tooltip"],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"C14A3C70-357F-4AE8-963C-B45ED543A4DB","name":"tooltip-outline","codepoint":"F0526","aliases":[],"tags":["Tooltip"],"author":"Austin Andrews","version":"1.5.54"},{"id":"E1ED044C-BD73-4844-A33D-7ED9A1D232F5","name":"tooltip-plus","codepoint":"F0BD6","aliases":["tooltip-add"],"tags":["Tooltip"],"author":"Austin Andrews","version":"3.0.39"},{"id":"CAA5F3A3-2044-48AC-94CA-04899F9459ED","name":"tooltip-plus-outline","codepoint":"F0527","aliases":["tooltip-outline-plus","tooltip-add-outline"],"tags":["Tooltip"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A54A45EF-9C4B-4AFB-8734-610B14D521A5","name":"tooltip-remove","codepoint":"F1560","aliases":[],"tags":["Tooltip"],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"192D99F7-B04B-476A-B638-70F27A7FF1E6","name":"tooltip-remove-outline","codepoint":"F1561","aliases":[],"tags":["Tooltip"],"author":"Colton Wiscombe","version":"5.5.55"},{"id":"B608ACE2-279D-4C66-9169-32BD86BDF5F3","name":"tooltip-text","codepoint":"F0528","aliases":[],"tags":["Tooltip"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B0E2F01D-A8A8-4945-A0C2-FB1866C2C1F2","name":"tooltip-text-outline","codepoint":"F0BD7","aliases":[],"tags":["Tooltip"],"author":"Austin Andrews","version":"3.0.39"},{"id":"486D33E1-B181-40D4-B088-BBB49221B91F","name":"tooth","codepoint":"F08C3","aliases":["dentist"],"tags":["Medical \/ Hospital"],"author":"Christopher Schreiner","version":"2.2.43"},{"id":"BFD05B50-CF42-49C4-B76D-447DB0AEFEEE","name":"tooth-outline","codepoint":"F0529","aliases":[],"tags":[],"author":"Christopher Schreiner","version":"1.5.54"},{"id":"1BA32EF0-94A2-4F7E-BD93-5A9102143F8E","name":"toothbrush","codepoint":"F1129","aliases":["dentist","oral-hygiene"],"tags":["Medical \/ Hospital"],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"6CC31B35-04D6-4883-A0CF-3CD35E81AB98","name":"toothbrush-electric","codepoint":"F112C","aliases":["dentist","oral-hygiene"],"tags":["Medical \/ Hospital"],"author":"Simran","version":"4.4.95"},{"id":"E06A1B1A-ACE7-43AD-BC75-5C3191D0AB1D","name":"toothbrush-paste","codepoint":"F112A","aliases":["dentist","oral-hygiene"],"tags":["Medical \/ Hospital"],"author":"Simran","version":"4.3.95"},{"id":"5E37234B-E874-4FB7-AC74-BD836129C433","name":"torch","codepoint":"F1606","aliases":["olympics"],"tags":["Sport"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"E66ECEE5-0382-4406-B0AB-CFE819AE7684","name":"tortoise","codepoint":"F0D3B","aliases":[],"tags":[],"author":"Nick","version":"3.3.92"},{"id":"207A1D36-F4A1-4ACB-B588-7BEA51C2E285","name":"toslink","codepoint":"F12B8","aliases":["optical-audio"],"tags":["Audio"],"author":"Michael Irigoyen","version":"4.7.95"},{"id":"E2623132-7507-4FFD-8382-E192DDC62D17","name":"tournament","codepoint":"F09AE","aliases":["bracket"],"tags":["Gaming \/ RPG","Sport"],"author":"GreenTurtwig","version":"2.4.85"},{"id":"BC8926AA-02C6-4755-B5A8-D3BD29C2CDE0","name":"tow-truck","codepoint":"F083C","aliases":["auto-towing","truck"],"tags":["Transportation + Road"],"author":"Google","version":"2.1.19"},{"id":"70D21CFE-DC3C-4615-9524-4CD2F2FDC44E","name":"tower-beach","codepoint":"F0681","aliases":[],"tags":[],"author":"Thomas Hunsaker","version":"1.7.12"},{"id":"11E0C03B-7522-4247-B0D3-F04AE1ECB166","name":"tower-fire","codepoint":"F0682","aliases":[],"tags":[],"author":"Thomas Hunsaker","version":"1.7.12"},{"id":"DDCE3E75-1E43-45A9-8D94-E24CFD8284B0","name":"toy-brick","codepoint":"F1288","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"602DF6D1-21C6-4540-960D-79D7C37AECF9","name":"toy-brick-marker","codepoint":"F1289","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"6EE7FD45-3389-4007-A362-0EDB4B9DF9BD","name":"toy-brick-marker-outline","codepoint":"F128A","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"03BB26E3-61C3-4FCF-9532-056FC8DC1E4D","name":"toy-brick-minus","codepoint":"F128B","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"BA71CE05-DEA6-4638-AF5C-2194D6FB946E","name":"toy-brick-minus-outline","codepoint":"F128C","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"E178F91C-A54C-41B1-892F-F17A96283D14","name":"toy-brick-outline","codepoint":"F128D","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"9426C325-5C35-40D8-9CA4-DA230CCC2736","name":"toy-brick-plus","codepoint":"F128E","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"A710B239-7C1A-4BDE-B337-AFEF3CD9E067","name":"toy-brick-plus-outline","codepoint":"F128F","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"F5773738-AE3C-423C-8B64-6C951B9A4B3A","name":"toy-brick-remove","codepoint":"F1290","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"497261EB-0B21-4829-8659-1B1EB39043D1","name":"toy-brick-remove-outline","codepoint":"F1291","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"AEED3DA4-5EAF-4630-BA5B-6E4675E29FA1","name":"toy-brick-search","codepoint":"F1292","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"86074918-B854-4C06-AAD5-C02EA910A6A2","name":"toy-brick-search-outline","codepoint":"F1293","aliases":["lego","plugin","extension"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"6BF0AEDF-F822-460F-8CEB-AEF0D83815F5","name":"track-light","codepoint":"F0914","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"C06AFD8C-C769-41B1-8E5C-355CE5DBEE8E","name":"trackpad","codepoint":"F07F8","aliases":[],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"92AB470E-CDB3-43F8-A299-D32C94043D83","name":"trackpad-lock","codepoint":"F0933","aliases":[],"tags":["Lock"],"author":"Simran","version":"2.3.54"},{"id":"D5993895-5ECF-4B4A-8C84-7E3D9C1F6ADB","name":"tractor","codepoint":"F0892","aliases":["farm"],"tags":["Agriculture","Transportation + Road"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"C80B9924-A19D-440E-8543-E1E232FAA90B","name":"tractor-variant","codepoint":"F14C4","aliases":["agriculture"],"tags":["Agriculture"],"author":"Google","version":"5.3.45"},{"id":"E1849947-175A-4347-BFC7-D8C7811F0B2B","name":"trademark","codepoint":"F0A78","aliases":["tm"],"tags":[],"author":"Michael Irigoyen","version":"2.6.95"},{"id":"BA597840-6D3A-4D89-B8DC-63C5B2DA6638","name":"traffic-cone","codepoint":"F137C","aliases":[],"tags":["Transportation + Road"],"author":"Michael Richins","version":"4.9.95"},{"id":"073B4489-5787-432C-9D10-50B270182D34","name":"traffic-light","codepoint":"F052B","aliases":[],"tags":["Transportation + Road"],"author":"Google","version":"1.5.54"},{"id":"B6E1232A-3A43-4200-BE34-1BC436B34BF1","name":"train","codepoint":"F052C","aliases":["directions-railway","locomotive","railroad"],"tags":["Navigation","Transportation + Other"],"author":"Google","version":"1.5.54"},{"id":"20588836-2EC7-467D-9E72-15D3C4FE7C93","name":"train-car","codepoint":"F0BD8","aliases":["commute","transportation","travel"],"tags":["Transportation + Other"],"author":"Google","version":"3.0.39"},{"id":"04821E67-5037-46E7-8F5E-740C7EBFAC1D","name":"train-car-passenger","codepoint":"F1733","aliases":[],"tags":["Transportation + Other"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"9F9E31CB-361B-40D6-8754-157401124ED2","name":"train-car-passenger-door","codepoint":"F1734","aliases":[],"tags":["Transportation + Other"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"042CE4C4-087F-49EC-9F67-A5467318C068","name":"train-car-passenger-door-open","codepoint":"F1735","aliases":[],"tags":["Transportation + Other"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"1A9FFFAE-5581-4E22-B87C-3798A9E97FD1","name":"train-car-passenger-variant","codepoint":"F1736","aliases":[],"tags":["Transportation + Other"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"C0A4E604-3829-4605-A7BC-CA0BFF138B18","name":"train-variant","codepoint":"F08C4","aliases":["locomotive-variant","railroad-variant"],"tags":["Transportation + Other"],"author":"Google","version":"2.2.43"},{"id":"13AE3C37-5323-4FE6-86F7-3B30B635969F","name":"tram","codepoint":"F052D","aliases":[],"tags":["Navigation","Transportation + Other"],"author":"Google","version":"1.5.54"},{"id":"BEB0D58A-A99B-40FE-9E6C-C81218E683F8","name":"tram-side","codepoint":"F0FE7","aliases":[],"tags":["Transportation + Other"],"author":"Google","version":"4.0.96"},{"id":"6DD88A18-582D-400D-A5AB-12996F26A05D","name":"transcribe","codepoint":"F052E","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"2D2FB32D-B253-4D3E-BA04-7AD5D5FE2C2E","name":"transcribe-close","codepoint":"F052F","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E9B887E6-76B3-45D5-8F69-43982EE59423","name":"transfer","codepoint":"F1065","aliases":[],"tags":[],"author":"Simran","version":"4.1.95"},{"id":"D4CB36CD-4F30-45BE-940D-CC2AFFCA078A","name":"transfer-down","codepoint":"F0DA1","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"3.4.93"},{"id":"03FA1C8F-8808-4293-A12A-7D9B7F8890D4","name":"transfer-left","codepoint":"F0DA2","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"3.4.93"},{"id":"D2895587-8DBA-4EDC-8624-3A32C20AB638","name":"transfer-right","codepoint":"F0530","aliases":[],"tags":["Arrow"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A7928BA3-AC13-42A2-9AC2-5AFBD60E3243","name":"transfer-up","codepoint":"F0DA3","aliases":[],"tags":["Arrow"],"author":"Michael Richins","version":"3.4.93"},{"id":"370C931A-E40F-4950-B9CE-87D337720400","name":"transit-connection","codepoint":"F0D3C","aliases":[],"tags":["Transportation + Other","Navigation"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"5F428B0A-E91D-48E5-8896-0CE072C919E4","name":"transit-connection-horizontal","codepoint":"F1546","aliases":[],"tags":["Transportation + Other"],"author":"Jeff Hilnbrand","version":"5.4.55"},{"id":"9E27C6FE-B44C-4A92-BDD7-A546A4F83E9D","name":"transit-connection-variant","codepoint":"F0D3D","aliases":[],"tags":["Transportation + Other","Navigation"],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"247F5D41-FA03-4D63-97AF-B39A4D4A7BFC","name":"transit-detour","codepoint":"F0F8B","aliases":[],"tags":["Transportation + Other","Navigation"],"author":"Contributors","version":"3.9.97"},{"id":"A52E6E56-7AE7-45E3-B854-A2DF41F3141B","name":"transit-skip","codepoint":"F1515","aliases":[],"tags":["Transportation + Other"],"author":"Jeff Hilnbrand","version":"5.4.55"},{"id":"CE6451FA-EF46-40B4-B87B-BCF93DDE6E54","name":"transit-transfer","codepoint":"F06AE","aliases":["transfer-within-a-station"],"tags":["Transportation + Other","Navigation"],"author":"Google","version":"1.7.12"},{"id":"2650CA0F-8423-4DE2-A821-9D7D1E5547C0","name":"transition","codepoint":"F0915","aliases":["animation","motion","translate"],"tags":[],"author":"Google","version":"2.3.50"},{"id":"D254EE82-37CA-4897-BE12-6FD0ED708E38","name":"transition-masked","codepoint":"F0916","aliases":["masked-transitions"],"tags":[],"author":"Google","version":"2.3.50"},{"id":"4486DD26-4110-457E-BBD7-B5D19DF72E4E","name":"translate","codepoint":"F05CA","aliases":["language"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"B65945C4-51D4-464A-985F-E6F9995BE40D","name":"translate-off","codepoint":"F0E06","aliases":[],"tags":[],"author":"Contributors","version":"3.5.94"},{"id":"DBA97655-B2ED-4FA6-95E0-02E7273549C9","name":"transmission-tower","codepoint":"F0D3E","aliases":["pylon","powerline"],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"260712C5-252B-484C-B5A7-33827BBC5487","name":"trash-can","codepoint":"F0A79","aliases":["delete","rubbish-bin","trashcan","garbage-can"],"tags":[],"author":"GreenTurtwig","version":"2.6.95"},{"id":"A586B5B1-1D48-4BC8-B31C-F8E93DC8CD49","name":"trash-can-outline","codepoint":"F0A7A","aliases":["delete-outline","rubbish-bin-outline","trashcan-outline","garbage-can-outline"],"tags":[],"author":"GreenTurtwig","version":"2.6.95"},{"id":"F9A7F6AA-7379-4215-A97A-0E2FCAF3A9ED","name":"tray","codepoint":"F1294","aliases":["queue","printer","inbox"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"A1CCEE33-5CCA-43B9-B056-23F3EAFBE506","name":"tray-alert","codepoint":"F1295","aliases":["queue","printer","inbox"],"tags":["Alert \/ Error"],"author":"Michael Richins","version":"4.7.95"},{"id":"B81435D3-9FE4-470D-A46A-7FEDA1773D15","name":"tray-full","codepoint":"F1296","aliases":["queue","printer","inbox"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"F7F07C92-4531-466D-AC3E-F7822D2FDFBD","name":"tray-minus","codepoint":"F1297","aliases":["queue","printer","inbox"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"BF55355C-56CC-4C1F-9136-D92AA0800706","name":"tray-plus","codepoint":"F1298","aliases":["queue","printer","inbox"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"FACF04CD-2633-47EC-97BE-59A3341289C3","name":"tray-remove","codepoint":"F1299","aliases":["queue","printer","inbox"],"tags":[],"author":"Michael Richins","version":"4.7.95"},{"id":"A0678E6D-C3D3-42AB-B9E7-C1B12D368B70","name":"treasure-chest","codepoint":"F0726","aliases":[],"tags":["Gaming \/ RPG"],"author":"Alex Efremo","version":"1.8.36"},{"id":"58E298BD-F32E-420D-9E55-BDB44D583AB7","name":"tree","codepoint":"F0531","aliases":["plant"],"tags":["Nature"],"author":"Austin Andrews","version":"1.5.54"},{"id":"81548212-EBFA-48B0-B0EB-D95EB5C0CC91","name":"tree-outline","codepoint":"F0E69","aliases":["plant"],"tags":["Nature"],"author":"Simran","version":"3.6.95"},{"id":"25CA8276-A876-459D-B203-C81C58F88342","name":"trello","codepoint":"F0532","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"ACC5BB4D-9439-472F-9DD5-F026FF36D023","name":"trending-down","codepoint":"F0533","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"A39F489B-ABB1-4420-A6DC-20AF0E2CF6DA","name":"trending-neutral","codepoint":"F0534","aliases":["trending-flat"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"4277434D-74AD-48E7-9C5F-BB7226C4FC39","name":"trending-up","codepoint":"F0535","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"78EC62FE-EC63-407F-BCF3-92C441398DDA","name":"triangle","codepoint":"F0536","aliases":[],"tags":["Shape"],"author":"Simran","version":"1.5.54"},{"id":"74A6BF3E-CEC2-40C3-A900-109D5E05E218","name":"triangle-outline","codepoint":"F0537","aliases":[],"tags":["Shape"],"author":"Simran","version":"1.5.54"},{"id":"59CAC75D-7028-4672-9EC2-1B9E797BA9D1","name":"triangle-wave","codepoint":"F147C","aliases":[],"tags":["Audio"],"author":"Haley Halcyon","version":"5.2.45"},{"id":"835C3AA9-800B-4767-BDED-97FB875B19DF","name":"triforce","codepoint":"F0BD9","aliases":["zelda"],"tags":["Gaming \/ RPG"],"author":"Contributors","version":"3.0.39"},{"id":"0B9368A1-FC31-4D0D-8909-C2D44DCC0B83","name":"trophy","codepoint":"F0538","aliases":["achievement"],"tags":["Sport"],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"39F70CE8-5C56-4AAB-A4F7-93F871B1CB96","name":"trophy-award","codepoint":"F0539","aliases":["achievement-award"],"tags":["Sport"],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"3AC48F23-1321-4B8E-80D7-B050CCBA0255","name":"trophy-broken","codepoint":"F0DA4","aliases":[],"tags":["Sport"],"author":"Contributors","version":"3.4.93"},{"id":"D7B01958-C212-49B9-B58B-146B4017348C","name":"trophy-outline","codepoint":"F053A","aliases":["achievement-outline"],"tags":["Sport"],"author":"Simran","version":"1.5.54"},{"id":"C6664923-EE26-4175-90CB-AD87B517F2FF","name":"trophy-variant","codepoint":"F053B","aliases":["achievement-variant"],"tags":["Sport"],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"C3A5133F-0462-40DB-863A-3659FC5DFE0E","name":"trophy-variant-outline","codepoint":"F053C","aliases":["achievement-variant-outline"],"tags":["Sport"],"author":"Simran","version":"1.5.54"},{"id":"A0B91DEA-DB9A-4737-B2F4-26B805B88648","name":"truck","codepoint":"F053D","aliases":["lorry","local-shipping","courier"],"tags":["Transportation + Road"],"author":"Google","version":"1.5.54"},{"id":"39C645BD-15AE-42BE-B571-5744CB77E97D","name":"truck-check","codepoint":"F0CD4","aliases":["truck-tick","lorry-check","courier-check"],"tags":[],"author":"Austin Andrews","version":"3.2.89"},{"id":"BCEE78F4-69D9-40FC-8174-D299610C0690","name":"truck-check-outline","codepoint":"F129A","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"D0EB091D-C62C-4A93-9AE4-AE942F5738C7","name":"truck-delivery","codepoint":"F053E","aliases":["lorry-delivery"],"tags":["Transportation + Road"],"author":"Simran","version":"1.5.54"},{"id":"E65E8E41-4516-4C25-B3C1-F6B71894B5B2","name":"truck-delivery-outline","codepoint":"F129B","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"401AC514-6441-4DDC-80DC-48CF851C5B5E","name":"truck-fast","codepoint":"F0788","aliases":["lorry-fast","courier-fast"],"tags":["Transportation + Road"],"author":"Austin Andrews","version":"1.9.32"},{"id":"42696369-BAF9-4854-A57D-355F89630929","name":"truck-fast-outline","codepoint":"F129C","aliases":[],"tags":[],"author":"Austin Andrews","version":"4.7.95"},{"id":"09111629-7960-46BA-A70E-DC85128E4F4A","name":"truck-outline","codepoint":"F129D","aliases":[],"tags":[],"author":"Google","version":"4.7.95"},{"id":"6F488FA3-B882-443D-8619-0124217E267C","name":"truck-trailer","codepoint":"F0727","aliases":[],"tags":["Transportation + Road"],"author":"Michael Richins","version":"1.8.36"},{"id":"CCE02F94-2930-488B-A39C-17A8DD8BE591","name":"trumpet","codepoint":"F1096","aliases":[],"tags":["Music"],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"E46BD04B-78BF-4243-8608-46930051A694","name":"tshirt-crew","codepoint":"F0A7B","aliases":["t-shirt-crew"],"tags":["Clothing"],"author":"Michael Richins","version":"2.6.95"},{"id":"6B67D149-AE33-40CF-997F-C57A7ECB8D42","name":"tshirt-crew-outline","codepoint":"F053F","aliases":["t-shirt-crew-outline"],"tags":["Clothing"],"author":"Austin Andrews","version":"1.5.54"},{"id":"618A5FB1-7308-4C2B-BCE1-461BA9DBFD13","name":"tshirt-v","codepoint":"F0A7C","aliases":["t-shirt-v"],"tags":["Clothing"],"author":"Michael Richins","version":"2.6.95"},{"id":"94791D5D-EEC5-4562-98DD-DF285E972EC8","name":"tshirt-v-outline","codepoint":"F0540","aliases":["t-shirt-v-outline"],"tags":["Clothing"],"author":"Austin Andrews","version":"1.5.54"},{"id":"7796F195-34DA-4CAA-8F58-1179343EFB18","name":"tumble-dryer","codepoint":"F0917","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"D21E17B9-0D84-4C21-977C-D1056E934449","name":"tumble-dryer-alert","codepoint":"F11BA","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"E9DC2320-5FD4-403B-8445-9EB68B4468B6","name":"tumble-dryer-off","codepoint":"F11BB","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"B1F7C2ED-4017-4162-A4C7-31D8761D8DC3","name":"tune","codepoint":"F062E","aliases":["mixer-settings","equaliser","settings"],"tags":["Settings","Audio"],"author":"Google","version":"1.6.50"},{"id":"B0AFC3B0-B718-407F-A51C-F4D932D7FCB2","name":"tune-variant","codepoint":"F1542","aliases":["settings","equalizer"],"tags":["Audio"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"AB147073-9D20-4DA1-A108-3856FC1764C1","name":"tune-vertical","codepoint":"F066A","aliases":["equaliser-vertical","instant-mix","settings-vertical","mixer-settings-vertical"],"tags":["Settings","Audio"],"author":"Google","version":"1.6.50"},{"id":"FF706504-28DF-4752-BD75-E50FFE794421","name":"tune-vertical-variant","codepoint":"F1543","aliases":["settings-vertical","equalizer-vertical"],"tags":["Audio"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"2BD0CF2B-70B8-4CFB-9350-A613C189EE7D","name":"turkey","codepoint":"F171B","aliases":["thanksgiving"],"tags":["Animal","Holiday"],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"40E06CC0-82EE-4EE0-976B-C6388BBFDD9D","name":"turnstile","codepoint":"F0CD5","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"22E6056D-46AF-4249-93DF-D0D5465DD6CA","name":"turnstile-outline","codepoint":"F0CD6","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"36BB53AA-DFB4-46DB-AAD7-FE4D266D8EC7","name":"turtle","codepoint":"F0CD7","aliases":[],"tags":["Animal"],"author":"Nick","version":"3.2.89"},{"id":"8BA5EB2D-7C4F-4336-8994-20CAA433BB26","name":"twitch","codepoint":"F0543","aliases":[],"tags":["Social Media","Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"A95F7C7C-DE85-4564-BA65-DEDCF3BE105A","name":"twitter","codepoint":"F0544","aliases":[],"tags":["Brand \/ Logo","Social Media"],"author":"Contributors","version":"1.5.54"},{"id":"2788034C-2A06-46C0-82B9-A34CB23C88E0","name":"twitter-retweet","codepoint":"F0547","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"B4BC8D17-225E-44B1-A44F-3A6DC21C9A7B","name":"two-factor-authentication","codepoint":"F09AF","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.4.85"},{"id":"C5841F2E-EFD9-4589-BDB1-554DFE6A623C","name":"typewriter","codepoint":"F0F2D","aliases":[],"tags":[],"author":"Michael Richins","version":"3.8.95"},{"id":"F8C3B22E-D72C-4A1C-BCB8-A24CBB3CAF46","name":"ubisoft","codepoint":"F0BDA","aliases":["uplay"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"3.0.39"},{"id":"D0B38B4B-389B-49A8-9797-BE1092231DE9","name":"ubuntu","codepoint":"F0548","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"D2609FE7-60FE-4372-94A9-7BB3C7AD18DE","name":"ufo","codepoint":"F10C4","aliases":["unidentified-flying-object","alien"],"tags":[],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"A0C08D07-838C-426F-8EA5-EBCA5C117684","name":"ufo-outline","codepoint":"F10C5","aliases":["unidentified-flying-object-outline","alien"],"tags":[],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"A7C08392-F82F-4910-8D0F-6A1907AE19E3","name":"ultra-high-definition","codepoint":"F07F9","aliases":["uhd"],"tags":["Video \/ Movie"],"author":"Austin Andrews","version":"2.0.46"},{"id":"EB029748-89CF-4E75-BBC9-9747BEF7AE29","name":"umbraco","codepoint":"F0549","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"6E7A679E-94FE-4BBD-931F-59B9F25B54EE","name":"umbrella","codepoint":"F054A","aliases":[],"tags":["Weather"],"author":"Simran","version":"1.5.54"},{"id":"591C025F-58CC-4E5D-9D63-FB43A8B7BA78","name":"umbrella-closed","codepoint":"F09B0","aliases":[],"tags":["Weather"],"author":"Simran","version":"2.4.85"},{"id":"4B483491-948F-4126-9041-DE8D3A4A9A10","name":"umbrella-closed-outline","codepoint":"F13E2","aliases":[],"tags":["Weather"],"author":"Simran","version":"5.1.45"},{"id":"B17B3489-56A4-490D-828E-61A64754EB1A","name":"umbrella-closed-variant","codepoint":"F13E1","aliases":[],"tags":["Weather"],"author":"Moma Design Studio","version":"5.1.45"},{"id":"7E42C11A-74C3-4C0F-BE6B-9794F343925A","name":"umbrella-outline","codepoint":"F054B","aliases":[],"tags":["Weather"],"author":"Simran","version":"1.5.54"},{"id":"C9D6F6DE-E9F7-4AC9-B9F1-41160A4C2B0E","name":"undo","codepoint":"F054C","aliases":["arrow"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"C262C766-4474-4BC5-AE66-23E5735F86F1","name":"undo-variant","codepoint":"F054D","aliases":["arrow"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"E533CB7E-48C2-4D9D-B935-B51C918703C0","name":"unfold-less-horizontal","codepoint":"F054E","aliases":["chevron-down-up","collapse-horizontal"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"E4DFDADF-60F8-4E90-A501-38381F4346A0","name":"unfold-less-vertical","codepoint":"F0760","aliases":["chevron-right-left","collapse-vertical"],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"E85F4170-11D3-4757-8247-17EBD07A08D4","name":"unfold-more-horizontal","codepoint":"F054F","aliases":["chevron-up-down","expand-horizontal"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"AE8D43D2-00EC-46D9-A21C-4D0024A539D7","name":"unfold-more-vertical","codepoint":"F0761","aliases":["chevron-left-right","expand-vertical"],"tags":[],"author":"Austin Andrews","version":"1.9.32"},{"id":"87E56CEE-67B1-427E-9A28-303F8B6D29A7","name":"ungroup","codepoint":"F0550","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0A232580-AB10-422D-B5B0-D0F4EFE7AD6A","name":"unicode","codepoint":"F0ED0","aliases":[],"tags":[],"author":"Contributors","version":"3.7.94"},{"id":"B3A5FE32-259C-4FBA-B6EB-A4A1CE7590DE","name":"unicorn","codepoint":"F15C2","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"D0825387-637B-4EB5-BCF5-470A7FCE1F05","name":"unicorn-variant","codepoint":"F15C3","aliases":[],"tags":["Animal"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"A0632550-1C97-49AF-B0B3-463625A8C3FB","name":"unicycle","codepoint":"F15E5","aliases":[],"tags":["Sport","Transportation + Other"],"author":"Colton Wiscombe","version":"5.6.55"},{"id":"50CFC57C-9C70-4953-BDC4-F6340EB7A243","name":"unity","codepoint":"F06AF","aliases":[],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"1.7.12"},{"id":"4AC79EF3-5BCA-41EC-976E-CB821416A905","name":"unreal","codepoint":"F09B1","aliases":["unreal-engine"],"tags":["Brand \/ Logo","Gaming \/ RPG"],"author":"Contributors","version":"2.4.85"},{"id":"BC7B3CEA-B4D3-4F52-8378-5ACF408A3D9B","name":"untappd","codepoint":"F0551","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"1B274396-AAE7-4CD8-8D57-27E31D915F68","name":"update","codepoint":"F06B0","aliases":["clockwise","clock-arrow"],"tags":["Date \/ Time"],"author":"Google","version":"1.7.12"},{"id":"08F8FCE9-67A0-4696-9B83-0B1F11EA959E","name":"upload","codepoint":"F0552","aliases":["file-upload"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"961ECD2E-2849-42C0-909A-5431B0273DA0","name":"upload-lock","codepoint":"F1373","aliases":[],"tags":["Lock"],"author":"Michael Richins","version":"4.9.95"},{"id":"AB9A1FD5-FAAC-4E6F-8B6D-D642D7066E96","name":"upload-lock-outline","codepoint":"F1374","aliases":[],"tags":["Lock"],"author":"Michael Richins","version":"4.9.95"},{"id":"2B1A438E-4795-43D1-B4FD-3997C8E1BA9F","name":"upload-multiple","codepoint":"F083D","aliases":["uploads"],"tags":[],"author":"Michael Richins","version":"2.1.19"},{"id":"B473675B-DF1E-4450-B85E-786B483C9FA4","name":"upload-network","codepoint":"F06F6","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.8.36"},{"id":"279E2BEC-B829-49A3-A9C5-0FC58781975C","name":"upload-network-outline","codepoint":"F0CD8","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.2.89"},{"id":"B6A90F94-944A-4B64-B551-1163605C6A30","name":"upload-off","codepoint":"F10C6","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"432A3BF4-56B2-4567-890C-F60CE8CE2F34","name":"upload-off-outline","codepoint":"F10C7","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.2.95"},{"id":"02F82A66-CEB3-4F54-825A-811342975170","name":"upload-outline","codepoint":"F0E07","aliases":["file-upload-outline"],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"25033E0B-3AD4-414D-9972-559F2690FC1D","name":"usb","codepoint":"F0553","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DB728530-EAF2-488E-8971-9567A31354DE","name":"usb-flash-drive","codepoint":"F129E","aliases":[],"tags":[],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"9FD568CE-B873-45FC-8F8A-8D8172FB4C7E","name":"usb-flash-drive-outline","codepoint":"F129F","aliases":[],"tags":[],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"B271CD5A-6340-440A-896E-6A53BAE3B685","name":"usb-port","codepoint":"F11F0","aliases":[],"tags":[],"author":"GreenTurtwig","version":"4.5.95"},{"id":"304B1BC9-DF83-41FF-B0F9-1FF4D83A95CB","name":"valve","codepoint":"F1066","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"4.1.95"},{"id":"753E83CB-F6D2-4162-B3B4-6D2B8E0DC642","name":"valve-closed","codepoint":"F1067","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"4.1.95"},{"id":"E9E77FBB-F72A-4A82-9565-6BE2885D5138","name":"valve-open","codepoint":"F1068","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"4.1.95"},{"id":"293262AA-69E7-4D04-B441-AAA13D22C63C","name":"van-passenger","codepoint":"F07FA","aliases":[],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"517A8F96-14C9-4FAB-8AC2-27321C91E1BF","name":"van-utility","codepoint":"F07FB","aliases":["van-candy"],"tags":["Transportation + Road"],"author":"GreenTurtwig","version":"2.0.46"},{"id":"437A175D-CA2F-44C9-9FA0-A59A43E7C590","name":"vanish","codepoint":"F07FC","aliases":[],"tags":[],"author":"ginlime","version":"2.0.46"},{"id":"2BEF3471-36F9-4813-AC45-3C3FF9FC329C","name":"vanish-quarter","codepoint":"F1554","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"5.5.55"},{"id":"D8231C86-FA8B-4450-96FC-5C2820DD7DCC","name":"vanity-light","codepoint":"F11E1","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"4.5.95"},{"id":"6D34F114-FA91-4815-8148-A4C6B3BF128C","name":"variable","codepoint":"F0AE7","aliases":[],"tags":["Developer \/ Languages","Math"],"author":"Michael Richins","version":"2.7.94"},{"id":"AAC0D31F-ABF0-4A36-862E-BAEF2979E243","name":"variable-box","codepoint":"F1111","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.3.95"},{"id":"576A1B80-550B-46BD-90A6-A497D8A29BC5","name":"vector-arrange-above","codepoint":"F0554","aliases":[],"tags":["Vector","Arrange","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"C2EC8280-2EFC-44F4-BA6D-89DE72F06CA3","name":"vector-arrange-below","codepoint":"F0555","aliases":[],"tags":["Vector","Arrange","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"1D649850-7C33-41FE-8FBA-E6DFAB384AEC","name":"vector-bezier","codepoint":"F0AE8","aliases":[],"tags":["Vector"],"author":"Louistwee","version":"2.7.94"},{"id":"5C73E245-C6D4-42F0-A5D6-C14F53982661","name":"vector-circle","codepoint":"F0556","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"D5741976-7530-4859-97C1-F170BCE7C8B3","name":"vector-circle-variant","codepoint":"F0557","aliases":[],"tags":["Vector"],"author":"Simran","version":"1.5.54"},{"id":"7845F254-C78F-44D3-84E3-421B0B2AFF31","name":"vector-combine","codepoint":"F0558","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"546B7A4F-6D63-46CD-B74D-DEF09CE8D8FB","name":"vector-curve","codepoint":"F0559","aliases":["bezier"],"tags":["Vector","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"C4CA626C-23C3-495A-A73B-4B55A6FBC1F9","name":"vector-difference","codepoint":"F055A","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"9D39AD1D-F643-43EF-B55B-6CF2EC4637EC","name":"vector-difference-ab","codepoint":"F055B","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"A327D00A-F451-4B88-AEBA-EA87016806CB","name":"vector-difference-ba","codepoint":"F055C","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"EE98FF75-8AAA-4912-AFDE-6D5290FD6800","name":"vector-ellipse","codepoint":"F0893","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Austin Andrews","version":"2.1.99"},{"id":"DACB8CA9-A0A9-4766-B1A3-EC334425514A","name":"vector-intersection","codepoint":"F055D","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"8C2D4FBB-00B1-4815-971F-03F0788093C2","name":"vector-line","codepoint":"F055E","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"FC1F3637-2FBC-4A77-AB1F-FF74FE2B7D78","name":"vector-link","codepoint":"F0FE8","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"4.0.96"},{"id":"C8B18CF5-BD7E-41FC-A653-6B46D85F982A","name":"vector-point","codepoint":"F055F","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"6CD0A5FB-8FB8-45E7-9955-A876E4B2ABB4","name":"vector-polygon","codepoint":"F0560","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"1D1C3847-C645-42AE-A93C-DE1E64685762","name":"vector-polyline","codepoint":"F0561","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Contributors","version":"1.5.54"},{"id":"D2CE645F-5DC0-4E94-AD3C-346D59DD6AB1","name":"vector-polyline-edit","codepoint":"F1225","aliases":[],"tags":["Edit \/ Modify"],"author":"Contributors","version":"4.6.95"},{"id":"ADB52436-4BAD-40E2-8A13-48C76188FCE6","name":"vector-polyline-minus","codepoint":"F1226","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"EFE8791E-593A-4B6F-8EFE-553A00C8E5A4","name":"vector-polyline-plus","codepoint":"F1227","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"0B173B1A-A4BE-4B96-A33F-2C332150B5AE","name":"vector-polyline-remove","codepoint":"F1228","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"4.6.95"},{"id":"1B112A31-E2A7-4BAD-B1F1-5289B8811F08","name":"vector-radius","codepoint":"F074A","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Austin Andrews","version":"1.9.32"},{"id":"2A12555B-0CBC-4FC9-9F86-88F7785B3B2C","name":"vector-rectangle","codepoint":"F05C6","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"B7C380C9-13D8-4A0E-8EEC-1B4FB23F1FB9","name":"vector-selection","codepoint":"F0562","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"039be9b8-08ad-11e4-bf19-842b2b6cfe1b","name":"vector-square","codepoint":"F0001","aliases":["mdi"],"tags":["Vector","Geographic Information System"],"author":"Austin Andrews","version":"1.5.54"},{"id":"CE6EAE27-922A-48B9-83AF-5C333B20724F","name":"vector-triangle","codepoint":"F0563","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"2FD284B6-3DC1-4733-B08E-BAD459E87B87","name":"vector-union","codepoint":"F0564","aliases":[],"tags":["Vector","Geographic Information System"],"author":"Simran","version":"1.5.54"},{"id":"551637A8-2091-4439-9710-71199B7AC0C1","name":"vhs","codepoint":"F0A1B","aliases":["video-home-system","vhs-cassette","vhs-tape"],"tags":["Video \/ Movie"],"author":"GreenTurtwig","version":"2.5.94"},{"id":"68E64FD4-A020-4DEF-B2CB-5EA5BAA80E42","name":"vibrate","codepoint":"F0566","aliases":["vibration"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"36F2725C-4346-4EB3-9AA8-288DC3E27AFD","name":"vibrate-off","codepoint":"F0CD9","aliases":[],"tags":[],"author":"Michael Richins","version":"3.2.89"},{"id":"B1337ECC-EF1F-481B-9E75-6A8DB7A01BB9","name":"video","codepoint":"F0567","aliases":["videocam"],"tags":["Video \/ Movie","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"3F4D3E00-72CA-4167-A269-F9DD1A94540D","name":"video-3d","codepoint":"F07FD","aliases":[],"tags":["Video \/ Movie"],"author":"Austin Andrews","version":"2.0.46"},{"id":"F9B5EF59-C66B-445A-B37D-0CD3FDD5F47A","name":"video-3d-off","codepoint":"F13D9","aliases":[],"tags":["Video \/ Movie"],"author":"Contributors","version":"5.1.45"},{"id":"29FC25BE-88B2-4311-ACD7-F85EFB43D0E9","name":"video-3d-variant","codepoint":"F0ED1","aliases":[],"tags":["Video \/ Movie"],"author":"Contributors","version":"3.7.94"},{"id":"FD1999E4-4780-48E5-8F18-606871BA0581","name":"video-4k-box","codepoint":"F083E","aliases":["4k"],"tags":["Video \/ Movie"],"author":"Google","version":"2.1.19"},{"id":"F02BE782-F323-40E5-B245-DF7B6AFB2B15","name":"video-account","codepoint":"F0919","aliases":["video-user"],"tags":["Account \/ User","Video \/ Movie"],"author":"Google","version":"2.3.50"},{"id":"9E0AEA4A-7A90-43F7-8A7F-D49F374F11FF","name":"video-box","codepoint":"F00FD","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"A8AD0C27-54CD-4362-A862-C6865B1EE750","name":"video-box-off","codepoint":"F00FE","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"9E4CFE98-3E4E-4C70-B1F1-7316F21427E3","name":"video-check","codepoint":"F1069","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"206175B7-4215-412C-A30B-979BADCCCEE3","name":"video-check-outline","codepoint":"F106A","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"4.1.95"},{"id":"C8098652-E839-4E39-8465-8488B2D6502E","name":"video-high-definition","codepoint":"F152E","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"1A06058D-FA25-4AAE-A7C8-225CD0D79F06","name":"video-image","codepoint":"F091A","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"2.3.50"},{"id":"D7B7AA15-66CB-4AA5-AD75-E96B78B89AB9","name":"video-input-antenna","codepoint":"F083F","aliases":["settings-input-antenna"],"tags":["Video \/ Movie"],"author":"Google","version":"2.1.19"},{"id":"55F413A7-319D-4419-87D4-97FF9ED96791","name":"video-input-component","codepoint":"F0840","aliases":["video-input-composite","settings-input-component","settings-input-composite","video-input-ypbpr","rca"],"tags":["Video \/ Movie"],"author":"Google","version":"2.1.19"},{"id":"D371C4A6-40A8-4C03-95DA-2ACF2A5ABC4B","name":"video-input-hdmi","codepoint":"F0841","aliases":["settings-input-hdmi"],"tags":["Video \/ Movie"],"author":"Google","version":"2.1.19"},{"id":"7F6FD88C-27A6-4E0D-BD8D-FDF34AAEB1A9","name":"video-input-scart","codepoint":"F0F8C","aliases":[],"tags":["Video \/ Movie"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"EA3FB3E6-9696-4F01-AD34-5253E19EA34C","name":"video-input-svideo","codepoint":"F0842","aliases":["settings-input-svideo"],"tags":["Video \/ Movie"],"author":"Google","version":"2.1.19"},{"id":"9453CFB6-B0CA-469B-87A0-48C51EA1B64D","name":"video-minus","codepoint":"F09B2","aliases":["video-remove"],"tags":["Video \/ Movie"],"author":"Google","version":"2.4.85"},{"id":"DEC0A182-36E6-47D2-ABC4-AF717946C412","name":"video-minus-outline","codepoint":"F02BA","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"F4C3A814-205E-4F0A-9B3D-34B5777A4237","name":"video-off","codepoint":"F0568","aliases":["videocam-off"],"tags":["Video \/ Movie","Home Automation"],"author":"Google","version":"1.5.54"},{"id":"4CD11F14-5EB9-4532-910A-D9329CB1CE48","name":"video-off-outline","codepoint":"F0BDB","aliases":["videocam-off-outline"],"tags":["Video \/ Movie"],"author":"Google","version":"3.0.39"},{"id":"993D76B5-D3E5-4360-986D-3F13A04F29A7","name":"video-outline","codepoint":"F0BDC","aliases":["videocam-outline"],"tags":["Video \/ Movie"],"author":"Google","version":"3.0.39"},{"id":"7C399890-F840-44F0-834E-409C1D9F1337","name":"video-plus","codepoint":"F09B3","aliases":["video-call","video-add"],"tags":["Video \/ Movie"],"author":"Google","version":"2.4.85"},{"id":"66BF0ABD-9688-49F1-B260-382B15D53432","name":"video-plus-outline","codepoint":"F01D3","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"DF10672F-0064-47B8-A327-797095F0F6A1","name":"video-stabilization","codepoint":"F091B","aliases":["video-stabilisation"],"tags":["Video \/ Movie"],"author":"Google","version":"2.3.50"},{"id":"465D18D8-ABEA-4D2B-8A05-C6555C36803F","name":"video-switch","codepoint":"F0569","aliases":["switch-video"],"tags":["Video \/ Movie"],"author":"Google","version":"1.5.54"},{"id":"FF441E7F-8F7E-4B03-876E-FD65C2A847C9","name":"video-switch-outline","codepoint":"F0790","aliases":[],"tags":["Video \/ Movie"],"author":"Google","version":"2.0.46"},{"id":"1A8E4CC1-97A7-4593-BE20-0E9C5686C2D3","name":"video-vintage","codepoint":"F0A1C","aliases":["video-film","video-classic"],"tags":["Video \/ Movie"],"author":"Contributors","version":"2.5.94"},{"id":"CB8F2A33-9238-40E0-9B1E-935586CF1FBA","name":"video-wireless","codepoint":"F0ED2","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"178F6478-2B6F-43B7-AC0C-050481FA0BF2","name":"video-wireless-outline","codepoint":"F0ED3","aliases":[],"tags":["Video \/ Movie"],"author":"Michael Irigoyen","version":"3.7.94"},{"id":"E0B1CD58-0403-430F-AA9A-30B9E0122314","name":"view-agenda","codepoint":"F056A","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"33C2B7B8-82DB-41C9-8B4E-2EFEE60C0D6E","name":"view-agenda-outline","codepoint":"F11D8","aliases":[],"tags":["View"],"author":"Google","version":"4.5.95"},{"id":"B3E07750-AF3A-49FA-BA72-7CE5D4A3C7AB","name":"view-array","codepoint":"F056B","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"C9B8EF68-CB6B-4B4E-BEEC-4BC30C04BE5F","name":"view-array-outline","codepoint":"F1485","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"99C269BA-B1CD-4BC0-9BCC-7C5D95F881AC","name":"view-carousel","codepoint":"F056C","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"27DE61C6-7B1F-429C-A396-AF9895CE5AD0","name":"view-carousel-outline","codepoint":"F1486","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"163CB77E-4663-4F8E-B73E-20FCC5C5BED3","name":"view-column","codepoint":"F056D","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"73732965-3E0C-4746-8D18-785E318F005D","name":"view-column-outline","codepoint":"F1487","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"CBBB6642-EA10-4B28-8D7B-7FD2E5252A2C","name":"view-comfy","codepoint":"F0E6A","aliases":[],"tags":["View"],"author":"Google","version":"3.6.95"},{"id":"31233545-9224-4135-87F7-7B1257F23767","name":"view-comfy-outline","codepoint":"F1488","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"CD9C04DB-710E-4FD1-A679-535C5EF50BFB","name":"view-compact","codepoint":"F0E6B","aliases":[],"tags":["View"],"author":"Google","version":"3.6.95"},{"id":"8FD1F3B0-682D-47BD-A4C8-C2526C674229","name":"view-compact-outline","codepoint":"F0E6C","aliases":[],"tags":["View"],"author":"Google","version":"3.6.95"},{"id":"B6D8B213-DC5F-40D3-97E4-EFA9B499A19D","name":"view-dashboard","codepoint":"F056E","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"B44B2BB0-0BF9-42B7-BF70-ECC7FF102520","name":"view-dashboard-outline","codepoint":"F0A1D","aliases":[],"tags":["View"],"author":"Google","version":"2.5.94"},{"id":"26B319A5-9CF7-4637-94A2-DB633BD22ABA","name":"view-dashboard-variant","codepoint":"F0843","aliases":[],"tags":["View"],"author":"Google","version":"2.1.19"},{"id":"F05DF9FC-A193-444F-8B6E-24862443BA63","name":"view-dashboard-variant-outline","codepoint":"F1489","aliases":[],"tags":["View"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"AD31242E-143E-475E-822B-E363C9E9F2F4","name":"view-day","codepoint":"F056F","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"B478F822-6D6B-4A47-BCFE-0236D5766711","name":"view-day-outline","codepoint":"F148A","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"E788F50B-B654-4AEC-ACD7-6E9F5AE8B789","name":"view-grid","codepoint":"F0570","aliases":[],"tags":["View"],"author":"Simran","version":"1.5.54"},{"id":"33566CF8-43DC-48FF-9891-557946141997","name":"view-grid-outline","codepoint":"F11D9","aliases":[],"tags":["View"],"author":"Michael Richins","version":"4.5.95"},{"id":"74FA0104-E5C4-4FE8-A9CD-45DC574D64C9","name":"view-grid-plus","codepoint":"F0F8D","aliases":["view-grid-add"],"tags":["View"],"author":"Google","version":"3.9.97"},{"id":"120B7778-EAE8-444B-AEDF-9F7793BF6A35","name":"view-grid-plus-outline","codepoint":"F11DA","aliases":[],"tags":["View"],"author":"Michael Richins","version":"4.5.95"},{"id":"86DC0560-F109-4301-ACC7-46A6F74F441A","name":"view-headline","codepoint":"F0571","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"D9FCEB1D-004D-442E-A979-320101768F99","name":"view-list","codepoint":"F0572","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"FA9A5868-724C-429E-897B-72AD25186E2D","name":"view-list-outline","codepoint":"F148B","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"467C52AB-0DEA-43AF-BAE4-76FD66D6C7F0","name":"view-module","codepoint":"F0573","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"69AAF987-9993-4E5D-952D-ED815244B1F6","name":"view-module-outline","codepoint":"F148C","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"A085C7C7-F5C5-441C-84C0-05EB3B6A8767","name":"view-parallel","codepoint":"F0728","aliases":[],"tags":["View"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"C14FCE1C-4ACB-4876-94AA-93C2E5DB362B","name":"view-parallel-outline","codepoint":"F148D","aliases":[],"tags":["View"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"F3640F38-D10F-42C8-8A68-751D965B1F65","name":"view-quilt","codepoint":"F0574","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"2797C36A-5A29-4679-AAB7-4F4832FA7DC5","name":"view-quilt-outline","codepoint":"F148E","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"350F115F-0C20-4AB3-8206-81D2A25A2EF4","name":"view-sequential","codepoint":"F0729","aliases":[],"tags":["View"],"author":"Michael Irigoyen","version":"1.8.36"},{"id":"1B8CD437-1CE6-4493-9C57-5E367B47A0BF","name":"view-sequential-outline","codepoint":"F148F","aliases":[],"tags":["View"],"author":"Michael Irigoyen","version":"5.3.45"},{"id":"7FE1CF30-B16F-4626-8450-1881934D2FDF","name":"view-split-horizontal","codepoint":"F0BCB","aliases":[],"tags":["View"],"author":"Google","version":"3.0.39"},{"id":"25E0A405-7A96-4159-8A63-9088BFA330F1","name":"view-split-vertical","codepoint":"F0BCC","aliases":[],"tags":["View"],"author":"Google","version":"3.0.39"},{"id":"1B42A4BC-3B55-4C21-BDEF-94DC970012F9","name":"view-stream","codepoint":"F0575","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"26CE4165-E7A4-425A-8175-8A8C392F08D3","name":"view-stream-outline","codepoint":"F1490","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"8ED74862-BA7D-43FC-91EA-283D655B451F","name":"view-week","codepoint":"F0576","aliases":[],"tags":["View"],"author":"Google","version":"1.5.54"},{"id":"163700DD-5F95-4BEC-82AC-7E5F1FD20BC8","name":"view-week-outline","codepoint":"F1491","aliases":[],"tags":["View"],"author":"Google","version":"5.3.45"},{"id":"0FF21C45-66B4-492A-829C-9F46778323A9","name":"vimeo","codepoint":"F0577","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"D6702650-990F-416E-BF27-F6F2B86BFB8D","name":"violin","codepoint":"F060F","aliases":[],"tags":["Music"],"author":"Google","version":"1.5.54"},{"id":"AE3F0BAE-DE0A-4BFE-82B6-3268D1B21006","name":"virtual-reality","codepoint":"F0894","aliases":["vr"],"tags":[],"author":"GreenTurtwig","version":"2.1.99"},{"id":"B413B8B5-E20E-41BF-B6F1-696050D47421","name":"virus","codepoint":"F13B6","aliases":[],"tags":["Science","Medical \/ Hospital"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"0F7EE89B-C9E3-4365-B9DC-D3A28D328F66","name":"virus-outline","codepoint":"F13B7","aliases":[],"tags":["Science","Medical \/ Hospital"],"author":"Michael Irigoyen","version":"5.1.45"},{"id":"9098736F-D298-4724-AE04-6BEA124F3854","name":"vk","codepoint":"F0579","aliases":["vkontakte"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"3695CD89-BCB2-4D10-A8C5-9190F31F7C92","name":"vlc","codepoint":"F057C","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"C90AED93-FCBD-4FDC-A15B-26CD066775BD","name":"voice-off","codepoint":"F0ED4","aliases":[],"tags":[],"author":"Google","version":"3.7.95"},{"id":"04CEF7C6-E77F-4A66-89F3-2F5B544C482B","name":"voicemail","codepoint":"F057D","aliases":[],"tags":[],"author":"Google","version":"1.5.54"},{"id":"3978DABC-FC98-4D3E-A971-88716AD5D600","name":"volleyball","codepoint":"F09B4","aliases":[],"tags":["Sport"],"author":"Augustin Ursu","version":"2.4.85"},{"id":"CE6E08CF-2476-4BBB-AF91-6D081F1CBEF9","name":"volume-high","codepoint":"F057E","aliases":["audio","speaker","speakerphone"],"tags":["Audio","Home Automation","Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"213621FE-E003-4B40-9385-B9BCE19DB035","name":"volume-low","codepoint":"F057F","aliases":["audio","speaker"],"tags":["Audio","Home Automation","Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"0E37E506-8AD8-42C7-87E4-F8A2AEE03972","name":"volume-medium","codepoint":"F0580","aliases":["audio","speaker"],"tags":["Audio","Home Automation","Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"D8BFD10F-6D55-4EE1-8D30-5B5CB064CBBF","name":"volume-minus","codepoint":"F075E","aliases":["volume-decrease"],"tags":["Audio","Home Automation","Cellphone \/ Phone"],"author":"Austin Andrews","version":"1.9.32"},{"id":"A78C1259-0DB5-4793-9EA9-DD69FEB337A8","name":"volume-mute","codepoint":"F075F","aliases":[],"tags":["Audio","Cellphone \/ Phone"],"author":"Austin Andrews","version":"1.9.32"},{"id":"74834C94-6AE1-493B-A9FB-4EE2A8FD989C","name":"volume-off","codepoint":"F0581","aliases":["mute","audio-off","speaker-off","speakerphone-off"],"tags":["Audio","Home Automation","Cellphone \/ Phone"],"author":"Google","version":"1.5.54"},{"id":"DECF3A51-F972-4D34-815D-D103BCE3888B","name":"volume-plus","codepoint":"F075D","aliases":["volume-increase"],"tags":["Audio","Home Automation","Cellphone \/ Phone"],"author":"Austin Andrews","version":"1.9.32"},{"id":"95D3325D-257A-433C-8B2E-D674C21BA268","name":"volume-source","codepoint":"F1120","aliases":[],"tags":["Cellphone \/ Phone","Audio"],"author":"Google","version":"4.3.95"},{"id":"E5699A8D-84C4-41F2-A48A-397F8153B4A1","name":"volume-variant-off","codepoint":"F0E08","aliases":[],"tags":["Audio","Cellphone \/ Phone"],"author":"Andrew Nenakhov","version":"3.5.94"},{"id":"9CDA3BD8-77A5-4669-BFB7-785EECAE2FCA","name":"volume-vibrate","codepoint":"F1121","aliases":[],"tags":["Cellphone \/ Phone","Audio"],"author":"Simran","version":"4.3.95"},{"id":"61CDB722-3238-4F21-9A3F-77DC47A51755","name":"vote","codepoint":"F0A1F","aliases":["how-to-vote"],"tags":[],"author":"Google","version":"2.5.94"},{"id":"392D2435-0B0E-4CDA-A542-FAB319411B8A","name":"vote-outline","codepoint":"F0A20","aliases":["how-to-vote-outline"],"tags":[],"author":"Google","version":"2.5.94"},{"id":"A9EE1532-2932-4F71-95DC-1EFB56BA4DFC","name":"vpn","codepoint":"F0582","aliases":["virtual-private-network"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"CB3BC222-1858-41C6-A488-0C2BB1FB2EA8","name":"vuejs","codepoint":"F0844","aliases":["vue-js"],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"2.1.19"},{"id":"2603306D-9691-469C-B468-6E53FFA2D0DE","name":"vuetify","codepoint":"F0E6D","aliases":[],"tags":[],"author":"Contributors","version":"3.6.95"},{"id":"DA42DA16-21E0-4A08-89E4-F634EBBCF85A","name":"walk","codepoint":"F0583","aliases":["directions-walk","walker","walking"],"tags":["Sport","Transportation + Other"],"author":"Google","version":"1.5.54"},{"id":"5DAB0112-3768-4ADC-8796-A88B4473FE56","name":"wall","codepoint":"F07FE","aliases":["bricks"],"tags":[],"author":"Austin Andrews","version":"2.0.46"},{"id":"EABFE131-4690-406C-9042-EFCA33E97A00","name":"wall-sconce","codepoint":"F091C","aliases":[],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"4F0EF72A-F2A8-4BFA-9E6F-279E159FC888","name":"wall-sconce-flat","codepoint":"F091D","aliases":["ceiling-light-flat","pot-light-flat"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"DEAC0604-6FD1-496C-99E1-74068FC27713","name":"wall-sconce-flat-variant","codepoint":"F041C","aliases":["pot-light-flat-variant"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"1.5.54"},{"id":"05EDCFBB-803B-4DA9-BDC5-17A4E43DE584","name":"wall-sconce-round","codepoint":"F0748","aliases":["pot-light-round"],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"1.9.32"},{"id":"D599F298-0E64-47A7-AD5B-B1AD5CEE1B1E","name":"wall-sconce-round-variant","codepoint":"F091E","aliases":["pot-light-round-variant"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"2.3.50"},{"id":"C5ABA786-D897-4770-AA78-CE4CB2A9230E","name":"wallet","codepoint":"F0584","aliases":["account-balance-wallet"],"tags":["Currency","Banking"],"author":"Google","version":"1.5.54"},{"id":"0D4DD4F1-0915-4D3D-8F21-A96C2DDAF6E0","name":"wallet-giftcard","codepoint":"F0585","aliases":["card-giftcard","redeem"],"tags":["Shopping","Banking"],"author":"Google","version":"1.5.54"},{"id":"BBE325B3-416A-4160-8E95-162B076B8839","name":"wallet-membership","codepoint":"F0586","aliases":["card-membership"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"BE3A6C7B-398B-4B7D-B7F3-7EDE9220F489","name":"wallet-outline","codepoint":"F0BDD","aliases":["account-balance-wallet-outline"],"tags":["Currency","Banking"],"author":"Google","version":"3.0.39"},{"id":"A53A1EF4-13E1-4807-A20E-A0DA2F52392D","name":"wallet-plus","codepoint":"F0F8E","aliases":["wallet-add"],"tags":["Banking"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"1BDED2D9-31E7-457D-AA32-6CE990645545","name":"wallet-plus-outline","codepoint":"F0F8F","aliases":["wallet-add-outline"],"tags":["Banking"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"790A03D3-B40A-468A-A6D6-CA3679FDBD8D","name":"wallet-travel","codepoint":"F0587","aliases":["card-travel"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"350FE9C5-BFF1-462D-9318-BA2DDC55E11E","name":"wallpaper","codepoint":"F0E09","aliases":[],"tags":[],"author":"Google","version":"3.5.94"},{"id":"0E468855-81AF-4CA1-ACF0-D166D07F188C","name":"wan","codepoint":"F0588","aliases":["wide-area-network"],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"A6E4DFBB-920D-4A21-AE54-6378FEBDD767","name":"wardrobe","codepoint":"F0F90","aliases":["closet"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"A1AA70DE-C9FD-4791-91D0-27FC025F7A81","name":"wardrobe-outline","codepoint":"F0F91","aliases":["closet-outline"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"DBF95B71-CC94-4672-8356-A09B96644694","name":"warehouse","codepoint":"F0F81","aliases":[],"tags":["Places"],"author":"Contributors","version":"3.9.97"},{"id":"42C06A23-81D5-4EF6-8CFA-B4FBF66E7B17","name":"washing-machine","codepoint":"F072A","aliases":["laundrette","local-laundry-service"],"tags":["Home Automation"],"author":"Google","version":"1.8.36"},{"id":"A00D0B3E-D24A-4BC9-915C-7B264B63F2F4","name":"washing-machine-alert","codepoint":"F11BC","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"9B318E52-E7BE-4BE1-94DF-96CA020CE55D","name":"washing-machine-off","codepoint":"F11BD","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"3389F6CD-3E46-47DE-B26A-341C1B65D6BF","name":"watch","codepoint":"F0589","aliases":[],"tags":["Device \/ Tech"],"author":"Google","version":"1.5.54"},{"id":"4FAFD079-50D1-4FD3-9427-CF0C08148D84","name":"watch-export","codepoint":"F058A","aliases":[],"tags":["Device \/ Tech"],"author":"Austin Andrews","version":"1.5.54"},{"id":"8213DABD-5CCB-415F-9457-A0A68B0F8179","name":"watch-export-variant","codepoint":"F0895","aliases":[],"tags":["Device \/ Tech"],"author":"Contributors","version":"2.1.99"},{"id":"0D93B47F-C9F9-4C87-B63C-656184A87C74","name":"watch-import","codepoint":"F058B","aliases":[],"tags":["Device \/ Tech"],"author":"Austin Andrews","version":"1.5.54"},{"id":"383F089B-340D-43BD-A64C-4F81B8DF2A1F","name":"watch-import-variant","codepoint":"F0896","aliases":[],"tags":["Device \/ Tech"],"author":"Contributors","version":"2.1.99"},{"id":"B6ADE62B-5D0C-4D24-87F4-9D8A0F1C7A04","name":"watch-variant","codepoint":"F0897","aliases":[],"tags":["Device \/ Tech"],"author":"GreenTurtwig","version":"2.1.99"},{"id":"AE556BFC-A1A0-4B42-9123-B48DC7A3CBF3","name":"watch-vibrate","codepoint":"F06B1","aliases":[],"tags":["Device \/ Tech"],"author":"GreenTurtwig","version":"1.7.12"},{"id":"391763A7-BCF6-4C13-920B-115A7A5092B6","name":"watch-vibrate-off","codepoint":"F0CDA","aliases":[],"tags":["Device \/ Tech"],"author":"Michael Richins","version":"3.2.89"},{"id":"17EEE663-92E4-4AB1-87FE-94F2CD296C4B","name":"water","codepoint":"F058C","aliases":["drop","blood","water-drop","trans-fat","ink"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"DDBEC0DB-97A9-439B-9FC0-5A05F51ED5E3","name":"water-alert","codepoint":"F1502","aliases":["drop-alert","blood-alert","ink-alert"],"tags":["Alert \/ Error"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"4741B9A5-3E15-45B5-BD7B-B812C7E7644F","name":"water-alert-outline","codepoint":"F1503","aliases":["drop-alert-outline","blood-alert-outline","ink-alert-outline"],"tags":["Alert \/ Error"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"02A9C002-3B54-415E-8199-067139DF771A","name":"water-boiler","codepoint":"F0F92","aliases":["water-heater"],"tags":["Home Automation"],"author":"GreenTurtwig","version":"3.9.97"},{"id":"EC21EC05-F45B-4560-A37E-3E721219A728","name":"water-boiler-alert","codepoint":"F11B3","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"E7515B82-DE9D-4053-9D48-297511ED48E5","name":"water-boiler-off","codepoint":"F11B4","aliases":[],"tags":["Home Automation"],"author":"Michael Irigoyen","version":"4.5.95"},{"id":"30A9ED7F-3D06-476B-A4F1-B9F85786FF00","name":"water-check","codepoint":"F1504","aliases":["drop-check","blood-check","ink-check"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"E555BA93-F6A7-4B19-A4F8-132585E14850","name":"water-check-outline","codepoint":"F1505","aliases":["drop-check-outline","blood-check-outline","ink-check-outline"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"C3824C0D-87B1-4577-A060-EDE628A694BC","name":"water-minus","codepoint":"F1506","aliases":["drop-minus","blood-minus","ink-minus"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"8536A2D7-1203-44B5-BBBE-6C37AABAD5B6","name":"water-minus-outline","codepoint":"F1507","aliases":["drop-minus-outline","blood-minus-outline","ink-minus-outline"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"6C9777A0-967D-4242-91B2-E4D6B5596498","name":"water-off","codepoint":"F058D","aliases":["format-color-reset","trans-fat-off","blood-off","ink-off"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"8B8E5074-5348-4856-BBF0-461BA5022BF3","name":"water-off-outline","codepoint":"F1508","aliases":["drop-off-outline","blood-off-outline","trans-fat-off-outline","ink-off-outline"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"DC3CFDE4-8FA9-497A-A937-6F7182B560E1","name":"water-outline","codepoint":"F0E0A","aliases":["drop-outline","blood-outline","water-drop-outline","ink-outline"],"tags":[],"author":"GreenTurtwig","version":"3.5.94"},{"id":"2CE24A47-D798-4FFD-A53D-65FE9D452E2F","name":"water-percent","codepoint":"F058E","aliases":["humidity","ink-percent"],"tags":["Weather","Home Automation"],"author":"Simran","version":"1.5.54"},{"id":"55C44783-89D5-4A31-86B8-863B719EC876","name":"water-percent-alert","codepoint":"F1509","aliases":["humidity-alert","ink-percent-alert"],"tags":["Alert \/ Error"],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"B7B4ACBA-F24A-48D7-A409-965A32860CE9","name":"water-plus","codepoint":"F150A","aliases":["drop-plus","blood-plus","ink-plus"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"74B7C41B-554D-453A-8646-FFAFDF78C3CA","name":"water-plus-outline","codepoint":"F150B","aliases":["drop-plus-outline","blood-plus-outline","ink-plus-outline"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"09C341A8-067F-4CE2-96BC-D96E18334AB3","name":"water-polo","codepoint":"F12A0","aliases":[],"tags":["Sport"],"author":"Yaroslav Bandura","version":"4.7.95"},{"id":"06862D93-608A-4B21-9193-83FA8C6BBDCD","name":"water-pump","codepoint":"F058F","aliases":["tap","kitchen-tap","faucet"],"tags":["Agriculture","Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"A66B4E6E-70F9-4136-BE33-D02C002F7B30","name":"water-pump-off","codepoint":"F0F93","aliases":["tap-off","kitchen-tap-off","faucet-off"],"tags":["Agriculture","Home Automation"],"author":"Nick","version":"3.9.97"},{"id":"2B0BAF1E-C9B8-42E9-84EB-D095EE2B0C39","name":"water-remove","codepoint":"F150C","aliases":["drop-remove","blood-remove","ink-remove"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"C90739A3-CEDE-4524-A736-BA5A5B5F0CCB","name":"water-remove-outline","codepoint":"F150D","aliases":["drop-remove-outline","blood-remove-outline","ink-remove-outline"],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"4EE62E99-C30B-4A90-B89D-ADF4C26EF888","name":"water-well","codepoint":"F106B","aliases":[],"tags":[],"author":"Michael Richins","version":"4.1.95"},{"id":"55A09921-7B26-49DB-AB0E-47E2C133D68C","name":"water-well-outline","codepoint":"F106C","aliases":[],"tags":[],"author":"Michael Richins","version":"4.1.95"},{"id":"5B017D32-0BE9-4A6A-999C-32777F995FBB","name":"watering-can","codepoint":"F1481","aliases":["watering-pot"],"tags":["Agriculture"],"author":"Contributors","version":"5.3.45"},{"id":"67419E50-B2CE-4B36-A137-705FD6404252","name":"watering-can-outline","codepoint":"F1482","aliases":["watering-pot-outline"],"tags":["Agriculture"],"author":"Contributors","version":"5.3.45"},{"id":"20907A4A-11CA-447E-A4F5-D0F0901D197E","name":"watermark","codepoint":"F0612","aliases":["branding-watermark"],"tags":[],"author":"Google","version":"1.5.54"},{"id":"34D870BF-048B-44DF-93F9-8EBE7AF4C263","name":"wave","codepoint":"F0F2E","aliases":["water"],"tags":["Transportation + Water"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"B677F1CB-606B-4DB5-9A9D-73E4FC0AC3F0","name":"waveform","codepoint":"F147D","aliases":[],"tags":["Audio"],"author":"Haley Halcyon","version":"5.2.45"},{"id":"547979BF-6FF4-4CFF-BD55-1E5793C9DAA3","name":"waves","codepoint":"F078D","aliases":["ocean","lake","flood","water"],"tags":["Weather","Transportation + Water"],"author":"Michael Irigoyen","version":"1.9.32"},{"id":"51E32DD0-F286-4039-8242-2BF03E917C37","name":"waze","codepoint":"F0BDE","aliases":[],"tags":[],"author":"Contributors","version":"3.0.39"},{"id":"9286B6B3-09EE-4465-9A70-D7874E26F3DF","name":"weather-cloudy","codepoint":"F0590","aliases":[],"tags":["Weather","Cloud"],"author":"Austin Andrews","version":"1.5.54"},{"id":"EF2214BE-8126-4458-A17A-74C58B30C2C5","name":"weather-cloudy-alert","codepoint":"F0F2F","aliases":[],"tags":["Weather","Alert \/ Error","Cloud"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"522BA775-D569-4615-AABE-40B9E638EA18","name":"weather-cloudy-arrow-right","codepoint":"F0E6E","aliases":[],"tags":["Weather","Cloud"],"author":"Michael Irigoyen","version":"3.6.95"},{"id":"9E1AC9CA-0FA4-44C6-BA5D-2EB3CED4899D","name":"weather-fog","codepoint":"F0591","aliases":["weather-mist"],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BED775CF-13BD-4D5A-A06F-7B026E820CB1","name":"weather-hail","codepoint":"F0592","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"87410436-C351-4FF7-91E4-9A5F52D49F69","name":"weather-hazy","codepoint":"F0F30","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"880967C4-85F9-4953-A6D0-73C9370BC987","name":"weather-hurricane","codepoint":"F0898","aliases":[],"tags":["Weather"],"author":"Michael Richins","version":"2.1.99"},{"id":"6AF7BD8A-088F-4B07-806D-7456EB382D76","name":"weather-lightning","codepoint":"F0593","aliases":["weather-storm","weather-thunder","weather-flash"],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F69033FD-E6F0-48E7-ADA7-7CDF71B1673C","name":"weather-lightning-rainy","codepoint":"F067E","aliases":["weather-thunder-rainy","weather-storm"],"tags":["Weather"],"author":"Austin Andrews","version":"1.7.12"},{"id":"1C3BA3AB-E86E-481B-A3C2-867B37A6E55A","name":"weather-night","codepoint":"F0594","aliases":["moon-and-stars","night-sky"],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"19D690AD-38F9-45CF-A092-D62A53098A68","name":"weather-night-partly-cloudy","codepoint":"F0F31","aliases":[],"tags":["Weather","Cloud"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"80E6A6FB-1524-4A7D-9551-17D3BDFBD7C5","name":"weather-partly-cloudy","codepoint":"F0595","aliases":["weather-partlycloudy"],"tags":["Weather","Cloud"],"author":"Austin Andrews","version":"1.5.54"},{"id":"93C1E28D-0C94-4B55-8B26-BACE3F777ECC","name":"weather-partly-lightning","codepoint":"F0F32","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"B01CFC20-40C4-4647-A20D-0181E5AB4952","name":"weather-partly-rainy","codepoint":"F0F33","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"0E45DB37-DF54-422B-AE18-2AA35BC54109","name":"weather-partly-snowy","codepoint":"F0F34","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"CAF9B1D0-1095-4A34-AC07-78C937BDA618","name":"weather-partly-snowy-rainy","codepoint":"F0F35","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"220955AA-770D-4884-A2ED-F21D2DC2CCDA","name":"weather-pouring","codepoint":"F0596","aliases":["weather-heavy-rain"],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"45EF5E01-7499-4964-A897-5602F45A822E","name":"weather-rainy","codepoint":"F0597","aliases":["weather-drizzle","weather-spitting"],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"88999373-43C5-4851-BBCF-5335D8DFBDA0","name":"weather-snowy","codepoint":"F0598","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"D97DA5D6-5A65-4ADB-B124-48C22F32B07A","name":"weather-snowy-heavy","codepoint":"F0F36","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"0938BCD1-BCF8-4439-B6B3-A590150878BC","name":"weather-snowy-rainy","codepoint":"F067F","aliases":["weather-sleet"],"tags":["Weather"],"author":"Austin Andrews","version":"1.7.12"},{"id":"7F85265E-304C-4575-A73F-F0FCF0CA951B","name":"weather-sunny","codepoint":"F0599","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"3AACF641-3923-4DBA-9568-0680999A6548","name":"weather-sunny-alert","codepoint":"F0F37","aliases":["heat-alert","heat-advisory","sun-advisory"],"tags":["Weather","Alert \/ Error"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"2C884CEC-BA06-491D-9A7D-17B8B2E74CA6","name":"weather-sunny-off","codepoint":"F14E4","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"5EF29669-A342-46D1-AE1B-47917E44311D","name":"weather-sunset","codepoint":"F059A","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"032B7D10-9218-4B71-B190-C486832BEF61","name":"weather-sunset-down","codepoint":"F059B","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"AC82F126-0773-44CE-A004-77E7DDD130C9","name":"weather-sunset-up","codepoint":"F059C","aliases":["sunrise"],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"BE149D04-25E9-4CE8-BD75-2D6D49A03FEA","name":"weather-tornado","codepoint":"F0F38","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"3.8.95"},{"id":"7544E7E7-02F7-405C-9ADB-2E2540B07343","name":"weather-windy","codepoint":"F059D","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"454DE99F-BA48-4A7B-A2C6-C0E162065D10","name":"weather-windy-variant","codepoint":"F059E","aliases":[],"tags":["Weather"],"author":"Austin Andrews","version":"1.5.54"},{"id":"DA9C32CA-8C31-4462-B123-479169C31587","name":"web","codepoint":"F059F","aliases":["language"],"tags":["Geographic Information System"],"author":"Google","version":"1.5.54"},{"id":"42B55CB7-DC3D-4804-A848-1A9CA7DCD533","name":"web-box","codepoint":"F0F94","aliases":["language-box"],"tags":["Geographic Information System"],"author":"Contributors","version":"3.9.97"},{"id":"FABF6519-0CE7-461D-986D-60B4BF7374A7","name":"web-clock","codepoint":"F124A","aliases":[],"tags":["Date \/ Time"],"author":"frankgrinaert","version":"4.6.95"},{"id":"03483AFB-9D53-4E10-B00C-1095C1873276","name":"webcam","codepoint":"F05A0","aliases":["web-camera"],"tags":["Video \/ Movie","Home Automation"],"author":"Chris Litherland","version":"1.5.54"},{"id":"F8D156C4-16AA-47AD-B06B-970E27F30FE6","name":"webcam-off","codepoint":"F1737","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.9.55"},{"id":"5B415522-B2A4-4D34-BEE3-D81D607BBD0B","name":"webhook","codepoint":"F062F","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.6.50"},{"id":"65235220-D361-4E99-BEC6-E62B231E4384","name":"webpack","codepoint":"F072B","aliases":[],"tags":["Brand \/ Logo","Developer \/ Languages"],"author":"Contributors","version":"1.8.36"},{"id":"972B66F0-ED66-42B4-BEE8-63EF28F4658B","name":"webrtc","codepoint":"F1248","aliases":[],"tags":[],"author":"Contributors","version":"4.6.95"},{"id":"31CBB823-2223-40D5-BCF7-470F91159757","name":"wechat","codepoint":"F0611","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"F5DECC39-2E4C-4574-B141-832DFBA8CB43","name":"weight","codepoint":"F05A1","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"ABC7A229-B0E6-4F6C-9A00-C1340D95DEAF","name":"weight-gram","codepoint":"F0D3F","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"3.3.92"},{"id":"5EDFF36D-4C8E-4B8D-BE3F-76C27DB804DF","name":"weight-kilogram","codepoint":"F05A2","aliases":["weight-kg"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"4ECFBE4E-52B2-4A60-BD6C-9B7DAB38E7A5","name":"weight-lifter","codepoint":"F115D","aliases":["crossfit","gym","fitness-center","human-barbell"],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"47B5C7D8-105F-4420-B911-50693081EA76","name":"weight-pound","codepoint":"F09B5","aliases":["weight-lb"],"tags":[],"author":"Haley Halcyon","version":"2.4.85"},{"id":"C58497CE-5E84-483C-9C85-3007ADF9BC9A","name":"whatsapp","codepoint":"F05A3","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"2D35B573-0B04-4E72-84CA-6BE431EE5AE5","name":"wheel-barrow","codepoint":"F14F2","aliases":[],"tags":["Hardware \/ Tools"],"author":"Michael Irigoyen","version":"5.4.55"},{"id":"FB4E1390-EFB1-4364-B6EE-F936C5715163","name":"wheelchair-accessibility","codepoint":"F05A4","aliases":["accessible"],"tags":[],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"2DADA4F6-D9AD-454D-BC75-1D8DE507FA82","name":"whistle","codepoint":"F09B6","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"2.4.85"},{"id":"93CDBDF3-A4BE-4ADE-9179-171FA94726A6","name":"whistle-outline","codepoint":"F12BC","aliases":[],"tags":["Sport"],"author":"Michael Richins","version":"4.8.95"},{"id":"2FE12EF0-B5CE-4ADB-9B1B-3F796F0EDE0E","name":"white-balance-auto","codepoint":"F05A5","aliases":["wb-auto"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"4464050A-1A97-46CF-BBA5-CE52D600CB45","name":"white-balance-incandescent","codepoint":"F05A6","aliases":["wb-incandescent"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"E88B06D9-C60D-4084-9AE9-742266F0E8FB","name":"white-balance-iridescent","codepoint":"F05A7","aliases":["wb-iridescent"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"7DCAB3C3-C32F-483D-98F1-1728919AA17B","name":"white-balance-sunny","codepoint":"F05A8","aliases":["wb-sunny"],"tags":["Photography"],"author":"Google","version":"1.5.54"},{"id":"419C0A49-C751-4204-8C82-7E43B0896BD9","name":"widgets","codepoint":"F072C","aliases":[],"tags":[],"author":"Google","version":"1.8.36"},{"id":"94C40C14-7BBA-4DF6-824B-6EFC9327F7E5","name":"widgets-outline","codepoint":"F1355","aliases":[],"tags":[],"author":"Google","version":"4.9.95"},{"id":"E77CF681-7DD0-4EDF-AA35-0DB80790BC03","name":"wifi","codepoint":"F05A9","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"9B9FF835-20F9-49BD-A11F-403786BC42A2","name":"wifi-alert","codepoint":"F16B5","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"8778FE48-83F3-484D-A1DE-C12000DB3170","name":"wifi-arrow-down","codepoint":"F16B6","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"79955442-BBC4-4B1D-84EE-69990BF30331","name":"wifi-arrow-left","codepoint":"F16B7","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"BD5239F0-5659-4E99-9860-F28D58BDF788","name":"wifi-arrow-left-right","codepoint":"F16B8","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"F245A78A-C6F3-45CF-B4C0-131280576715","name":"wifi-arrow-right","codepoint":"F16B9","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"20394D81-3E4C-4963-88C7-BB015ECA8D72","name":"wifi-arrow-up","codepoint":"F16BA","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"EE028441-38B6-40F9-B3E8-C673241BD39D","name":"wifi-arrow-up-down","codepoint":"F16BB","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"06F860BA-78F4-4F9C-8A90-E6ABEF1FA064","name":"wifi-cancel","codepoint":"F16BC","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"41D2061C-CFC9-4686-B916-4BEC07AB1553","name":"wifi-check","codepoint":"F16BD","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"17572DB9-20E6-4B83-A6B8-C66282523BC8","name":"wifi-cog","codepoint":"F16BE","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"3E5F6D19-E6C7-48BD-990F-C7D10598B2F7","name":"wifi-lock","codepoint":"F16BF","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"F9450F5D-FCF2-4E89-B234-FDA2F72C6B18","name":"wifi-lock-open","codepoint":"F16C0","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"A6FB83C2-13FE-4B23-AE9B-7F2696CA2835","name":"wifi-marker","codepoint":"F16C1","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"DFEC628C-E105-456D-8F73-71F54116DBC2","name":"wifi-minus","codepoint":"F16C2","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"A7CAE187-B853-41DD-9D8D-FB9A28C3F764","name":"wifi-off","codepoint":"F05AA","aliases":[],"tags":[],"author":"Simran","version":"1.5.54"},{"id":"3CF89702-EA3B-48A1-9B5E-5188A80DCBA8","name":"wifi-plus","codepoint":"F16C3","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"540437B4-6901-4F18-A60F-CAA10FD74B49","name":"wifi-refresh","codepoint":"F16C4","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"5989CC44-8A90-4D17-ADB8-F7AC12A0CF4E","name":"wifi-remove","codepoint":"F16C5","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"BA9356E6-E4D6-4A64-923C-395114E0DBE3","name":"wifi-settings","codepoint":"F16C6","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"30694858-4607-48C1-A533-861E4968A0CE","name":"wifi-star","codepoint":"F0E0B","aliases":["wifi-favourite","network-favourite"],"tags":[],"author":"Michael Irigoyen","version":"3.5.94"},{"id":"E4665C87-DB69-45CC-B922-1FCB0F0A54A3","name":"wifi-strength-1","codepoint":"F091F","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"31F993F8-3BC0-4818-AE1C-91DF005766F3","name":"wifi-strength-1-alert","codepoint":"F0920","aliases":["wifi-strength-1-warning"],"tags":["Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"035F0E2C-C952-40AB-BC29-B8CE120C389D","name":"wifi-strength-1-lock","codepoint":"F0921","aliases":[],"tags":["Lock"],"author":"Simran","version":"2.3.50"},{"id":"91890A07-398B-41A0-B91C-647C7BE9F5DA","name":"wifi-strength-1-lock-open","codepoint":"F16CB","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"92D075FB-99D3-4926-A4E9-F25EAB70E78E","name":"wifi-strength-2","codepoint":"F0922","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"38D73A8E-CEA5-4E6F-960B-BD2A0D482D9F","name":"wifi-strength-2-alert","codepoint":"F0923","aliases":["wifi-strength-2-warning"],"tags":["Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"CD7B760F-1A3C-4DDE-AB00-9EF11DF12073","name":"wifi-strength-2-lock","codepoint":"F0924","aliases":[],"tags":["Lock"],"author":"Simran","version":"2.3.50"},{"id":"22E5DDDA-12A4-4087-B1FF-5C3E8807CE0B","name":"wifi-strength-2-lock-open","codepoint":"F16CC","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"736B9B99-3A60-4BCA-A79A-40DE34D17F43","name":"wifi-strength-3","codepoint":"F0925","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"780617FD-FBFA-4F88-98CA-2DEA43409312","name":"wifi-strength-3-alert","codepoint":"F0926","aliases":["wifi-strength-3-warning"],"tags":["Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"CD4F72AA-B86D-4133-8EB8-145F457A1F06","name":"wifi-strength-3-lock","codepoint":"F0927","aliases":[],"tags":["Lock"],"author":"Simran","version":"2.3.50"},{"id":"249BF1E5-B9AC-47D6-9FC4-72678EE933C4","name":"wifi-strength-3-lock-open","codepoint":"F16CD","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"41B86B22-7245-4A97-9BAA-3E9EBD44CEB0","name":"wifi-strength-4","codepoint":"F0928","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"B37308A1-15BE-4F23-82F4-B360C8BA63C1","name":"wifi-strength-4-alert","codepoint":"F0929","aliases":["wifi-strength-4-warning"],"tags":["Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"11518A63-4E2B-477D-8D93-9B6C708DE5E1","name":"wifi-strength-4-lock","codepoint":"F092A","aliases":[],"tags":["Lock"],"author":"Simran","version":"2.3.50"},{"id":"332A10AE-2396-460B-819F-7149D0BE4085","name":"wifi-strength-4-lock-open","codepoint":"F16CE","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"50E531C4-A82A-4F0C-A8BB-A2208B546E81","name":"wifi-strength-alert-outline","codepoint":"F092B","aliases":["wifi-strength-warning-outline","wifi-strength-0-alert","wifi-strength-0-warning"],"tags":["Alert \/ Error"],"author":"Simran","version":"2.3.50"},{"id":"40B4EE9D-5DA4-428C-BEF3-C75FD6740CA3","name":"wifi-strength-lock-open-outline","codepoint":"F16CF","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"718740BB-FC95-47E4-856B-0A469966C8DD","name":"wifi-strength-lock-outline","codepoint":"F092C","aliases":["wifi-strength-0-lock"],"tags":["Lock"],"author":"Simran","version":"2.3.50"},{"id":"122332EC-08DD-438C-BD47-AB332E1E04F6","name":"wifi-strength-off","codepoint":"F092D","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"E4D2EA69-5F99-4D0B-BC12-BD22A2835B19","name":"wifi-strength-off-outline","codepoint":"F092E","aliases":[],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"0DAAFF13-5A8D-44C3-AE46-9DDE62493C60","name":"wifi-strength-outline","codepoint":"F092F","aliases":["wifi-strength-0"],"tags":[],"author":"Simran","version":"2.3.50"},{"id":"73D9D138-DCB0-4CA7-9AB9-5C3BCB4D2165","name":"wifi-sync","codepoint":"F16C7","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.8.55"},{"id":"19DE621D-F082-42B5-9FD3-FEF8D84A2BB9","name":"wikipedia","codepoint":"F05AC","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"9DABF133-FBE0-416C-82D8-F47E8A559E12","name":"wind-turbine","codepoint":"F0DA5","aliases":[],"tags":[],"author":"Google","version":"3.4.93"},{"id":"0CB92EB7-2EE0-401C-9113-7D52E78DB51E","name":"window-close","codepoint":"F05AD","aliases":["cancel","close"],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"42DDDE71-7AA4-4A61-98F5-2A3B0AD486FF","name":"window-closed","codepoint":"F05AE","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"8A71B80F-BEE0-4603-8EB3-06699D1140FF","name":"window-closed-variant","codepoint":"F11DB","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"4.5.95"},{"id":"AB365770-45CF-44AC-941E-8E1396FAF428","name":"window-maximize","codepoint":"F05AF","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"C329F2CA-AC52-45CD-87D7-253AB115D47F","name":"window-minimize","codepoint":"F05B0","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"5617DB90-FDD7-4909-B322-D1EC44EB1372","name":"window-open","codepoint":"F05B1","aliases":[],"tags":["Home Automation"],"author":"Austin Andrews","version":"1.5.54"},{"id":"47841D12-3D7E-40C1-9230-08C8890E0067","name":"window-open-variant","codepoint":"F11DC","aliases":[],"tags":["Home Automation"],"author":"Michael Richins","version":"4.5.95"},{"id":"405C8463-0E67-48A3-B824-7C5E74423125","name":"window-restore","codepoint":"F05B2","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"0893E339-7750-4CAB-8C19-6496711F3C37","name":"window-shutter","codepoint":"F111C","aliases":[],"tags":["Home Automation"],"author":"idevo89","version":"4.3.95"},{"id":"8D6FB7B2-191F-459C-A41A-1D8881EA286B","name":"window-shutter-alert","codepoint":"F111D","aliases":[],"tags":["Home Automation","Alert \/ Error"],"author":"idevo89","version":"4.3.95"},{"id":"955A5813-3414-4712-ADF4-62878A42D3B9","name":"window-shutter-open","codepoint":"F111E","aliases":[],"tags":["Home Automation"],"author":"idevo89","version":"4.3.95"},{"id":"0D2A52AA-2CAE-427F-887E-6198929D6855","name":"windsock","codepoint":"F15FA","aliases":[],"tags":["Weather"],"author":"Michael Irigoyen","version":"5.6.55"},{"id":"70D590C8-8B7E-4F4A-A9FC-31765D35F349","name":"wiper","codepoint":"F0AE9","aliases":[],"tags":[],"author":"Michael Irigoyen","version":"2.7.94"},{"id":"CC8D7DD6-699C-4746-ACAB-84DCA7BBC5E9","name":"wiper-wash","codepoint":"F0DA6","aliases":["wiper-fluid","washer-fluid"],"tags":[],"author":"Michael Irigoyen","version":"3.4.93"},{"id":"464D9AC5-8A79-4E35-89E3-D84DDC0056A3","name":"wizard-hat","codepoint":"F1477","aliases":[],"tags":["Clothing","Gaming \/ RPG"],"author":"Michael Irigoyen","version":"5.2.45"},{"id":"0059A2CA-E266-4A57-9EE8-4520B7330D5C","name":"wordpress","codepoint":"F05B4","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"79D47101-F8CB-496B-99B0-957DADED5D44","name":"wrap","codepoint":"F05B6","aliases":[],"tags":[],"author":"Doug C. Hardester","version":"1.5.54"},{"id":"44C4926C-7F82-4A6A-8F55-A7B23E56A9D7","name":"wrap-disabled","codepoint":"F0BDF","aliases":["unwrap"],"tags":[],"author":"Contributors","version":"3.0.39"},{"id":"CACAAE64-D38D-423E-8C84-68EFF0EA0F8A","name":"wrench","codepoint":"F05B7","aliases":["build","spanner"],"tags":["Hardware \/ Tools"],"author":"Google","version":"1.5.54"},{"id":"040BA3F6-86B3-4597-9EBE-C6D6A916091D","name":"wrench-outline","codepoint":"F0BE0","aliases":["build-outline","spanner-outline"],"tags":["Hardware \/ Tools"],"author":"Google","version":"3.0.39"},{"id":"958B8A8B-A4D7-45A4-8C80-39F7140443C0","name":"xamarin","codepoint":"F0845","aliases":["microsoft-xamarin"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.19"},{"id":"7016027D-C32A-4462-A9E5-98132FA518B4","name":"xamarin-outline","codepoint":"F0846","aliases":["microsoft-xamarin-outline"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.1.19"},{"id":"5415674F-E6F6-433D-9A9F-E976FD7245F8","name":"xing","codepoint":"F05BE","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.5.54"},{"id":"994C18D8-DAF1-4311-A30B-CD93F5ADC233","name":"xml","codepoint":"F05C0","aliases":["code"],"tags":["Developer \/ Languages"],"author":"Austin Andrews","version":"1.5.54"},{"id":"F2F74E7E-9EC8-4748-AF3B-A14D6158770D","name":"xmpp","codepoint":"F07FF","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.0.46"},{"id":"A19711E4-E339-4016-970B-F81D14B303AC","name":"y-combinator","codepoint":"F0624","aliases":["hackernews"],"tags":["Brand \/ Logo"],"author":"Contributors","version":"1.6.50"},{"id":"63AB3732-B3D1-4AFA-81B5-5D0F40E5D0E0","name":"yahoo","codepoint":"F0B4F","aliases":[],"tags":["Brand \/ Logo"],"author":"Contributors","version":"2.8.94"},{"id":"17C0DA66-AB24-4935-A928-26BE13FDC3C0","name":"yeast","codepoint":"F05C1","aliases":[],"tags":[],"author":"Austin Andrews","version":"1.5.54"},{"id":"068670F6-B9DF-40C5-8C50-C9A3953F6201","name":"yin-yang","codepoint":"F0680","aliases":["taoism"],"tags":[],"author":"Austin Andrews","version":"1.7.12"},{"id":"82F65F53-8458-4F6D-8151-D20FFDDC09C2","name":"yoga","codepoint":"F117C","aliases":[],"tags":["Sport"],"author":"Michael Irigoyen","version":"4.4.95"},{"id":"0A078909-90AF-41F5-8E76-CAB565D49AAA","name":"youtube","codepoint":"F05C3","aliases":["video-youtube","youtube-play"],"tags":["Brand \/ Logo","Social Media"],"author":"Google","version":"1.5.54"},{"id":"9C80F67A-8A15-4109-BA37-7B92FE1F67DB","name":"youtube-gaming","codepoint":"F0848","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"2.1.19"},{"id":"7150F7D3-B162-41DE-80A8-5DFD930EDF1B","name":"youtube-studio","codepoint":"F0847","aliases":["youtube-creator-studio"],"tags":["Brand \/ Logo"],"author":"Google","version":"2.1.19"},{"id":"E06EE7FD-6CC5-4BB4-9B00-1397D6E18DDF","name":"youtube-subscription","codepoint":"F0D40","aliases":[],"tags":[],"author":"Google","version":"3.3.92"},{"id":"011BAC94-8FD5-4335-AFF3-120C04299E78","name":"youtube-tv","codepoint":"F0448","aliases":[],"tags":["Brand \/ Logo"],"author":"Google","version":"1.5.54"},{"id":"9BCCFDB1-42DE-4807-BF9B-36AD3B40B996","name":"yurt","codepoint":"F1516","aliases":[],"tags":[],"author":"Colton Wiscombe","version":"5.4.55"},{"id":"6A2E5A75-34CC-4B32-A1F6-156803328935","name":"z-wave","codepoint":"F0AEA","aliases":["zwave"],"tags":[],"author":"Contributors","version":"2.7.94"},{"id":"989885C5-DF4B-4B6E-B17B-7E74F2AEE1DB","name":"zend","codepoint":"F0AEB","aliases":[],"tags":["Developer \/ Languages"],"author":"Contributors","version":"2.7.94"},{"id":"C4D3EAAC-C54B-4406-BCB4-8C08E2B07451","name":"zigbee","codepoint":"F0D41","aliases":[],"tags":[],"author":"Contributors","version":"3.3.92"},{"id":"00A83C35-A726-464B-ACEE-F0D690045C25","name":"zip-box","codepoint":"F05C4","aliases":["compressed-file"],"tags":["Files \/ Folders"],"author":"Google","version":"1.5.54"},{"id":"19E804D8-154F-4250-82D3-76F5401B5674","name":"zip-box-outline","codepoint":"F0FFA","aliases":["compressed-file-outline"],"tags":["Files \/ Folders"],"author":"Michael Irigoyen","version":"4.0.96"},{"id":"775EA566-CF0B-473E-B43E-59319FC83D38","name":"zip-disk","codepoint":"F0A23","aliases":[],"tags":[],"author":"GreenTurtwig","version":"2.5.94"},{"id":"8E27593E-7C4E-41F7-A238-865DA00CDEE7","name":"zodiac-aquarius","codepoint":"F0A7D","aliases":["horoscope-aquarius"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"8DC63282-63B3-4F4A-B976-2346FC3B7CFA","name":"zodiac-aries","codepoint":"F0A7E","aliases":["horoscope-aries"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"DCBC9ECE-641C-40E1-BD15-2F02F8412780","name":"zodiac-cancer","codepoint":"F0A7F","aliases":["horoscope-cancer"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"6310BE95-A7A4-4A4C-A478-059DCA6C4E0B","name":"zodiac-capricorn","codepoint":"F0A80","aliases":["horoscope-capricorn"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"ECDB16AC-832D-446E-974E-9F99657685D0","name":"zodiac-gemini","codepoint":"F0A81","aliases":["horoscope-gemini"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"D280F50D-92FC-4DA2-BBAD-CE93140E6FEA","name":"zodiac-leo","codepoint":"F0A82","aliases":["horoscope-leo"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"142861F0-C930-43ED-B186-4BD97C175394","name":"zodiac-libra","codepoint":"F0A83","aliases":["horoscope-libra"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"3410C5F7-CAEF-405C-9159-86F38ACE9619","name":"zodiac-pisces","codepoint":"F0A84","aliases":["horoscope-pisces"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"1FC91C87-E02C-4830-B0A6-6EA7CDABB8D3","name":"zodiac-sagittarius","codepoint":"F0A85","aliases":["horoscope-sagittarius"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"0AEE35B6-4A9F-422A-BCC8-395174DCBA71","name":"zodiac-scorpio","codepoint":"F0A86","aliases":["horoscope-scorpio"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"40205151-C976-49D8-98F1-A0E120086E07","name":"zodiac-taurus","codepoint":"F0A87","aliases":["horoscope-taurus"],"tags":[],"author":"Michael Richins","version":"2.6.95"},{"id":"41D13BD9-7CB3-4015-A845-485B9915FA65","name":"zodiac-virgo","codepoint":"F0A88","aliases":["horoscope-virgo"],"tags":[],"author":"Michael Richins","version":"2.6.95"}] \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java b/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java index 301f07bd1..47f4c1bc0 100644 --- a/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java +++ b/src/test/java/de/bonndan/nivio/SchemaGenerationTest.java @@ -19,14 +19,14 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Map; +import java.util.TreeMap; public class SchemaGenerationTest { @Test void generateDocs() { Components components = new Components(); - Map schema = ModelConverters.getInstance().readAll(new AnnotatedType(LandscapeDescription.class)); - components.setSchemas(schema); + components.setSchemas(getSchemaMap()); OpenAPI openAPI = new OpenAPI(); openAPI.setComponents(components); openAPI.setPaths(new Paths()); @@ -55,4 +55,14 @@ void generateDocs() { defaultGenerator.opts(config); defaultGenerator.generate(); } + + @SuppressWarnings("rawtypes") + private Map getSchemaMap() { + Map stringSchemaMap = ModelConverters.getInstance().readAll(new AnnotatedType(LandscapeDescription.class)); + stringSchemaMap.keySet().forEach(s -> { + Schema schema = stringSchemaMap.get(s); + schema.setProperties(new TreeMap(schema.getProperties())); + }); + return stringSchemaMap; + } } diff --git a/src/test/java/de/bonndan/nivio/api/ApiControllerTest.java b/src/test/java/de/bonndan/nivio/api/ApiControllerTest.java new file mode 100644 index 000000000..4df5cf7b6 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/api/ApiControllerTest.java @@ -0,0 +1,122 @@ +package de.bonndan.nivio.api; + +import de.bonndan.nivio.input.IndexingDispatcher; +import de.bonndan.nivio.model.*; +import de.bonndan.nivio.output.dto.GroupApiModel; +import de.bonndan.nivio.output.dto.ItemApiModel; +import de.bonndan.nivio.output.dto.LandscapeApiModel; +import de.bonndan.nivio.search.ItemIndex; +import de.bonndan.nivio.util.FrontendMapping; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class ApiControllerTest { + LinkFactory linkFactory; + IndexingDispatcher indexingDispatcher; + LandscapeRepository landscapeRepository; + FrontendMapping frontendMapping; + ApiController apiController; + + @BeforeEach + void setUp() { + linkFactory = Mockito.mock(LinkFactory.class); + indexingDispatcher = Mockito.mock(IndexingDispatcher.class); + landscapeRepository = Mockito.mock(LandscapeRepository.class); + frontendMapping = Mockito.mock(FrontendMapping.class); + apiController = new ApiController(landscapeRepository, linkFactory, indexingDispatcher, frontendMapping); + } + + @Test + void index() { + var index = Mockito.mock(Index.class); + Mockito.when(linkFactory.getIndex(landscapeRepository.findAll())).thenReturn(index); + assertThat(apiController.index()).isEqualTo(index); + } + + @Test + void landscape() { + var landscape = Mockito.mock(Landscape.class); + Mockito.when(landscapeRepository.findDistinctByIdentifier("")).thenReturn(Optional.empty()); + assertThat(apiController.landscape("")).isEqualTo(ResponseEntity.notFound().build()); + Mockito.when(landscapeRepository.findDistinctByIdentifier("test")).thenReturn(Optional.of(landscape)); + assertThat(apiController.landscape("test").getClass()).isEqualTo(ResponseEntity.class); + assertThat(apiController.landscape("test").getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(apiController.landscape("test").getBody()).isEqualToComparingFieldByField(new LandscapeApiModel(landscape)); + } + + @Test + void group() { + var landscape = Mockito.mock(Landscape.class); + Mockito.when(landscapeRepository.findDistinctByIdentifier("")).thenReturn(Optional.empty()); + assertThat(apiController.group("", "")).isEqualTo(ResponseEntity.notFound().build()); + Mockito.when(landscapeRepository.findDistinctByIdentifier("test")).thenReturn(Optional.of(landscape)); + Mockito.when(landscape.getGroup("test")).thenReturn(Optional.of(new Group("test", "test"))); + Mockito.when(landscape.getItems()).thenReturn(new ItemIndex<>(Item.class)); + + assertThat(apiController.group("test", "test").getClass()).isEqualTo(ResponseEntity.class); + assertThat(apiController.group("test", "test").getStatusCode()).isEqualTo(HttpStatus.OK); + Group test = landscape.getGroup("test").get(); + assertThat(apiController.group("test", "test").getBody()).isEqualToComparingFieldByField(new GroupApiModel(test, landscape.getItems().retrieve(test.getItems()))); + } + + @Test + void item() { + var landscape = Mockito.mock(Landscape.class); + var item = Mockito.mock(Item.class); + var itemIndex = new ItemIndex<>(Item.class); + Mockito.when(item.getFullyQualifiedIdentifier()).thenReturn(FullyQualifiedIdentifier.build("test", "test", "test")); + Mockito.when(landscapeRepository.findDistinctByIdentifier("")).thenReturn(Optional.empty()); + assertThat(apiController.item("test", "test", "test")).isEqualTo(ResponseEntity.notFound().build()); + Mockito.when(landscape.getItems()).thenReturn(itemIndex); + assertThat(apiController.item("test", "test", "test")).isEqualTo(ResponseEntity.notFound().build()); + itemIndex.add(item); + + Mockito.when(landscapeRepository.findDistinctByIdentifier("test")).thenReturn(Optional.of(landscape)); + Mockito.when(landscape.getGroup("test")).thenReturn(Optional.of(new Group("test", "test"))); + assertThat(apiController.item("test", "test", "test").getClass()).isEqualTo(ResponseEntity.class); + assertThat(apiController.item("test", "test", "test").getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(apiController.item("test", "test", "test").getBody()).isEqualToComparingFieldByField(new ItemApiModel(item, landscape.getGroup("test").get())); + } + + + @Test + void search() { + var landscape = Mockito.mock(Landscape.class); + var item1 = Mockito.mock(Item.class); + var item2 = Mockito.mock(Item.class); + Mockito.when(item1.getGroup()).thenReturn("test"); + Mockito.when(item2.getGroup()).thenReturn("test"); + Mockito.when(landscapeRepository.findDistinctByIdentifier("")).thenReturn(Optional.empty()); + assertThat(apiController.search("", "test")).isEqualTo(ResponseEntity.notFound().build()); + Mockito.when(landscapeRepository.findDistinctByIdentifier("test")).thenReturn(Optional.of(landscape)); + Mockito.when(landscape.getGroups()).thenReturn(Map.of("test", new Group("test", "test"))); + Mockito.when(landscape.getGroup("test")).thenReturn(Optional.of(new Group("test", "test"))); + Mockito.when(landscape.search("test")).thenReturn(Set.of(item1, item2)); + assertThat(apiController.search("test", "test").getClass()).isEqualTo(ResponseEntity.class); + assertThat(apiController.search("test", "test").getStatusCode()).isEqualTo(HttpStatus.OK); + var hashSet = new HashSet(); + assertThat(apiController.search("test", "test").getBody().size()).isEqualTo(2); + } + + @Test + void mapping() { + Mockito.when(frontendMapping.getKeys()).thenReturn(Map.of("testKey", "testValue")); + assertThat(apiController.mapping().getBody()).isEqualTo(Map.of("testKey", "testValue")); + } + + @Test + void description() { + Mockito.when(frontendMapping.getDescriptions()).thenReturn(Map.of("testKey", "testValue")); + assertThat(apiController.description().getBody()).isEqualTo(Map.of("testKey", "testValue")); + } +} diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessableGroupTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessableGroupTest.java new file mode 100644 index 000000000..4e000842b --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/AssessableGroupTest.java @@ -0,0 +1,20 @@ +package de.bonndan.nivio.assessment; + +import de.bonndan.nivio.model.Group; +import de.bonndan.nivio.model.GroupFactory; +import de.bonndan.nivio.model.Labeled; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class AssessableGroupTest { + + @Test + void getLabels() { + AssessableGroup group = new AssessableGroup(new Group("foo", "bar"), new HashSet<>()); + assertThat(group).isInstanceOf(Labeled.class); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java index 57b28fc8b..0c582a6f6 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessableTest.java @@ -2,16 +2,15 @@ import de.bonndan.nivio.assessment.kpi.AbstractKPI; import de.bonndan.nivio.assessment.kpi.KPI; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.output.dto.RangeApiModel; +import de.bonndan.nivio.model.*; import org.junit.jupiter.api.Test; import org.springframework.lang.NonNull; import java.util.*; +import java.util.function.Function; -import static de.bonndan.nivio.assessment.StatusValue.SUMMARY_LABEL; +import static de.bonndan.nivio.assessment.Assessable.getWorst; import static de.bonndan.nivio.model.ItemFactory.getTestItem; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; @@ -24,42 +23,40 @@ void getSummaryHighest() { var child1 = new TestAssessable(null); List statusValues = List.of( - new StatusValue("test1", Status.GREEN), - new StatusValue("test2", Status.GREEN), - new StatusValue("test3", Status.RED, "worst") + new StatusValue("foo", "test1", Status.GREEN, ""), + new StatusValue("foo", "test2", Status.GREEN, ""), + new StatusValue("foo", "test2", Status.ORANGE, ""), + new StatusValue("foo", "test3", Status.RED, "broken"), + new StatusValue("foo", "test4", Status.RED, "out of order") ); - StatusValue max = statusValues.stream() - .filter(Objects::nonNull) - .max(new StatusValue.Comparator()) - .orElse(new StatusValue(SUMMARY_LABEL, Status.UNKNOWN)); + List max = getWorst(new ArrayList<>(statusValues)); - StatusValue summary = StatusValue.summary(SUMMARY_LABEL + "." + child1.getIdentifier(), max); + StatusValue summary = StatusValue.summary("foo", max); assertNotNull(summary); assertEquals(Status.RED, summary.getStatus()); - assertEquals("worst", summary.getMessage()); - assertEquals("test3", summary.getMaxField()); + assertEquals("foo test3: broken; foo test4: out of order", summary.getMessage()); } @Test void skipsDisabledKPIs() { var child1 = new TestAssessable(null); - child1.setStatusValue(new StatusValue("test", Status.GREEN)); - child1.setStatusValue(new StatusValue("test2", Status.YELLOW)); + child1.setStatusValue(new StatusValue("foo", "test", Status.GREEN, "")); + child1.setStatusValue(new StatusValue("foo", "test2", Status.YELLOW, "")); var child2 = new TestAssessable(null); - child2.setStatusValue(new StatusValue("test", Status.GREEN)); + child2.setStatusValue(new StatusValue("foo", "test", Status.GREEN, "")); var parent = new TestAssessable(List.of(child1, child2)); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override - protected List getStatusValues(String value, String message) { + protected List getStatusValues(Assessable assessable, String value, String message) { return new ArrayList<>(); } }); - var disabled = new AbstractKPI(component -> null, null) { + var disabled = new TestKPI(component -> null, null) { @Override - protected List getStatusValues(String value, String message) { + protected List getStatusValues(Assessable assessable, String value, String message) { throw new RuntimeException("This should never happen."); } }; @@ -70,30 +67,29 @@ protected List getStatusValues(String value, String message) { } @Test - public void withItem() { + void withItem() { Item item = getTestItem("foo", "bar"); item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_STATUS), Status.BROWN.getName()); item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_MESSAGE), "very bad"); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override - protected List getStatusValues(String value, String message) { + protected List getStatusValues(Assessable assessable, String value, String message) { return new ArrayList<>(); } }); //when - Map> assessmentMap = item.applyKPIs(kpis); + Map> assessmentMap = item.applyKPIs(kpis); //then assertNotNull(assessmentMap); - List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier()); + List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier().toString()); assertNotNull(itemStatuses); - StatusValue statusValue = itemStatuses.stream().filter(statusValue1 -> statusValue1.getField().equals("summary.bar")).findFirst().orElse(null); + StatusValue statusValue = itemStatuses.stream().filter(statusValue1 -> statusValue1.getField().equals(StatusValue.SUMMARY_FIELD_VALUE)).findFirst().orElse(null); assertNotNull(statusValue); - assertEquals("summary.bar", statusValue.getField()); StatusValue something = itemStatuses.stream().filter(statusValue1 -> statusValue1.getField().equals("something")).findFirst().orElse(null); assertNotNull(something); @@ -103,27 +99,27 @@ protected List getStatusValues(String value, String message) { } @Test - public void uniqueStatusLists() { + void uniqueStatusLists() { Item item = getTestItem("foo", "bar"); item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_STATUS), Status.BROWN.getName()); item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_MESSAGE), "very bad"); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override - protected List getStatusValues(String value, String message) { + protected List getStatusValues(Assessable assessable, String value, String message) { return List.of( - new StatusValue("something", Status.RED, "newer value") + new StatusValue(item.getAssessmentIdentifier(), "something", Status.RED, "newer value") ); } }); //when - Map> assessmentMap = item.applyKPIs(kpis); + Map> assessmentMap = item.applyKPIs(kpis); //then assertNotNull(assessmentMap); - List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier()); + List itemStatuses = assessmentMap.get(item.getFullyQualifiedIdentifier().toString()); assertNotNull(itemStatuses); assertThat(itemStatuses).hasSize(2); @@ -133,45 +129,45 @@ protected List getStatusValues(String value, String message) { } @Test - public void groupSummary() { + void groupSummary() { Item item = getTestItem("foo", "bar"); - item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_STATUS), Status.BROWN.getName()); - item.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_MESSAGE), "very bad"); + item.setLabel(Label.withPrefix(Label.status, "someKPI", StatusValue.LABEL_SUFFIX_STATUS), Status.BROWN.getName()); + item.setLabel(Label.withPrefix(Label.status, "someKPI", StatusValue.LABEL_SUFFIX_MESSAGE), "very bad"); Item item2 = getTestItem("foo", "baz"); - item2.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_STATUS), Status.RED.getName()); - item2.setLabel(Label.withPrefix(Label.status, "something", StatusValue.LABEL_SUFFIX_MESSAGE), "not so bad"); + item2.setLabel(Label.withPrefix(Label.status, "someKPI", StatusValue.LABEL_SUFFIX_STATUS), Status.RED.getName()); + item2.setLabel(Label.withPrefix(Label.status, "someKPI", StatusValue.LABEL_SUFFIX_MESSAGE), "not so bad"); - Group foo = new Group("foo", "landscapeIdentifier"); - foo.addItem(item); - foo.addItem(item2); + Group foo = new Group("foo", "test"); + foo.addOrReplaceItem(item); + foo.addOrReplaceItem(item2); + + AssessableGroup assessableGroup = new AssessableGroup(foo, Set.of(item, item2)); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override - protected List getStatusValues(String value, String message) { + protected List getStatusValues(@NonNull final Assessable assessable, String value, String message) { return new ArrayList<>(); } }); //when - Map> groupStatuses = foo.applyKPIs(kpis); + Map> groupStatuses = assessableGroup.applyKPIs(kpis); //then - List statusValues = groupStatuses.get(foo.getFullyQualifiedIdentifier()); + List statusValues = groupStatuses.get(assessableGroup.getAssessmentIdentifier()); assertNotNull(statusValues); //group summary - StatusValue statusValue = statusValues.stream().filter(statusValue1 -> statusValue1.getField().equals("summary.foo")).findFirst().orElse(null); + StatusValue statusValue = statusValues.stream().filter(statusValue1 -> statusValue1.getField().equals(StatusValue.SUMMARY_FIELD_VALUE)).findFirst().orElse(null); assertNotNull(statusValue); - assertEquals("summary.foo", statusValue.getField()); assertEquals(Status.BROWN, statusValue.getStatus()); - assertEquals("very bad", statusValue.getMessage()); - assertEquals("summary.bar", statusValue.getMaxField()); + assertEquals("test/foo/bar somekpi: very bad", statusValue.getMessage()); } @Test - public void isSorted() { + void isSorted() { Item item = getTestItem("foo", "bar"); item.setLabel(Label.withPrefix(Label.status, "foo", StatusValue.LABEL_SUFFIX_STATUS), Status.BROWN.getName()); item.setLabel(Label.withPrefix(Label.status, "foo", StatusValue.LABEL_SUFFIX_MESSAGE), "very bad"); @@ -183,18 +179,18 @@ public void isSorted() { item.setLabel(Label.withPrefix(Label.status, "baz", StatusValue.LABEL_SUFFIX_MESSAGE), "not so bad"); Map kpis = new HashMap<>(); - kpis.put("on", new AbstractKPI(component -> null, null) { + kpis.put("on", new TestKPI(component -> null, null) { @Override - protected List getStatusValues(String value, String message) { + protected List getStatusValues(Assessable assessable, String value, String message) { return new ArrayList<>(); } }); //when - Map> statuses = item.applyKPIs(kpis); + Map> statuses = item.applyKPIs(kpis); //then - List statusValues = statuses.get(item.getFullyQualifiedIdentifier()); + List statusValues = statuses.get(item.getFullyQualifiedIdentifier().toString()); assertNotNull(statusValues); assertEquals(4, statusValues.size()); StatusValue summary = statusValues.get(0); @@ -207,9 +203,9 @@ protected List getStatusValues(String value, String message) { assertThat(s2.getStatus().compareTo(s3.getStatus())).isEqualTo(1); } - class TestAssessable implements Assessable { + static class TestAssessable implements Assessable { - private Set statusValues = new HashSet<>(); + private final Set statusValues = new HashSet<>(); private final List children; TestAssessable(List children) { @@ -225,54 +221,35 @@ void setStatusValue(@NonNull StatusValue statusValue) { getAdditionalStatusValues().add(statusValue); } - @Override + @NonNull public String getIdentifier() { return "test"; } @Override - public FullyQualifiedIdentifier getFullyQualifiedIdentifier() { - return FullyQualifiedIdentifier.build("test", null, null); - } - - @Override - public String getName() { - return "test"; - } - - @Override - public String getContact() { - return "test"; - } - - @Override - public String getDescription() { + public String getAssessmentIdentifier() { return "test"; } @Override - public String getOwner() { - return null; + public List getChildren() { + return children; } + } - @Override - public String getIcon() { - return null; + private abstract static class TestKPI extends AbstractKPI { + public TestKPI(Function valueFunction, Function msgFunction) { + super(valueFunction, msgFunction); } @Override - public String getColor() { + public Map getRanges() { return null; } @Override - public String getAddress() { + public Map> getMatches() { return null; } - - @Override - public List getChildren() { - return children; - } } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java index 5430b6b87..f9c9759b9 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessmentFactoryTest.java @@ -10,7 +10,7 @@ import java.util.*; -import static de.bonndan.nivio.assessment.AssessmentFactory.ASSESSMENTERRORNULL; +import static de.bonndan.nivio.assessment.AssessmentFactory.ASSESSMENT_ERROR_NULL; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -43,8 +43,8 @@ void getAssessmentFromFactoryLandscape() { void getAssessmentFromFactoryMap() { var fqi = FullyQualifiedIdentifier.build("test1", "test2", "test3"); var statusList = new ArrayList(); - var results = new HashMap>(); - results.put(fqi, statusList); + var results = new HashMap>(); + results.put(fqi.toString(), statusList); var assessment = AssessmentFactory.createAssessment(results); assertThat(assessment.getClass()).isEqualTo(Assessment.class); } @@ -53,10 +53,10 @@ void getAssessmentFromFactoryMap() { @Test void testNullValues() { var exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment(null, null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); + assertThat(exception.getMessage()).isEqualTo(ASSESSMENT_ERROR_NULL); exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment((Landscape) null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); - exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment((Map>) null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); + assertThat(exception.getMessage()).isEqualTo(ASSESSMENT_ERROR_NULL); + exception = assertThrows(NullPointerException.class, () -> AssessmentFactory.createAssessment((Map>) null)); + assertThat(exception.getMessage()).isEqualTo(ASSESSMENT_ERROR_NULL); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java b/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java index 653a99a45..74498aca4 100644 --- a/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/AssessmentRepositoryTest.java @@ -9,11 +9,9 @@ import java.util.Set; -import static de.bonndan.nivio.assessment.AssessmentFactory.ASSESSMENTERRORNULL; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; - class AssessmentRepositoryTest { private static Landscape landscape; @@ -34,15 +32,15 @@ void cleanAssessmentRepository() { } @Test - void testNull() { - var getValue = assessmentRepository.getAssessment(null); - assertThat(getValue).isNotPresent(); - } + void testSaveAndGet() { + //given + var assessment = Assessment.empty(); + assessmentRepository.save(landscape.getFullyQualifiedIdentifier(), assessment); - @Test - void testGetExistingElement() { - var assessment = assessmentRepository.createAssessment(landscape); + //when var storedAssessment = assessmentRepository.getAssessment(landscape.getFullyQualifiedIdentifier()); + + //then assertThat(storedAssessment).isPresent().contains(assessment); } @@ -55,8 +53,8 @@ void testGetNonExistingElement() { @Test void testIllegalArgumentExceptionGet() { - var exception = assertThrows(NullPointerException.class, () -> assessmentRepository.createAssessment(null)); - assertThat(exception.getMessage()).isEqualTo(ASSESSMENTERRORNULL); + var exception = assertThrows(NullPointerException.class, () -> assessmentRepository.getAssessment(null)); + assertThat(exception.getMessage()).isEqualTo("Null instead of FQI given"); } } diff --git a/src/test/java/de/bonndan/nivio/assessment/ProcessingEventListenerTest.java b/src/test/java/de/bonndan/nivio/assessment/ProcessingEventListenerTest.java new file mode 100644 index 000000000..acc462402 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/ProcessingEventListenerTest.java @@ -0,0 +1,46 @@ +package de.bonndan.nivio.assessment; + +import de.bonndan.nivio.input.LandscapeDescriptionFactory; +import de.bonndan.nivio.input.ProcessingChangelog; +import de.bonndan.nivio.input.ProcessingFinishedEvent; +import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.context.ApplicationEventPublisher; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +class ProcessingEventListenerTest { + + private ProcessingEventListener listener; + private AssessmentRepository repo; + private ApplicationEventPublisher publisher; + + @BeforeEach + void setUp() { + repo = mock(AssessmentRepository.class); + publisher = mock(ApplicationEventPublisher.class); + listener = new ProcessingEventListener(repo, publisher); + } + + @Test + void onProcessingFinishedEvent() { + //given + Landscape landscape = LandscapeFactory.createForTesting("foo", "bar").build(); + LandscapeDescription description = new LandscapeDescription("foo"); + ProcessingFinishedEvent e = new ProcessingFinishedEvent(description, landscape, mock(ProcessingChangelog.class)); + + //when + listener.onProcessingFinishedEvent(e); + + //then + verify(repo).save(eq(landscape.getFullyQualifiedIdentifier()), any(Assessment.class)); + verify(publisher).publishEvent(any(AssessmentChangedEvent.class)); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/StatusTest.java b/src/test/java/de/bonndan/nivio/assessment/StatusTest.java new file mode 100644 index 000000000..2762d8c96 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/StatusTest.java @@ -0,0 +1,17 @@ +package de.bonndan.nivio.assessment; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class StatusTest { + + @Test + void comparator() { + Status green = Status.GREEN; + Status red = Status.RED; + assertEquals(-1, new Status.Comparator().compare(green, red)); + assertEquals(0, new Status.Comparator().compare(green, green)); + assertEquals(1, new Status.Comparator().compare(red, green)); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java b/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java index 8dc626ab7..a7c04cc18 100644 --- a/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/StatusValueTest.java @@ -13,33 +13,36 @@ class StatusValueTest { @Test void mustHaveField() { - assertThrows(IllegalArgumentException.class, () -> {new StatusValue(null, Status.GREEN);}); + assertThrows(IllegalArgumentException.class, () -> new StatusValue(null, "foo", Status.GREEN, "")); + assertThrows(IllegalArgumentException.class, () -> new StatusValue("foo", null, Status.GREEN, "")); } @Test void comparator() { - StatusValue green = new StatusValue("foo", Status.GREEN); - StatusValue red = new StatusValue("foo", Status.RED); - assertEquals(-1, new StatusValue.Comparator().compare(green, red)); + StatusValue green = new StatusValue("foo", "bar", Status.GREEN, ""); + StatusValue red = new StatusValue("foo", "bar", Status.RED, ""); + StatusValue yellow = new StatusValue("foo", "bar", Status.YELLOW, ""); + assertEquals(-3, new StatusValue.Comparator().compare(green, red)); assertEquals(0, new StatusValue.Comparator().compare(green, green)); - assertEquals(1, new StatusValue.Comparator().compare(red, green)); + assertEquals(1, new StatusValue.Comparator().compare(yellow, green)); + assertEquals(3, new StatusValue.Comparator().compare(red, green)); } @Test void isNotSummary() { - StatusValue statusValue = new StatusValue("security", Status.BROWN, "epically broken"); + StatusValue statusValue = new StatusValue("foo", "security", Status.BROWN, "epically broken"); assertFalse(statusValue.isSummary()); } @Test void summary() { - StatusValue summary = StatusValue.summary("foo.bar", new StatusValue("security", Status.BROWN, "epically broken")); + StatusValue summary = StatusValue.summary("foo", Collections.singletonList(new StatusValue("foo", "security", Status.BROWN, "epically broken"))); assertNotNull(summary); - assertEquals("foo.bar", summary.getField()); - assertEquals("epically broken", summary.getMessage()); + assertEquals("foo", summary.getIdentifier()); + assertEquals(StatusValue.SUMMARY_FIELD_VALUE, summary.getField()); + assertThat(summary.getMessage()).contains("epically broken").contains("security"); assertEquals(Status.BROWN, summary.getStatus()); - assertEquals("security", summary.getMaxField()); assertTrue(summary.isSummary()); } @@ -53,7 +56,7 @@ void fromMapping() { input.get("security").put(LABEL_SUFFIX_MESSAGE, "foobar"); //when - Set statusValues = StatusValue.fromMapping(input); + Set statusValues = StatusValue.fromMapping("foo", input); assertFalse(statusValues.isEmpty()); StatusValue security = statusValues.iterator().next(); assertEquals("security", security.getField()); @@ -64,6 +67,9 @@ void fromMapping() { @Test void isEqual() { //equality on field basis only to guarantee uniqueness - assertThat(new StatusValue("foo", Status.GREEN)).isEqualTo(new StatusValue("foo", Status.RED)); + assertThat(new StatusValue("foo", "bar", Status.GREEN, "")) + .isEqualTo(new StatusValue("foo", "bar", Status.RED, "")); + assertThat(new StatusValue("baz", "bar", Status.GREEN, "")) + .isNotEqualTo(new StatusValue("foo", "bar", Status.RED, "")); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/ConditionKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/ConditionKPITest.java index b39653031..25d47691e 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/ConditionKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/ConditionKPITest.java @@ -24,7 +24,7 @@ public void setup() { @Test public void testGreen() { Item item = getTestItem("null", "foo"); - item.setLabel(Label.condition.withPrefix("bar"), "True"); + item.setLabel(Label._condition.withPrefix("bar"), "True"); List statusValues = kpi.getStatusValues(item); assertEquals(1, statusValues.size()); @@ -34,8 +34,8 @@ public void testGreen() { @Test public void testRed() { Item item = getTestItem("null", "foo"); - item.setLabel(Label.condition.withPrefix("bar"), "True"); - item.setLabel(Label.condition.withPrefix("baz"), "False"); + item.setLabel(Label._condition.withPrefix("bar"), "True"); + item.setLabel(Label._condition.withPrefix("baz"), "False"); List statusValues = kpi.getStatusValues(item); assertEquals(1, statusValues.size()); diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java index cffec6ec5..bb8b3c218 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/CustomKPITest.java @@ -16,6 +16,7 @@ import java.util.Map; import static de.bonndan.nivio.model.ItemFactory.getTestItem; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; class CustomKPITest { @@ -48,6 +49,19 @@ void testWithRanges1(String value, String status) { Assertions.assertEquals(status, statusValue.getStatus().getName().toLowerCase(Locale.ROOT)); } + @Test + void testUsesConfigValues() { + CustomKPI test = new CustomKPI(); + kpiConfig.ranges = getRangeMap(); + kpiConfig.description = "bar"; + + //when + test.init(kpiConfig); + + //then + assertThat(test.getDescription()).isEqualTo("bar"); + } + @Test void testoutOfRange() { CustomKPI test = new CustomKPI(); diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java index a74c31f39..5a36cdb50 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/KPIFactoryTest.java @@ -1,11 +1,11 @@ package de.bonndan.nivio.assessment.kpi; -import de.bonndan.nivio.model.LandscapeConfig; -import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.assessment.Status; import de.bonndan.nivio.input.ProcessLog; -import de.bonndan.nivio.model.LandscapeFactory; +import de.bonndan.nivio.input.ProcessingException; import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeConfig; +import de.bonndan.nivio.model.LandscapeFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; @@ -14,7 +14,7 @@ import java.util.Map; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; class KPIFactoryTest { @@ -39,7 +39,7 @@ public void defaultKPIs() { Map configuredKPIs = kpiFactory.getConfiguredKPIs(landscapeConfig.getKPIs()); assertNotNull(configuredKPIs); - assertEquals(4, configuredKPIs.size()); + assertEquals(5, configuredKPIs.size()); assertTrue(configuredKPIs.get(ScalingKPI.IDENTIFIER) instanceof ScalingKPI); } diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/KPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/KPITest.java new file mode 100644 index 000000000..aa259e563 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/KPITest.java @@ -0,0 +1,58 @@ +package de.bonndan.nivio.assessment.kpi; + +import de.bonndan.nivio.assessment.Assessable; +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.assessment.StatusValue; +import de.bonndan.nivio.output.dto.RangeApiModel; +import org.junit.jupiter.api.Test; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class KPITest { + + @Test + void sorted() { + + KPI test = new KPI() { + @Override + public List getStatusValues(Assessable component) { + return null; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public boolean isEnabled() { + return false; + } + + @Override + public Map getRanges() { + return null; + } + + @Override + public Map> getMatches() { + return sorted( + Map.of(Status.RED, List.of("foo"), Status.BROWN, List.of("bar", "baz"), Status.GREEN, List.of("hihi")) + ); + } + }; + + //when + Map> matches = test.getMatches(); + + //then + Iterator iterator = matches.keySet().iterator(); + assertThat(iterator.next()).isEqualTo(Status.GREEN); + assertThat(iterator.next()).isEqualTo(Status.RED); + assertThat(iterator.next()).isEqualTo(Status.BROWN); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java new file mode 100644 index 000000000..11841fcec --- /dev/null +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/KubernetesKpiTest.java @@ -0,0 +1,97 @@ +package de.bonndan.nivio.assessment.kpi; + +import de.bonndan.nivio.assessment.Assessable; +import de.bonndan.nivio.assessment.Status; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.model.Item; +import de.bonndan.nivio.model.Landscape; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class KubernetesKpiTest { + KubernetesKPI kubernetesKPI; + private Item item; + + @BeforeEach + void setUp() { + kubernetesKPI = new KubernetesKPI(); + item = new Item("test", new Landscape("test", Map.of(), "test", null, null, null, null, null, null, Map.of()), "test", null, null, null, null, null, null, null, null); + } + + @Test + void boolTrue() { + assertThat(kubernetesKPI.getStatusValues(Mockito.mock(Assessable.class)).getClass()).isEqualTo(ArrayList.class); + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition.test", "true"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("test"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void boolFalse() { + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition.test", "false"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.RED); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("test"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void replicaa1() { + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.test", "a;1"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.ORANGE); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("ReadyReplicas count was null"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void replica1a() { + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.test", "1;a"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.ORANGE); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("Replicas count was null"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void replica22() { + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.test", "2;2"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("all pods are ready"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void replica12() { + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.test", "1;2"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.YELLOW); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("1 of 2 Pods are ready"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void replica02() { + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.test", "0;2"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.RED); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("0 of 2 Pods are ready"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void testcondition() { + item.setLabel(InputFormatHandlerKubernetes.LABEL_PREFIX + ".testcondition.test", Status.GREEN.toString()); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getStatus()).isEqualTo(Status.GREEN); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getMessage()).isEqualTo("testcondition.test"); + assertThat(kubernetesKPI.getStatusValues(item).get(0).getField()).isEqualTo("k8s:0"); + } + + @Test + void testGetSetEnabled() { + kubernetesKPI.setEnabled(false); + assertThat(kubernetesKPI.isEnabled()).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java index ba6f16006..bcd288be2 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/LifecycleKPITest.java @@ -33,7 +33,7 @@ public void green() { assertEquals(1, statusValues.size()); StatusValue statusValue = statusValues.get(0); assertEquals(Status.GREEN, statusValue.getStatus()); - assertEquals("Phase: production", statusValue.getMessage()); + assertEquals("phase: production", statusValue.getMessage()); } @Test diff --git a/src/test/java/de/bonndan/nivio/assessment/kpi/ScalingKPITest.java b/src/test/java/de/bonndan/nivio/assessment/kpi/ScalingKPITest.java index e1f23d365..185b41679 100644 --- a/src/test/java/de/bonndan/nivio/assessment/kpi/ScalingKPITest.java +++ b/src/test/java/de/bonndan/nivio/assessment/kpi/ScalingKPITest.java @@ -113,7 +113,7 @@ void yellowIfBottleneck() { assertEquals(1, statusValues.size()); StatusValue value = statusValues.get(0); assertEquals(Status.YELLOW, value.getStatus()); - assertEquals("Unscaled, but 2 items depend on it.", value.getMessage()); + assertEquals("unscaled, but 2 items depend on it", value.getMessage()); } @Test diff --git a/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java b/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java index 81c0c23e6..5e8b461e9 100644 --- a/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java +++ b/src/test/java/de/bonndan/nivio/config/NivioConfigPropertiesTest.java @@ -95,4 +95,7 @@ void checksBrandingMessage() { ConstraintViolation[] constraintViolations = (ConstraintViolation[]) validate.toArray(ConstraintViolation[]::new); assertThat(constraintViolations[0].getMessage()).isEqualTo("brandingMessage must be a valid string"); } + + + } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/AppearanceProcessorTest.java b/src/test/java/de/bonndan/nivio/input/AppearanceProcessorTest.java deleted file mode 100644 index f3c4dc0d0..000000000 --- a/src/test/java/de/bonndan/nivio/input/AppearanceProcessorTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package de.bonndan.nivio.input; - -import de.bonndan.nivio.model.*; -import de.bonndan.nivio.output.icons.DataUrlHelper; -import de.bonndan.nivio.output.icons.IconService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.HashSet; - -import static de.bonndan.nivio.model.ItemFactory.getTestItem; -import static de.bonndan.nivio.model.ItemFactory.getTestItemBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class AppearanceProcessorTest { - - private AppearanceProcessor resolver; - private Landscape landscape; - private IconService iconService; - private Group g1; - private ArrayList items; - - @BeforeEach - public void setup() { - - iconService = mock(IconService.class); - landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); - resolver = new AppearanceProcessor(new ProcessLog(LoggerFactory.getLogger(AppearanceProcessorTest.class), landscape.getIdentifier()), iconService); - - - g1 = new Group("g1", "landscapeIdentifier"); - landscape.addGroup(g1); - items = new ArrayList<>(); - - Item s1 = getTestItem("g1", "s1", landscape); - - s1.setLabel(Label.type, "loadbalancer"); - items.add(s1); - g1.addItem(s1); - - Item s2 = getTestItem("g1", "s2", landscape); - - s2.setLabel(Label.icon, "https://foo.bar/icon.png"); - items.add(s2); - g1.addItem(s2); - - landscape.setItems(new HashSet<>(items)); - } - - @Test - public void setsItemIcons() { - - Item pick = landscape.getItems().pick("s1", "g1"); - when(iconService.getIconUrl(eq(pick))).thenReturn(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); - //when - resolver.process(null, landscape); - - //then - - //check icon is set - assertThat(pick.getIcon()).isEqualTo(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); - } - - @Test - public void setsColor() { - - Item pick = landscape.getItems().pick("s1", "g1"); - when(iconService.getIconUrl(eq(pick))).thenReturn(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); - - //when - resolver.process(null, landscape); - - //then - assertThat(pick.getColor()).isEqualTo(g1.getColor()); - } - - @Test - public void doesNotOverwriteColor() { - - Item s3 = getTestItemBuilder("g1", "s3") - .withLandscape(landscape) - .withColor("00FFAA") - .build(); - landscape.getItems().add(s3); - g1.addItem(s3); - - Item pick = landscape.getItems().pick("s3", "g1"); - when(iconService.getIconUrl(eq(pick))).thenReturn(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); - - //when - resolver.process(null, landscape); - - //then - assertThat(pick.getColor()).isEqualTo("00ffaa"); - } -} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java b/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java index 65a8ee15d..e0b374c2f 100644 --- a/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java +++ b/src/test/java/de/bonndan/nivio/input/ComponentDescriptionValuesTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; class ComponentDescriptionValuesTest { diff --git a/src/test/java/de/bonndan/nivio/input/DiffProcessorTest.java b/src/test/java/de/bonndan/nivio/input/DiffProcessorTest.java index 370282998..999f44c56 100644 --- a/src/test/java/de/bonndan/nivio/input/DiffProcessorTest.java +++ b/src/test/java/de/bonndan/nivio/input/DiffProcessorTest.java @@ -40,8 +40,8 @@ public void setup() { items.add(s2); landscape.setItems(items); - g1.addItem(s1); - g1.addItem(s2); + g1.addOrReplaceItem(s1); + g1.addOrReplaceItem(s2); } @Test diff --git a/src/test/java/de/bonndan/nivio/input/HintTest.java b/src/test/java/de/bonndan/nivio/input/HintTest.java index 2d0ca64ef..b0b0d7472 100644 --- a/src/test/java/de/bonndan/nivio/input/HintTest.java +++ b/src/test/java/de/bonndan/nivio/input/HintTest.java @@ -100,7 +100,7 @@ void doesNotOverwriteExistingRelation() { RelationDescription relation = new RelationDescription(source.getIdentifier(), target.getIdentifier()); relation.setType(RelationType.DATAFLOW); - source.addRelation(relation); + source.addOrReplaceRelation(relation); //when hint.use(source, target, Optional.of(relation)); @@ -118,7 +118,7 @@ void setsTypeOnExistingRelation() { Hint hint = new Hint(ItemType.DATABASE, RelationType.PROVIDER, null); RelationDescription relation = new RelationDescription(source.getIdentifier(), target.getIdentifier()); - source.addRelation(relation); + source.addOrReplaceRelation(relation); //when hint.use(source, target, Optional.of(relation)); diff --git a/src/test/java/de/bonndan/nivio/input/IndexerIntegrationTest.java b/src/test/java/de/bonndan/nivio/input/IndexerIntegrationTest.java index ea2994ddd..6710d506c 100644 --- a/src/test/java/de/bonndan/nivio/input/IndexerIntegrationTest.java +++ b/src/test/java/de/bonndan/nivio/input/IndexerIntegrationTest.java @@ -4,7 +4,6 @@ import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.external.LinkHandlerFactory; import de.bonndan.nivio.model.*; -import de.bonndan.nivio.output.icons.IconService; import de.bonndan.nivio.search.ItemIndex; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -44,9 +43,6 @@ public class IndexerIntegrationTest { @Autowired LandscapeDescriptionFactory landscapeDescriptionFactory; - @Autowired - IconService iconService; - @Mock LinkHandlerFactory linkHandlerFactory; @@ -61,14 +57,15 @@ private Landscape index(String path) { File file = new File(getRootPath() + path); LandscapeDescription landscapeDescription = landscapeDescriptionFactory.fromYaml(file); - Indexer indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, applicationEventPublisher, iconService); + Indexer indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, applicationEventPublisher); indexer.index(landscapeDescription); return landscapeRepository.findDistinctByIdentifier(landscapeDescription.getIdentifier()).orElseThrow(); } - @Test //first pass - public void testIndexing() { + @Test + //first pass + void testIndexing() { Landscape landscape = index(); Assertions.assertNotNull(landscape); @@ -114,8 +111,9 @@ public void testIndexing() { assertEquals("http://acme.io/create", i.getUrl().toString()); } - @Test //second pass - public void testReIndexing() { + @Test + //second pass + void testReIndexing() { Landscape landscape = index(); Assertions.assertNotNull(landscape); @@ -164,7 +162,7 @@ public void testReIndexing() { * wordpress-web updates must not create new services */ @Test - public void testIncrementalUpdate() { + void testIncrementalUpdate() { Landscape landscape = index(); Item blog = landscape.getItems().pick("blog-server", null); int before = landscape.getItems().all().size(); @@ -184,7 +182,7 @@ public void testIncrementalUpdate() { exsistingWordPress.setName("Other name"); landscapeDescription.getItemDescriptions().add(exsistingWordPress); - Indexer indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, applicationEventPublisher, iconService); + Indexer indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, applicationEventPublisher); //created indexer.index(landscapeDescription); @@ -213,7 +211,7 @@ public void testIncrementalUpdate() { * Ensures that same names in different landscapes do not collide */ @Test - public void testNameConflictDifferentLandscapes() { + void testNameConflictDifferentLandscapes() { Landscape landscape1 = index("/src/test/resources/example/example_env.yml"); Landscape landscape2 = index("/src/test/resources/example/example_other.yml"); @@ -237,7 +235,7 @@ public void testNameConflictDifferentLandscapes() { * Ensures that same names in different landscapes do not collide */ @Test - public void testDataflow() { + void testDataflow() { Landscape landscape1 = index("/src/test/resources/example/example_dataflow.yml"); Assertions.assertNotNull(landscape1); @@ -257,7 +255,7 @@ public void testDataflow() { } @Test - public void environmentTemplatesApplied() { + void environmentTemplatesApplied() { Landscape landscape = index("/src/test/resources/example/example_templates.yml"); Item web = landscape.getItems().pick("web", null); @@ -267,7 +265,7 @@ public void environmentTemplatesApplied() { } @Test - public void readGroups() { + void readGroups() { Landscape landscape1 = index("/src/test/resources/example/example_env.yml"); Map groups = landscape1.getGroups(); assertTrue(groups.containsKey("content")); @@ -282,18 +280,18 @@ public void readGroups() { } @Test - public void readGroupsContains() { + void readGroupsContains() { Landscape landscape1 = index("/src/test/resources/example/example_groups.yml"); Group a = landscape1.getGroups().get("groupA"); ItemIndex index = new ItemIndex<>(Item.class); - index.setItems(new HashSet<>(a.getItems())); + index.setItems(new HashSet<>(landscape1.getItems().retrieve(a.getItems()))); assertNotNull(index.pick("blog-server", null)); assertNotNull(index.pick("crappy_dockername-234234", null)); } @Test - public void masksSecrets() { + void masksSecrets() { Landscape landscape1 = index("/src/test/resources/example/example_secret.yml"); Optional abc = landscape1.getItems().find("abc", null); assertThat(abc).isNotEmpty(); @@ -304,7 +302,7 @@ public void masksSecrets() { } @Test - public void labelRelations() { + void labelRelations() { Landscape landscape = index("/src/test/resources/example/example_label_relations.yml"); assertEquals(2, landscape.getGroups().size()); //common group is present by default assertEquals(2, landscape.getItems().all().size()); diff --git a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java index ab785d05b..9ca2e2267 100644 --- a/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java +++ b/src/test/java/de/bonndan/nivio/input/ItemDescriptionValuesTest.java @@ -5,7 +5,7 @@ import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.model.Label; import de.bonndan.nivio.model.Lifecycle; -import de.bonndan.nivio.model.RelationBuilder; +import de.bonndan.nivio.model.RelationFactory; import de.bonndan.nivio.model.RelationType; import org.junit.jupiter.api.Test; @@ -79,19 +79,42 @@ public void incrementAddsDataflow() { ItemDescription sd1 = new ItemDescription(); sd1.setIdentifier("sd1"); - RelationDescription other = RelationBuilder.createDataflowDescription(sd1, "other"); - sd1.addRelation(other); + RelationDescription other = RelationFactory.createDataflowDescription(sd1, "other"); + sd1.addOrReplaceRelation(other); ItemDescription increment = new ItemDescription(); increment.setIdentifier("sd1"); - RelationDescription another = RelationBuilder.createDataflowDescription(increment, "another"); - increment.addRelation(another); + RelationDescription another = RelationFactory.createDataflowDescription(increment, "another"); + increment.addOrReplaceRelation(another); ItemDescriptionValues.assignNotNull(sd1, increment); assertEquals(2, sd1.getRelations().size()); } + @Test + public void incrementUpdatesRelationDescription() { + + ItemDescription sd1 = new ItemDescription(); + sd1.setIdentifier("sd1"); + RelationDescription other = RelationFactory.createDataflowDescription(sd1, "other"); + sd1.addOrReplaceRelation(other); + + ItemDescription increment = new ItemDescription(); + increment.setIdentifier("sd1"); + RelationDescription another = RelationFactory.createDataflowDescription(increment, "other"); + another.setLabel("foo", "bar"); + increment.addOrReplaceRelation(another); + + //when + ItemDescriptionValues.assignNotNull(sd1, increment); + + + assertEquals(1, sd1.getRelations().size()); + RelationDescription relationDescription = sd1.getRelations().iterator().next(); + assertEquals("bar", relationDescription.getLabel("foo")); + } + @Test public void incrementAddsNetworks() { @@ -113,14 +136,14 @@ public void incrementAddsProvidedBy() { ItemDescription sd1 = new ItemDescription(); sd1.setIdentifier("sd1"); - RelationDescription dbProvider = RelationBuilder.createProviderDescription(sd1, "db1"); - sd1.addRelation(dbProvider); + RelationDescription dbProvider = RelationFactory.createProviderDescription(sd1, "db1"); + sd1.addOrReplaceRelation(dbProvider); ItemDescription increment = new ItemDescription(); increment.setIdentifier("sd1"); - RelationDescription redisProvider = RelationBuilder.createProviderDescription(sd1, "redis"); - increment.addRelation(redisProvider); + RelationDescription redisProvider = RelationFactory.createProviderDescription(sd1, "redis"); + increment.addOrReplaceRelation(redisProvider); ItemDescriptionValues.assignNotNull(sd1, increment); diff --git a/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java b/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java index 9f68bef82..65501f623 100644 --- a/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java +++ b/src/test/java/de/bonndan/nivio/input/ItemRelationProcessorTest.java @@ -5,6 +5,7 @@ import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.model.*; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; @@ -32,11 +33,11 @@ void setUp() { Item baz = ItemFactory.getTestItem("a", "baz"); items.add(baz); - foo.addOrReplace(new Relation(foo, bar)); - bar.addOrReplace(new Relation(foo, bar)); + foo.addOrReplace(RelationFactory.createForTesting(foo, bar)); + bar.addOrReplace(RelationFactory.createForTesting(foo, bar)); - foo.addOrReplace(new Relation(foo, baz)); - baz.addOrReplace(new Relation(foo, baz)); + foo.addOrReplace(RelationFactory.createForTesting(foo, baz)); + baz.addOrReplace(RelationFactory.createForTesting(foo, baz)); landscape = LandscapeFactory.createForTesting("test", "test").withItems(items).build(); @@ -48,13 +49,13 @@ void processAddsRelation() { ItemDescription description = new ItemDescription("foo"); description.setGroup("a"); - description.addRelation(new RelationDescription("foo", "bar")); - description.addRelation(new RelationDescription("foo", "baz")); + description.addOrReplaceRelation(new RelationDescription("foo", "bar")); + description.addOrReplaceRelation(new RelationDescription("foo", "baz")); input.mergeItems(List.of(description)); //new ItemDescription bar = new ItemDescription("bar"); bar.setGroup("a"); - bar.addRelation(new RelationDescription("bar", "baz")); + bar.addOrReplaceRelation(new RelationDescription("bar", "baz")); input.mergeItems(List.of(bar)); //when @@ -72,8 +73,8 @@ void processAddsUpdates() { description.setGroup("a"); RelationDescription relationItem = new RelationDescription("foo", "bar"); relationItem.setFormat("JSON"); - description.addRelation(relationItem); - description.addRelation(new RelationDescription("foo", "baz")); + description.addOrReplaceRelation(relationItem); + description.addOrReplaceRelation(new RelationDescription("foo", "baz")); input.mergeItems(List.of(description)); //when @@ -88,7 +89,35 @@ void processRemovesRelation() { ItemDescription description = new ItemDescription("foo"); description.setGroup("a"); - description.addRelation(new RelationDescription("foo", "bar")); + description.addOrReplaceRelation(new RelationDescription("foo", "bar")); + input.mergeItems(List.of(description)); + + //when + ProcessingChangelog process = processor.process(input, landscape); + + //then + assertThat(process.changes).hasSize(1); //no update, one delete + assertThat(process.changes).containsKey("test/a/foo;test/a/baz"); + assertThat(process.changes.get("test/a/foo;test/a/baz").getChangeType()).isEqualTo(ProcessingChangelog.ChangeType.DELETED.name()); + + Item foo = landscape.getItems().pick("foo", "a"); + assertThat(foo.getRelations()).hasSize(1); + + Item bar = landscape.getItems().pick("bar", "a"); + assertThat(bar.getRelations()).hasSize(1); + + Item baz = landscape.getItems().pick("baz", "a"); + assertThat(baz.getRelations()).hasSize(0); + } + + @DisplayName("removes relation even if ends cannot be found") + @Test + void regression647() { + + ItemDescription description = new ItemDescription("foo"); + description.setGroup("a"); + description.addOrReplaceRelation(new RelationDescription("foo", "bar")); + description.addOrReplaceRelation(new RelationDescription("foo", "somethingToDelete")); input.mergeItems(List.of(description)); //when diff --git a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java b/src/test/java/de/bonndan/nivio/input/KubernetesTest.java deleted file mode 100644 index 5f0aa2ef9..000000000 --- a/src/test/java/de/bonndan/nivio/input/KubernetesTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package de.bonndan.nivio.input; - -import de.bonndan.nivio.input.dto.ItemDescription; -import de.bonndan.nivio.input.dto.LandscapeDescription; -import de.bonndan.nivio.input.dto.SourceReference; -import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; -import io.fabric8.kubernetes.api.model.Container; -import io.fabric8.kubernetes.api.model.PodBuilder; -import io.fabric8.kubernetes.api.model.PodSpecBuilder; -import io.fabric8.kubernetes.api.model.PodStatusBuilder; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -@EnableKubernetesMockClient(crud = true) -public class KubernetesTest { - - static KubernetesClient client; - - @BeforeEach - void setup() { - List containers = new ArrayList<>(); - Container c1 = new Container(); - c1.setImage("postgres:9.5"); - c1.setName("mydb"); - containers.add(c1); - - var pod = new PodBuilder() - .withNewMetadata() - .withName("pod1") - .withNamespace("default") - .withLabels(Map.of("release", "testgroup")) - .endMetadata() - .withSpec( - new PodSpecBuilder() - .withContainers(containers) - .withNodeName("node1") - .build() - ) - .withStatus(new PodStatusBuilder().build()) - .build(); - client.pods().inNamespace("default").create(pod); - - } - - @Test - public void testRead() { - - SourceReference sourceReference = new SourceReference(null, "k8s"); - sourceReference.setUrl("http://localhost:80?groupLabel=release&namespace=default"); - - InputFormatHandlerKubernetes factory = new InputFormatHandlerKubernetes(java.util.Optional.ofNullable(client)); - factory.getConfiguration().setNamespace("default"); - - LandscapeDescription landscapeDescription = new LandscapeDescription("test"); - - //when - factory.applyData(sourceReference, null, landscapeDescription); - - //then - assertEquals(3, landscapeDescription.getItemDescriptions().all().size()); - - ItemDescription itemDescription = landscapeDescription.getItemDescriptions().all().stream() - .filter(itemDescription1 -> ItemType.POD.equals(itemDescription1.getType())) - .findFirst() - .get(); - assertNotNull(itemDescription); - - assertEquals("testgroup", itemDescription.getGroup()); - assertEquals("pod1", itemDescription.getName()); - assertEquals("pod1", itemDescription.getIdentifier()); - assertEquals("testgroup", itemDescription.getLabels().get("release")); - } -} diff --git a/src/test/java/de/bonndan/nivio/input/LandscapeDescriptionFactoryTest.java b/src/test/java/de/bonndan/nivio/input/LandscapeDescriptionFactoryTest.java index 39ee1cd5a..cf056486c 100644 --- a/src/test/java/de/bonndan/nivio/input/LandscapeDescriptionFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/input/LandscapeDescriptionFactoryTest.java @@ -13,6 +13,7 @@ import de.bonndan.nivio.util.RootPath; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.io.File; @@ -36,6 +37,7 @@ class LandscapeDescriptionFactoryTest { final private String FILE_PATH_ENV = FILE_PATH + "example_env.yml"; final private String FILE_PATH_TEMPLATES = FILE_PATH + "example_templates.yml"; + private LandscapeDescriptionFactory factory; @BeforeEach @@ -45,7 +47,7 @@ public void setup() { } @Test - public void read() throws MalformedURLException { + void read() throws MalformedURLException { File file = new File(FILE_PATH_ENV); LandscapeDescription landscapeDescription = factory.fromYaml(file); assertEquals("Landscape example", landscapeDescription.getName()); @@ -62,19 +64,20 @@ public void read() throws MalformedURLException { } @Test - public void readsMinimalWithIdentifier() { + void readsMinimalWithIdentifier() { assertDoesNotThrow(() -> new LandscapeDescriptionFactory(mock(FileFetcher.class)) .fromString("yaml", "")); } @Test - public void readFails() { - assertThrows(ReadingException.class, () -> new LandscapeDescriptionFactory(mock(FileFetcher.class)) + void readFails() { + LandscapeDescriptionFactory landscapeDescriptionFactory = new LandscapeDescriptionFactory(mock(FileFetcher.class)); + assertThrows(ReadingException.class, () -> landscapeDescriptionFactory .fromString("", "")); } @Test - public void readYamlStr() throws IOException { + void readYamlStr() throws IOException { File file = new File(FILE_PATH_ENV); String yaml = new String(Files.readAllBytes(file.toPath())); LandscapeDescription landscapeDescription = factory.fromString(yaml, file.toString()); @@ -91,7 +94,7 @@ public void readYamlStr() throws IOException { } @Test - public void readYamlStrWithUrlSource() throws IOException { + void readYamlStrWithUrlSource() throws IOException { File file = new File(FILE_PATH_ENV); String yaml = new String(Files.readAllBytes(file.toPath())); @@ -100,7 +103,7 @@ public void readYamlStrWithUrlSource() throws IOException { } @Test - public void readUrl() throws IOException { + void readUrl() throws IOException { //given File file = new File(FILE_PATH_ENV); @@ -114,7 +117,7 @@ public void readUrl() throws IOException { } @Test - public void readIncremental() { + void readIncremental() { final String FILE_PATH_INCREMENTAL_ENV = FILE_PATH + "example_incremental_env.yml"; File file = new File(FILE_PATH_INCREMENTAL_ENV); LandscapeDescription landscapeDescription = factory.fromYaml(file); @@ -124,7 +127,7 @@ public void readIncremental() { } @Test - public void readEnvVars() throws IOException { + void readEnvVars() throws IOException { final String FILE_PATH_ENVIRONMENT_VARS; final String user; if (SystemUtils.IS_OS_WINDOWS) { @@ -143,7 +146,7 @@ public void readEnvVars() throws IOException { } @Test - public void customLabels() { + void customLabels() { final String FILE_PATH_ENVIRONMENT_VARS = FILE_PATH + "example_items_extrafields.yml"; File file = new File(FILE_PATH_ENVIRONMENT_VARS); @@ -156,7 +159,7 @@ public void customLabels() { } @Test - public void environmentTemplatesRead() { + void environmentTemplatesRead() { File file = new File(FILE_PATH_TEMPLATES); LandscapeDescription landscapeDescription = factory.fromYaml(file); assertNotNull(landscapeDescription); @@ -170,18 +173,18 @@ public void environmentTemplatesRead() { } @Test - public void environmentTemplatesSanitized() { + void environmentTemplatesSanitized() { File file = new File(FILE_PATH_TEMPLATES); LandscapeDescription landscapeDescription = factory.fromYaml(file); ItemDescription template = landscapeDescription.getTemplates().get("myfirsttemplate"); - assertEquals("webservice", template.getLabel(Label.type)); + assertEquals("webservice", template.getType()); assertTrue(template.getName().isEmpty()); } @Test - public void templatesAssigned() { + void templatesAssigned() { File file = new File(FILE_PATH_TEMPLATES); LandscapeDescription landscapeDescription = factory.fromYaml(file); @@ -195,7 +198,7 @@ public void templatesAssigned() { } @Test - public void templatesAssignedWithDataflow() { + void templatesAssignedWithDataflow() { final String FILE_PATH_TEMPLATES_2 = FILE_PATH + "example_templates2.yml"; File file = new File(FILE_PATH_TEMPLATES_2); LandscapeDescription landscapeDescription = factory.fromYaml(file); @@ -206,7 +209,7 @@ public void templatesAssignedWithDataflow() { } @Test - public void configRead() { + void configRead() { final String FILE_PATH_CONFIG = FILE_PATH + "example_config.yml"; File file = new File(FILE_PATH_CONFIG); LandscapeDescription landscapeDescription = factory.fromYaml(file); @@ -219,7 +222,7 @@ public void configRead() { } @Test - public void testReadUnknownFile() { + void testReadUnknownFile() { final String FILE_PATH_UNKNOWN = FILE_PATH + "example_xxx.yml"; File file = new File(FILE_PATH_UNKNOWN); @@ -235,7 +238,7 @@ public void testReadUnknownFile() { } @Test - public void testReadGroups() { + void testReadGroups() { final String FILE_PATH_GROUPS = FILE_PATH + "example_groups.yml"; File file = new File(FILE_PATH_GROUPS); LandscapeDescription landscapeDescription = factory.fromYaml(file); @@ -253,7 +256,7 @@ public void testReadGroups() { } @Test - public void testGroupsHaveEnv() { + void testGroupsHaveEnv() { final String FILE_PATH_GROUPS = FILE_PATH + "example_groups.yml"; File file = new File(FILE_PATH_GROUPS); LandscapeDescription landscapeDescription = factory.fromYaml(file); @@ -271,12 +274,14 @@ public void testGroupsHaveEnv() { } @Test - public void testUnknownProperty() { - factory.fromYaml(new File(FILE_PATH + "example_typo.yml")); + @DisplayName("Unknown field in yaml") + void testUnknownProperty() { + File file = new File(FILE_PATH + "example_typo.yml"); + assertThrows(ReadingException.class, () -> factory.fromYaml(file)); } @Test - public void readCustomKPIs() { + void readCustomKPIs() { File file = new File(RootPath.get() + "/src/test/resources/example/example_kpis.yml"); LandscapeDescription landscapeDescription = factory.fromYaml(file); LandscapeConfig config = landscapeDescription.getConfig(); @@ -304,7 +309,7 @@ public void readCustomKPIs() { } @Test - public void fromBodyItem() { + void fromBodyItem() { //when LandscapeDescription landscapeDescription = factory.fromBodyItems("foo", "nivio", "body"); @@ -316,4 +321,18 @@ public void fromBodyItem() { assertThat(sourceReference.getFormat()).isEqualTo("nivio"); assertThat(sourceReference.getContent()).isEqualTo("body"); } + + @Test + void addLogoLandscape() throws IOException { + // given + File file = new File(FILE_PATH + "inout.yml"); + String yaml = new String(Files.readAllBytes(file.toPath())); + + // when + LandscapeDescription landscapeDescription = factory.fromString(yaml, file.toString()); + + // then + assertThat(landscapeDescription.getIcon()).isEqualTo("https://dedica.team/images/logo_orange_weiss.png"); + } + } diff --git a/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java b/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java index bcfa27a7e..8cf8b2a04 100644 --- a/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java +++ b/src/test/java/de/bonndan/nivio/input/ProcessingChangelogTest.java @@ -3,6 +3,7 @@ import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.ItemFactory; import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.RelationFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -59,7 +60,7 @@ void testAddEntryWithoutMessage() { void addRelation() { //when Item bar = ItemFactory.getTestItem("foo", "bar"); - Relation relation = new Relation(this.testItem, bar); + Relation relation = RelationFactory.createForTesting(this.testItem, bar); changelog.addEntry(relation, ProcessingChangelog.ChangeType.DELETED, null); //then diff --git a/src/test/java/de/bonndan/nivio/input/SeedTest.java b/src/test/java/de/bonndan/nivio/input/SeedTest.java index 2bbf17871..b1e2ffd2d 100644 --- a/src/test/java/de/bonndan/nivio/input/SeedTest.java +++ b/src/test/java/de/bonndan/nivio/input/SeedTest.java @@ -17,7 +17,7 @@ public class SeedTest { public void twoLocal() throws MalformedURLException { Path currentRelativePath = Paths.get(""); String root = currentRelativePath.toAbsolutePath().toString(); - Seed seed = new Seed(java.util.Optional.of(root + "/src/test/resources/example/example_env.yml," + root + "/src/test/resources/example/inout.yml")); + Seed seed = new Seed(root + "/src/test/resources/example/example_env.yml," + root + "/src/test/resources/example/inout.yml", null); List locations = seed.getLocations(); assertFalse(locations.isEmpty()); @@ -30,7 +30,7 @@ public void twoLocal() throws MalformedURLException { public void http() { Path currentRelativePath = Paths.get(""); String root = currentRelativePath.toAbsolutePath().toString(); - Seed seed = new Seed(java.util.Optional.of(root + "/src/test/resources/example/example_env.yml,http://somehost.com/somefile.yml")); + Seed seed = new Seed(root + "/src/test/resources/example/example_env.yml,http://somehost.com/somefile.yml", null); List locations = seed.getLocations(); assertFalse(locations.isEmpty()); @@ -40,6 +40,6 @@ public void http() { @Test public void fails() { - assertThrows(RuntimeException.class, () -> new Seed(java.util.Optional.of(" :xxx"))); + assertThrows(RuntimeException.class, () -> new Seed(" :xxx", null)); } } diff --git a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java index 62dbdf826..81a9b2c67 100644 --- a/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java +++ b/src/test/java/de/bonndan/nivio/input/StartupListenerTest.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.input; +import de.bonndan.nivio.config.SeedProperties; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.LandscapeSource; import org.junit.jupiter.api.BeforeEach; @@ -22,21 +23,23 @@ class StartupListenerTest { private LandscapeDescriptionFactory factory; private ApplicationEventPublisher publisher; private StartupListener startupListener; - private Seed seed = new Seed(Optional.empty()); // will use Seed.NIVIO_ENV_DIRECTORY + private SeedProperties seedProperties = new SeedProperties("src/test/resources/example/inout.yml","1"); + private Seed seed = new Seed(seedProperties.getSeed(), seedProperties.getDemo()); // will use Seed.NIVIO_ENV_DIRECTORY + @BeforeEach public void setup() { factory = mock(LandscapeDescriptionFactory.class); publisher = mock(ApplicationEventPublisher.class); - startupListener = new StartupListener(factory, publisher, seed); + seedProperties = mock(SeedProperties.class); + startupListener = new StartupListener(factory, publisher, seed, seedProperties); } @Test - public void fires() throws MalformedURLException { - + void fires() throws MalformedURLException { //given - seed = new Seed(Optional.of("https://dedica.team")); - startupListener = new StartupListener(factory, publisher, seed); + seed = new Seed("https://dedica.team", seedProperties.getDemo()); + startupListener = new StartupListener(factory, publisher, seed,seedProperties); LandscapeDescription landscapeDescription = new LandscapeDescription("foo", "bar", null); landscapeDescription.setSource(new LandscapeSource(new URL("https://dedica.team"))); diff --git a/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java b/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java index ca2a0b55b..bd7da4057 100644 --- a/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java +++ b/src/test/java/de/bonndan/nivio/input/csv/InputFormatHandlerCSVTest.java @@ -4,6 +4,7 @@ import de.bonndan.nivio.input.FileFetcher; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.dto.RelationDescription; import de.bonndan.nivio.input.dto.SourceReference; import de.bonndan.nivio.input.http.HttpService; import de.bonndan.nivio.observation.InputFormatObserver; @@ -17,6 +18,7 @@ import java.util.List; import java.util.Map; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; @@ -77,6 +79,40 @@ public void read() { assertEquals("superior", super1.getLabels().get("nivio.description")); } + @Test + public void readRelationDescriptions() { + + SourceReference file = SourceReference.of(new File(getRootPath() + "/src/test/resources/example/services/test_relation.csv")); + + Map mapping = new HashMap<>(); + mapping.put("identifier", "1"); + mapping.put("name", "0"); + mapping.put("foo", "2"); + mapping.put("bar", "3"); + file.setProperty("mapping", mapping); + file.setProperty("skipLines", 1); + file.setProperty("separator", ";"); + + InputFormatHandlerCSV factoryCSV = new InputFormatHandlerCSV(fileFetcher); + LandscapeDescription landscapeDescription = new LandscapeDescription("test"); + + //when + factoryCSV.applyData(file, null, landscapeDescription); + + //then + assertEquals(1, landscapeDescription.getItemDescriptions().all().size()); + ItemDescription foo = landscapeDescription.getItemDescriptions().pick("foo", null); + assertNotNull(foo); + + assertThat(foo.getRelations()).hasSize(1).satisfies(relationDescriptions -> { + RelationDescription next = relationDescriptions.iterator().next(); + assertThat(next.getSource()).isEqualTo("foo"); + assertThat(next.getTarget()).isEqualTo("bar"); + assertThat(next.getLabel("nivio.name")).isEqualTo("a relation"); + assertThat(next.getLabel("nivio.foo")).isEqualTo("This does nothing"); + }); + } + @Test public void failsWithoutMapping() { diff --git a/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java b/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java index 242fa9dec..05a78df4b 100644 --- a/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java +++ b/src/test/java/de/bonndan/nivio/input/demo/ChangeTriggerTest.java @@ -1,11 +1,11 @@ package de.bonndan.nivio.input.demo; import de.bonndan.nivio.input.LandscapeDescriptionFactory; +import de.bonndan.nivio.model.LandscapeRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationEventPublisher; -import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; class ChangeTriggerTest { @@ -18,7 +18,7 @@ class ChangeTriggerTest { void setUp() { factory = mock(LandscapeDescriptionFactory.class); publisher = mock(ApplicationEventPublisher.class); - trigger = new ChangeTrigger(factory, publisher); + trigger = new ChangeTrigger(new LandscapeRepository(), factory, publisher); } @Test diff --git a/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java b/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java new file mode 100644 index 000000000..c48098aa1 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/dto/RelationDescriptionTest.java @@ -0,0 +1,74 @@ +package de.bonndan.nivio.input.dto; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class RelationDescriptionTest { + + private List relations; + + @BeforeEach + void setup() { + relations = List.of(new RelationDescription("agroup/foo", "bgroup/bar")); + } + + @Test + void findMatching() { + var rel = new RelationDescription("aGroup/foo", "bGroup/Bar"); + + //when + Optional matching = rel.findMatching(relations); + + //then + assertThat(matching).isPresent(); + } + + @Test + void findMatchingOtherSource() { + var rel = new RelationDescription("aGroup/notfoo", "bGroup/Bar"); + + //when + Optional matching = rel.findMatching(relations); + + //then + assertThat(matching).isEmpty(); + } + + @Test + void findMatchingOtherTarget() { + var rel = new RelationDescription("aGroup/foo", "bGroup/notBar"); + + //when + Optional matching = rel.findMatching(relations); + + //then + assertThat(matching).isEmpty(); + } + + @Test + void update() { + var rel = new RelationDescription("aGroup/foo", "bGroup/notBar"); + rel.setLabel("foo", "one"); + rel.setFormat("f1"); + + var newer = new RelationDescription("aGroup/foo", "bGroup/notBar"); + newer.setDescription("one"); + newer.setFormat("foo"); + newer.setLabel("foo", "two"); + + //when + rel.update(newer); + + //then + assertThat(rel.getDescription()).isEqualTo("one"); + assertThat(rel.getFormat()).isEqualTo("foo"); + assertThat(rel.getLabel("foo")).isEqualTo("two"); + } + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java b/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java index 66fcca9bd..1bbe730ac 100644 --- a/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java +++ b/src/test/java/de/bonndan/nivio/input/external/GitLabRepoHandlerTest.java @@ -3,6 +3,7 @@ import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.external.github.GitHubRepoHandler; import de.bonndan.nivio.input.external.gitlab.GitLabConfig; +import de.bonndan.nivio.input.external.gitlab.GitLabProperties; import de.bonndan.nivio.input.external.gitlab.GitLabRepoHandler; import de.bonndan.nivio.model.Link; import org.gitlab4j.api.*; @@ -99,7 +100,8 @@ void setsDescriptionIfEmpty() throws IOException, ExecutionException, Interrupte void integration() throws IOException, ExecutionException, InterruptedException { //env vars used, configure them properly - GitLabConfig gitLabConfig = new GitLabConfig(); + GitLabProperties gitLabProperties = new GitLabProperties(); + GitLabConfig gitLabConfig = new GitLabConfig(gitLabProperties); GitLabApi gitLabAPI = gitLabConfig.getGitLabAPI(); handler = new GitLabRepoHandler(gitLabAPI); diff --git a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java index 7bbd5b11b..9f49c42f2 100644 --- a/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java +++ b/src/test/java/de/bonndan/nivio/input/external/github/GitHubConfigTest.java @@ -1,6 +1,7 @@ package de.bonndan.nivio.input.external.github; import org.junit.jupiter.api.Test; +import org.springframework.util.StringUtils; import static org.junit.jupiter.api.Assertions.*; @@ -8,7 +9,82 @@ class GitHubConfigTest { @Test void returnsNullIfNoConfig() { - GitHubConfig gitHubConfig = new GitHubConfig(); + + GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); + GitHubConfig gitHubConfig = new GitHubConfig(gitHubProperties); assertNull(gitHubConfig.getGitHub()); } + + @Test + void groupedAssertions(){ + GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); + // in a grouped assertion all assertions are executed, and any failures will be reported together + assertAll("gitHubProperties",()-> assertEquals("kohsuke",gitHubProperties.getLogin()), + ()->assertEquals("012345678",gitHubProperties.getPassword()), + ()-> assertEquals("4d98173f7c075527cb64878561d1fe70",gitHubProperties.getOauth()), + ()-> assertEquals("my_jwt_token",gitHubProperties.getJwt())); + gitHubProperties.setLogin("dedicaTest"); + gitHubProperties.setPassword("123456789"); + gitHubProperties.setOauth("abcdef12345"); + gitHubProperties.setJwt("my_new_jwt"); + + assertEquals("123456789",gitHubProperties.getPassword()); + assertEquals("abcdef12345",gitHubProperties.getOauth()); + assertEquals("my_new_jwt",gitHubProperties.getJwt()); + assertEquals("dedicaTest",gitHubProperties.getLogin()); + + + } + @Test + void dependentAssertions(){ + // within a code block, if an assertion fails the subsequent code in the + // same block will be skipped + GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); + assertAll("properties", + ()->{String login = gitHubProperties.getLogin(); + assertNotNull(login); + // executed only if the previous assertion is valid + assertAll("login", + ()-> assertTrue(login.startsWith("ko")), + ()-> assertTrue(login.endsWith("ke"))); + }, + ()->{String password = gitHubProperties.getPassword(); + assertNotNull(password); + // executed only if the previous assertion is valid + assertAll("password", + ()-> assertTrue(password.contains("45")), + ()-> assertEquals(9,password.length())); + + }, + ()->{String oauth = gitHubProperties.getOauth(); + assertNotNull(oauth); + // executed only if the previous assertion is valid + assertAll("oauth", + ()-> assertTrue(oauth.contains("cb648")), + ()->assertTrue(oauth.endsWith("0"))); + }, + ()->{String jwt = gitHubProperties.getJwt(); + assertNotNull(jwt); + // executed only if the previous assertion is valid + assertAll("jwt", + ()->assertEquals(12,jwt.length()), + ()->assertTrue(jwt.endsWith("ken")) + ); + + } + + ); + + } + @Test + void testCheckAnyEnv(){ + + GitHubProperties gitHubProperties = new GitHubProperties("kohsuke","012345678","4d98173f7c075527cb64878561d1fe70","my_jwt_token"); + boolean value = StringUtils.isEmpty(System.getenv(gitHubProperties.getLogin())) || + StringUtils.isEmpty(System.getenv(gitHubProperties.getPassword())) || + StringUtils.isEmpty(System.getenv(gitHubProperties.getOauth())) || + StringUtils.isEmpty(System.getenv(gitHubProperties.getJwt())); + assertTrue(value); + } + } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java new file mode 100644 index 000000000..c8bba312b --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/external/gitlab/GitLabConfigTest.java @@ -0,0 +1,112 @@ +package de.bonndan.nivio.input.external.gitlab; + +import org.gitlab4j.api.GitLabApi; +import org.junit.jupiter.api.Test; +import java.util.Optional; + +import static java.util.Optional.*; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class GitLabConfigTest { + + + @Test + void returnsNullIfNoConfig() + { + GitLabProperties gitLabProperties = new GitLabProperties(); + GitLabConfig gitLabConfig = new GitLabConfig(gitLabProperties); + assertNull(gitLabConfig.getGitLabAPI()); + } + + + @Test + void groupedAssertions(){ + GitLabProperties gitLabProperties = new GitLabProperties("http://gitlab.example.com","token-string-here123","abracadabra","123456789"); + // in a grouped assertion all assertions are executed, and any failures will be reported together + assertAll("hostUrl",()->assertEquals("http://gitlab.example.com",gitLabProperties.getHostUrl()), + ()->assertEquals("token-string-here123",gitLabProperties.getPersonalAccessToken()), + ()->assertEquals("abracadabra",gitLabProperties.getUsername()), + ()->assertEquals("123456789",gitLabProperties.getPassword()) + ); + gitLabProperties.setHostUrl("http://gitlab.com"); + gitLabProperties.setPersonalAccessToken("my_access_token"); + gitLabProperties.setUsername("my_account"); + gitLabProperties.setPassword("0123456789"); + + assertAll("hostUrl",()->assertEquals("http://gitlab.com",gitLabProperties.getHostUrl()), + ()->assertEquals("my_access_token",gitLabProperties.getPersonalAccessToken()), + ()->assertEquals("my_account",gitLabProperties.getUsername()), + ()->assertEquals("0123456789",gitLabProperties.getPassword()) + ); + + + } + + + @Test + void dependentAssertions(){ + // with a code block, if an assertion fails the subsequent code in the same block will be skipped + GitLabProperties gitLabProperties = new GitLabProperties("http://gitlab.example.com","token-string-here123","abracadabra","123456789"); + assertAll("properties", + ()->{ String hostUrl = gitLabProperties.getHostUrl(); + assertNotNull(hostUrl); + // executed only if the previous assertion is valid + assertAll("Host Url", + ()->assertFalse(hostUrl.isEmpty()), + ()->assertTrue(hostUrl.contains("exa"))); + }, + ()->{String personalAccessToken = gitLabProperties.getPersonalAccessToken(); + assertNotNull(personalAccessToken); + // executed only if the previous assertion is valid + assertAll("Personal Access Token", + ()->assertTrue(personalAccessToken.endsWith("123")), + ()->assertTrue(personalAccessToken.startsWith("tok"))); + }, + ()->{String username = gitLabProperties.getUsername(); + assertNotNull(username); + // executed only if the previous assertion is valid + assertAll("username", + ()->assertTrue(username.contains("dabra")), + ()->assertFalse(username.isEmpty())); + }, + ()->{String password = gitLabProperties.getPassword(); + assertNotNull(password); + // executed only if the previous assertion is valid + assertAll("password", + ()->assertFalse(password.contains("xyz")), + ()->assertTrue(password.endsWith("89"))); + } + + ); + } + @Test + void getGitLabAPI(){ + GitLabProperties gitLabProperties = new GitLabProperties("","token-string-here123","abracadabra","123456789"); + GitLabConfig gitLabConfig = new GitLabConfig(gitLabProperties); + GitLabApi gitLabApi = gitLabConfig.getGitLabAPI(); + assertNotNull(gitLabApi); + assertFalse(gitLabApi == null); + assertTrue(gitLabProperties.getHostUrl().isEmpty()); + } + + @Test + void testGetGitLabAPI(){ + GitLabProperties gitLabProperties = new GitLabProperties("http://gitlab.example.com","token-string-here123","abracadabra","123456789"); + GitLabConfig gitLabConfig = new GitLabConfig(gitLabProperties); + String hostUrl = gitLabProperties.getHostUrl(); + Optional personalAccessToken = Optional.ofNullable(gitLabProperties.getPersonalAccessToken()); + Optional username = Optional.ofNullable(gitLabProperties.getUsername()); + Optional password = Optional.ofNullable(gitLabProperties.getPassword()); + + GitLabApi gitLabApi = gitLabConfig.getGitLabAPI(hostUrl,personalAccessToken,username,password); + assertNotNull(gitLabApi); + assertFalse(gitLabApi == null); + assertThat(hostUrl.isEmpty()); + assertThat(personalAccessToken.isPresent()); + assertThat(username.isPresent()); + assertThat(password.isPresent()); + } + + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/external/sonar/SonarConfigTest.java b/src/test/java/de/bonndan/nivio/input/external/sonar/SonarConfigTest.java new file mode 100644 index 000000000..48a50ed84 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/external/sonar/SonarConfigTest.java @@ -0,0 +1,45 @@ +package de.bonndan.nivio.input.external.sonar; + +import de.bonndan.nivio.input.external.gitlab.GitLabProperties; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SonarConfigTest { + + @Test + void returnNotNullIfConfig(){ + SonarProperties sonarProperties = new SonarProperties("https://www.sonarcloud.io","my_sonar_account","123456789","proxy.sonarcloud.io","8080"); + SonarConfig sonarConfig = new SonarConfig(sonarProperties); + assertNotNull(sonarConfig.getSonarClientBuilder()); + + } + + @Test + void groupedAssertions(){ + SonarProperties sonarProperties = new SonarProperties("https://www.sonarcloud.io","my_sonar_account","123456789","proxy.sonarcloud.io","8080"); + // in a grouped assertion all assertions are executed, and any failures will be reported together + assertAll("serverUrl",()->assertEquals("https://www.sonarcloud.io",sonarProperties.getServerUrl()), + ()->assertEquals("my_sonar_account",sonarProperties.getLogin()), + ()->assertEquals("123456789",sonarProperties.getPassword()), + ()->assertEquals("proxy.sonarcloud.io",sonarProperties.getProxyHost()), + ()->assertEquals("8080",sonarProperties.getProxyPort()) + ); + sonarProperties.setServerUrl("https://www.sonarqube.org"); + sonarProperties.setLogin("my_new_account"); + sonarProperties.setPassword("abracadabra"); + sonarProperties.setProxyHost("proxy.sonarqube.org"); + sonarProperties.setProxyPort("8090"); + + assertAll("serverUrl",()->assertEquals("https://www.sonarqube.org",sonarProperties.getServerUrl()), + ()->assertEquals("my_new_account",sonarProperties.getLogin()), + ()->assertEquals("abracadabra",sonarProperties.getPassword()), + ()->assertEquals("proxy.sonarqube.org",sonarProperties.getProxyHost()), + ()->assertEquals("8090",sonarProperties.getProxyPort()) + ); + } + +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java new file mode 100644 index 000000000..9a1809243 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/CreateItemsTest.java @@ -0,0 +1,170 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.kubernetes.itemadapters.*; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; +import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static org.assertj.core.api.Assertions.assertThat; + + +@EnableKubernetesMockClient(crud = true, https = false) +class CreateItemsTest { + KubernetesClient kubernetesClient; + + @Test + void getDeploymentItems() { + var deployment = new DeploymentBuilder() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withNewStrategy().withNewType("strategyType").endStrategy().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.apps().deployments().create(deployment); + var deploymentList = CreateItems.getDeploymentItems(kubernetesClient); + assertThat(deploymentList).isNotNull(); + assertThat(deploymentList.size()).isOne(); + assertThat(deploymentList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(deploymentList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(deploymentList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); + assertThat(deploymentList.get(0).getUid()).isEqualTo("testUid"); + assertThat(deploymentList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(deploymentList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition.testtype", "teststatus", "name", "deployment", "namespace", "test", "strategy", "strategyType")); + assertThat(deploymentList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new DeploymentItemAdapter(deployment)); + assertThat(deploymentList.get(0).getType()).isEqualTo(ItemType.DEPLOYMENT); + } + + @Test + void getPersistentVolumeClaimItems() { + var persistentVolumeClaim = new PersistentVolumeClaimBuilder() + .withNewMetadata().withName("persistentvolumeclaim").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumeClaims().create(persistentVolumeClaim); + var persistentVolumeClaimList = CreateItems.getPersistentVolumeClaimItems(kubernetesClient); + assertThat(persistentVolumeClaimList).isNotNull(); + assertThat(persistentVolumeClaimList.size()).isOne(); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); + assertThat(persistentVolumeClaimList.get(0).getUid()).isEqualTo("testUid"); + assertThat(persistentVolumeClaimList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(persistentVolumeClaimList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "name", "persistentvolumeclaim", "namespace", "test", "phase status", "testPhase", "storage class", "testStorageName")); + assertThat(persistentVolumeClaimList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new PersistentVolumeClaimItemAdapter(persistentVolumeClaim)); + assertThat(persistentVolumeClaimList.get(0).getType()).isEqualTo(ItemType.VOLUME); + } + + @Test + void getPersistentVolumeItems() { + var persistentVolume = new PersistentVolumeBuilder() + .withNewMetadata().withName("persistentvolume").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").withPersistentVolumeReclaimPolicy("testReclaimPolicy").addNewAccessMode("testAccessMode").addToCapacity("testCapacity", new Quantity("8", "Gi")).withClaimRef(new ObjectReferenceBuilder().withUid("testClaimUid").build()).endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumes().create(persistentVolume); + var persistentVolumeList = CreateItems.getPersistentVolumeItems(kubernetesClient); + assertThat(persistentVolumeList).isNotNull(); + assertThat(persistentVolumeList.size()).isOne(); + assertThat(persistentVolumeList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(persistentVolumeList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(persistentVolumeList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); + assertThat(persistentVolumeList.get(0).getUid()).isEqualTo("testUid"); + assertThat(persistentVolumeList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(persistentVolumeList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", "name", "persistentvolume", "namespace", "test", "phase status", "testPhase", "reclaim policy", "testReclaimPolicy", "storage class", "testStorageName", "storage mode", "testAccessMode", "testCapacity", "8Gi")); + assertThat(persistentVolumeList.get(0).getType()).isEqualTo(ItemType.VOLUME); + assertThat(((PersistentVolumeItemAdapter) persistentVolumeList.get(0).getItemAdapter()).getClaimRef().getUid()).isEqualTo("testClaimUid"); + } + + @Test + void getPodItems() { + var pod = new PodBuilder() + .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().addNewVolume().withNewPersistentVolumeClaim().withNewClaimName("testClaimName").endPersistentVolumeClaim().endVolume().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.pods().create(pod); + var podList = CreateItems.getPodItems(kubernetesClient); + assertThat(podList).isNotNull(); + assertThat(podList.size()).isOne(); + assertThat(podList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(podList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(podList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); + assertThat(podList.get(0).getUid()).isEqualTo("testUid"); + assertThat(podList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(podList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition.testtype", "teststatus", "name", "pod", "namespace", "test")); + assertThat(podList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new PodItemAdapter(pod)); + assertThat(((PodItemAdapter) podList.get(0).getItemAdapter()).getVolumes().size()).isOne(); + assertThat(((PodItemAdapter) podList.get(0).getItemAdapter()).getVolumes().get(0).getPersistentVolumeClaim().getClaimName()).isEqualTo("testClaimName"); + assertThat(podList.get(0).getType()).isEqualTo(ItemType.POD); + } + + @Test + void getReplicaSetItems() { + var replicaSet = new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().replicaSets().create(replicaSet); + var replicaSetList = CreateItems.getReplicaSetItems(kubernetesClient); + assertThat(replicaSetList).isNotNull(); + assertThat(replicaSetList.size()).isOne(); + assertThat(replicaSetList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(replicaSetList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(replicaSetList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); + assertThat(replicaSetList.get(0).getUid()).isEqualTo("testUid"); + assertThat(replicaSetList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(replicaSetList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", "1;1", "name", "replicaSet", "namespace", "test")); + assertThat(replicaSetList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new ReplicaSetItemAdapter(replicaSet)); + assertThat(replicaSetList.get(0).getType()).isEqualTo(ItemType.REPLICASET); + } + + @Test + void getServiceItems() { + var service = new ServiceBuilder() + .withNewMetadata().withName("service").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withClusterIP("testIP").withNewType("testType").withSessionAffinity("testSessionAffinity").endSpec() + .build(); + kubernetesClient.services().create(service); + var serviceList = CreateItems.getServiceItems(kubernetesClient); + assertThat(serviceList).isNotNull(); + assertThat(serviceList.size()).isOne(); + assertThat(serviceList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(serviceList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(serviceList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); + assertThat(serviceList.get(0).getUid()).isEqualTo("testUid"); + assertThat(serviceList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(serviceList.get(0).getDetails()).isEqualTo(Map.of("cluster ip", "testIP", "creation", "testCreation", "name", "service", "namespace", "test", "service type", "testType", "session affinity", "testSessionAffinity")); + assertThat(serviceList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new ServiceItemAdapter(service)); + assertThat(serviceList.get(0).getType()).isEqualTo(ItemType.SERVICE); + } + + @Test + void getStatefulSetItems() { + var statefulSet = new StatefulSetBuilder() + .withNewMetadata().withName("statefulSet").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().statefulSets().create(statefulSet); + var statefulSetList = CreateItems.getStatefulSetItems(kubernetesClient); + assertThat(statefulSetList).isNotNull(); + assertThat(statefulSetList.size()).isOne(); + assertThat(statefulSetList.get(0).getItemAdapter().getLabels()).containsExactly(entry("testLabelKey", "testLabelValue")); + assertThat(statefulSetList.get(0).getItemAdapter().getOwnerReferences().size()).isOne(); + assertThat(statefulSetList.get(0).getItemAdapter().getOwnerReferences().get(0).getUid()).isEqualTo("testOwnerUid"); + assertThat(statefulSetList.get(0).getUid()).isEqualTo("testUid"); + assertThat(statefulSetList.get(0).getClass()).isEqualTo(K8sItem.class); + assertThat(statefulSetList.get(0).getDetails()).isEqualTo(Map.of("creation", "testCreation", InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", "1;1", "name", "statefulSet", "namespace", "test")); + assertThat(statefulSetList.get(0).getItemAdapter()).isEqualToComparingFieldByField(new StatefulSetItemAdapter(statefulSet)); + assertThat(statefulSetList.get(0).getType()).isEqualTo(ItemType.STATEFULSET); + } +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java new file mode 100644 index 000000000..c0bc48781 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/InputFormatHandlerKubernetesTest.java @@ -0,0 +1,126 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.dto.SourceReference; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.observation.KubernetesObserver; +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; +import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationEventPublisher; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@EnableKubernetesMockClient(crud = true, https = false) +class InputFormatHandlerKubernetesTest { + KubernetesClient kubernetesClient; + InputFormatHandlerKubernetes inputFormatHandlerKubernetes; + + @BeforeEach + void setUp() { + SourceReference sourceReference = new SourceReference(null, "k8s"); + sourceReference.setUrl("http://localhost:80?groupLabel=release&namespace=default"); + inputFormatHandlerKubernetes = new InputFormatHandlerKubernetes(Optional.of(kubernetesClient)); + } + + @Test + void getFormats() { + assertThat(inputFormatHandlerKubernetes.getFormats()).containsAll(List.of("kubernetes", "k8s")); + } + + @Test + void applyData() throws MalformedURLException { + var landscapeDescription = new LandscapeDescription("k8sLandscapeTest"); + var url = new URL("https://dedica.team"); + var sourceReference = new SourceReference("https://dedica.team", ""); + inputFormatHandlerKubernetes.applyData(sourceReference, url, landscapeDescription); + assertThat(landscapeDescription.getItemDescriptions().all().size()).isZero(); + setK8sTestEnvironment(); + inputFormatHandlerKubernetes.applyData(sourceReference, url, landscapeDescription); + assertThat(landscapeDescription.getItemDescriptions().all().size()).isEqualTo(7); + assertThat(landscapeDescription.getItemDescriptions().find("deploymentUid", "deployment").orElseThrow().getRelations().size()).isZero(); + assertThat(landscapeDescription.getItemDescriptions().find("replicaSetUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("deploymentUid"); + assertThat(landscapeDescription.getItemDescriptions().find("replicaSetUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("replicaSetUid"); + assertThat(landscapeDescription.getItemDescriptions().find("podUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("replicaSetUid"); + assertThat(landscapeDescription.getItemDescriptions().find("podUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("podUid"); + assertThat(landscapeDescription.getItemDescriptions().find("serviceUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("deploymentUid"); + assertThat(landscapeDescription.getItemDescriptions().find("serviceUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("serviceUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("persistentVolumeClaimUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("persistentVolumeUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("podUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("persistentVolumeClaimUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getSource()).isEqualTo("podUid"); + assertThat(landscapeDescription.getItemDescriptions().find("persistentVolumeClaimUid", "deployment").orElseThrow().getRelations().stream().findFirst().orElseThrow().getTarget()).isEqualTo("persistentVolumeClaimUid"); + } + + private void setK8sTestEnvironment() { + var service = new ServiceBuilder() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("serviceUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withClusterIP("testIP").withNewType("testType").withSessionAffinity("testSessionAffinity").endSpec() + .build(); + kubernetesClient.services().create(service); + var deployment = new DeploymentBuilder() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("deploymentUid").withLabels(Map.of("testLabelKey", "testLabelValue", "1", "2")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withNewStrategy().withNewType("strategyType").endStrategy().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.apps().deployments().create(deployment); + var replicaSet = new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("replicaSetUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("deploymentUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().replicaSets().create(replicaSet); + var statefulSet = new StatefulSetBuilder() + .withNewMetadata().withName("statefulSet").withCreationTimestamp("testCreation").withUid("statefulSetUid").withLabels(Map.of("testLabelKey", "testLabelValue", "1", "2")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build(); + kubernetesClient.apps().statefulSets().create(statefulSet); + var pod = new PodBuilder() + .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("podUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("replicaSetUid").build()).withNamespace("test").endMetadata() + .withNewSpec().addNewVolume().withNewPersistentVolumeClaim().withNewClaimName("persistentvolumeclaim").endPersistentVolumeClaim().endVolume().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.pods().create(pod); + var persistentVolumeClaim = new PersistentVolumeClaimBuilder() + .withNewMetadata().withName("persistentvolumeclaim").withCreationTimestamp("testCreation").withUid("persistentVolumeClaimUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumeClaims().create(persistentVolumeClaim); + var persistentVolume = new PersistentVolumeBuilder() + .withNewMetadata().withName("persistentvolume").withCreationTimestamp("testCreation").withUid("persistentVolumeUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withStorageClassName("testStorageName").withPersistentVolumeReclaimPolicy("testReclaimPolicy").addNewAccessMode("testAccessMode").addToCapacity("testCapacity", new Quantity("8", "Gi")).withClaimRef(new ObjectReferenceBuilder().withUid("persistentVolumeClaimUid").build()).endSpec() + .withNewStatus().withNewPhase("testPhase").endStatus() + .build(); + kubernetesClient.persistentVolumes().create(persistentVolume); + } + + @Test + void getObserver() { + //given + var applicationEventPublisher = Mockito.mock(ApplicationEventPublisher.class); + var landscape = Mockito.mock(Landscape.class); + var sourceReference = Mockito.mock(SourceReference.class); + + //when + var observerClass = Objects.requireNonNull(inputFormatHandlerKubernetes.getObserver(applicationEventPublisher, landscape, sourceReference)).getClass(); + + //then + assertThat(observerClass).isEqualTo(KubernetesObserver.class); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/K8sConfigTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sConfigTest.java new file mode 100644 index 000000000..ff89b31af --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sConfigTest.java @@ -0,0 +1,17 @@ +package de.bonndan.nivio.input.kubernetes; + +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class K8sConfigTest { + @Test + void testConstructor() { + var testConfig = new K8sConfig(true, 2, Map.of()); + assertThat(testConfig.isActive()).isTrue(); + assertThat(testConfig.getMinMatchingLabel()).isEqualTo(2); + assertThat(testConfig.getLevel()).isEmpty(); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/K8sItemTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sItemTest.java new file mode 100644 index 000000000..e6c038beb --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/K8sItemTest.java @@ -0,0 +1,69 @@ +package de.bonndan.nivio.input.kubernetes; + +import de.bonndan.nivio.input.ItemType; +import de.bonndan.nivio.input.dto.RelationDescription; +import de.bonndan.nivio.input.kubernetes.itemadapters.PodItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; +import io.fabric8.kubernetes.api.model.PodBuilder; +import io.fabric8.kubernetes.api.model.apps.ReplicaSetBuilder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class K8sItemTest { + K8sItem k8sItem; + + @BeforeEach + void setUp() { + k8sItem = new K8sItemBuilder(ItemType.POD, new PodItemAdapter(new PodBuilder() + .withNewMetadata().withName("pod").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build())).build(); + } + + @Test + void addGetOwner() { + assertThat(k8sItem.getOwner().size()).isZero(); + var ownerK8sItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build())).build(); + k8sItem.addOwner(ownerK8sItem); + assertThat(k8sItem.getOwner().size()).isOne(); + assertThat(k8sItem.getOwner()).containsExactly(ownerK8sItem); + } + + @Test + void addGetRelation() { + assertThat(k8sItem.getRelationDescriptionList().size()).isZero(); + var relationDescription = new RelationDescription("1", "2"); + k8sItem.addRelation(relationDescription); + assertThat(k8sItem.getRelationDescriptionList().size()).isOne(); + assertThat(k8sItem.getRelationDescriptionList()).containsExactly(relationDescription); + } + + @Test + void getGroup() { + assertThat(k8sItem.getGroup()).isEqualTo("pod"); + var ownerK8sItem = new K8sItemBuilder(ItemType.REPLICASET, new ReplicaSetItemAdapter(new ReplicaSetBuilder() + .withNewMetadata().withName("replicaSet").withCreationTimestamp("testCreation").withUid("testUid").withNamespace("test").endMetadata() + .withNewSpec().withReplicas(1).endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().withReadyReplicas(1).endStatus() + .build())).build(); + k8sItem.addOwner(ownerK8sItem); + assertThat(k8sItem.getGroup()).isEqualTo("replicaSet"); + } + + @Test + void getLevelDecorator() { + assertThat(k8sItem.getLevelDecorator()).isEqualToComparingFieldByField(new LevelDecorator(K8sJsonParser.getExperimentalLevel(k8sItem.getItemAdapter().getClass()))); + } + + @Test + void getName() { + assertThat(k8sItem.getName()).isEqualTo("pod"); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesObserverTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesObserverTest.java new file mode 100644 index 000000000..579682206 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/KubernetesObserverTest.java @@ -0,0 +1,74 @@ +package de.bonndan.nivio.input.kubernetes; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeFactory; +import de.bonndan.nivio.observation.InputChangedEvent; +import de.bonndan.nivio.observation.KubernetesObserver; +import io.fabric8.kubernetes.api.model.OwnerReferenceBuilder; +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientException; +import io.fabric8.kubernetes.client.server.mock.EnableKubernetesMockClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@EnableKubernetesMockClient(crud = true, https = false) +class KubernetesObserverTest { + + private ListAppender logWatcher; + ApplicationEventPublisher eventPublisher; + KubernetesClient kubernetesClient; + KubernetesObserver kubernetesObserver; + Landscape landscape; + + @BeforeEach + void setUp() { + landscape = LandscapeFactory.createForTesting("foo", "bar").build(); + eventPublisher = mock(ApplicationEventPublisher.class); + + } + + @Test + void testExceptionHandling() { + //given + this.logWatcher = new ListAppender<>(); + this.logWatcher.start(); + ((Logger) LoggerFactory.getLogger(KubernetesObserver.class)).addAppender(this.logWatcher); + var kubernetesClientException = Mockito.mock(KubernetesClient.class); + Mockito.when(kubernetesClientException.apps()).thenThrow(KubernetesClientException.class); + + //when + kubernetesObserver = new KubernetesObserver(landscape, eventPublisher, kubernetesClientException); + + //then + int logSize = logWatcher.list.size(); + assertThat(logWatcher.list.get(logSize - 1).getFormattedMessage()).contains("Kubernetes might not be available"); + verify(eventPublisher, never()).publishEvent(any(InputChangedEvent.class)); + } + + @Test + void run() { + kubernetesObserver = new KubernetesObserver(landscape, eventPublisher, kubernetesClient); + var deployment = new DeploymentBuilder() + .withNewMetadata().withName("deployment").withCreationTimestamp("testCreation").withUid("testUid").withLabels(Map.of("testLabelKey", "testLabelValue")).withOwnerReferences(new OwnerReferenceBuilder().withUid("testOwnerUid").build()).withNamespace("test").endMetadata() + .withNewSpec().withNewStrategy().withNewType("strategyType").endStrategy().endSpec() + .withNewStatus().addNewCondition().withType("testType").withStatus("testStatus").endCondition().endStatus() + .build(); + kubernetesClient.apps().deployments().create(deployment); + kubernetesObserver.run(); + + verify(eventPublisher).publishEvent(any(InputChangedEvent.class)); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetailsTest.java new file mode 100644 index 000000000..e22e01fe8 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DefaultDetailsTest.java @@ -0,0 +1,32 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class DefaultDetailsTest { + DefaultDetails defaultDetails = new DefaultDetails(); + + @Test + void testGetExtendedDetails() { + ItemAdapter itemAdapter = Mockito.mock(ItemAdapter.class); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Map result = defaultDetails.getExtendedDetails(new HashMap<>() {{ + put("String", "String"); + }}, itemAdapter); + assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "creation", "creationTimestamp")); + } + + @Test + void testGetExtendedDetailsException() { + assertThrows(NullPointerException.class, () -> defaultDetails.getExtendedDetails(null, null)); + } +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java new file mode 100644 index 000000000..e9820777a --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/DeploymentDetailsTest.java @@ -0,0 +1,67 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class DeploymentDetailsTest { + DeploymentDetails deploymentDetails; + + @BeforeEach + void setUp() { + + } + + @Test + void testGetExtendedDetails() { + var itemAdapter = Mockito.mock(DeploymentItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getStrategyType()).thenReturn("strategyType"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + deploymentDetails = new DeploymentDetails(new DefaultDetails()); + Map result = deploymentDetails.getExtendedDetails(Map.of(), itemAdapter); + assertThat(result).isEqualTo(Map.of("name", "name", "namespace", "namespace", "strategy", "strategyType", "creation", "creationTimestamp")); + } + + @Test + void testGetExtendedDetailsClassCastException() { + var itemAdapter = Mockito.mock(ServiceItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getType()).thenReturn("testType"); + Mockito.when(itemAdapter.getClusterIP()).thenReturn("testIP"); + Mockito.when(itemAdapter.getSessionAffinity()).thenReturn("testSessionAffinity"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(DeploymentDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new DeploymentDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); + } + + + @Test + void testGetExtendedDetailsException() { + assertThrows(NullPointerException.class, () -> deploymentDetails.getExtendedDetails(null, null)); + } + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java new file mode 100644 index 000000000..d088e3580 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeClaimDetailsTest.java @@ -0,0 +1,38 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class PersistentVolumeClaimDetailsTest { + @Test + void testGetExtendedDetailsClassCastException() { + var itemAdapter = Mockito.mock(ServiceItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getType()).thenReturn("testType"); + Mockito.when(itemAdapter.getClusterIP()).thenReturn("testIP"); + Mockito.when(itemAdapter.getSessionAffinity()).thenReturn("testSessionAffinity"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(PersistentVolumeClaimDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new PersistentVolumeClaimDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeClaimItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java new file mode 100644 index 000000000..500ff3cec --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/PersistentVolumeDetailsTest.java @@ -0,0 +1,72 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter; +import io.fabric8.kubernetes.api.model.Quantity; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class PersistentVolumeDetailsTest { + + PersistentVolumeDetails persistentVolumeDetails; + PersistentVolumeItemAdapter itemAdapter; + + @BeforeEach + void setUp() { + itemAdapter = Mockito.mock(PersistentVolumeItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getAccessModes()).thenReturn(List.of("testMode")); + Mockito.when(itemAdapter.getPhase()).thenReturn("phase"); + Mockito.when(itemAdapter.getPersistentVolumeReclaimPolicy()).thenReturn("persistentVolumeReclaimPolicy"); + Mockito.when(itemAdapter.getCapacity()).thenReturn(Map.of("testCapacity", new Quantity("8", "gi"))); + Mockito.when(itemAdapter.getStorageClassName()).thenReturn("testStorage"); + } + + @Test + void testGetExtendedDetails() { + persistentVolumeDetails = new PersistentVolumeDetails(new DefaultDetails()); + Map result = persistentVolumeDetails.getExtendedDetails(Map.of(), itemAdapter); + assertThat(result).isEqualTo(Map.of("creation", "creationTimestamp", "name", "name", "namespace", "namespace", "phase status", "phase", "reclaim policy", "persistentVolumeReclaimPolicy", "storage class", "testStorage", "storage mode", "testMode", "testCapacity", "8gi")); + } + + @Test + void testGetExtendedDetailsClassCastException() { + var itemAdapter = Mockito.mock(ServiceItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Mockito.when(itemAdapter.getType()).thenReturn("testType"); + Mockito.when(itemAdapter.getClusterIP()).thenReturn("testIP"); + Mockito.when(itemAdapter.getSessionAffinity()).thenReturn("testSessionAffinity"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(PersistentVolumeDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new PersistentVolumeDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.PersistentVolumeItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); + } + + + @Test + void testGetExtendedDetailsException() { + assertThrows(NullPointerException.class, () -> persistentVolumeDetails.getExtendedDetails(null, null)); + } +} diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetailsTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetailsTest.java new file mode 100644 index 000000000..32d6a5f0d --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/details/ServiceDetailsTest.java @@ -0,0 +1,35 @@ +package de.bonndan.nivio.input.kubernetes.details; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ServiceDetailsTest { + @Test + void testGetExtendedDetailsClassCastException() { + var itemAdapter = Mockito.mock(DeploymentItemAdapter.class); + Mockito.when(itemAdapter.getCreationTimestamp()).thenReturn("creationTimestamp"); + Mockito.when(itemAdapter.getNamespace()).thenReturn("namespace"); + Mockito.when(itemAdapter.getName()).thenReturn("name"); + Logger detailLogger = (Logger) LoggerFactory.getLogger(ServiceDetails.class); + ListAppender listAppender = new ListAppender<>(); + listAppender.start(); + detailLogger.addAppender(listAppender); + var serviceDetails = new ServiceDetails(new DefaultDetails()); + serviceDetails.getExtendedDetails(Map.of(), itemAdapter); + List logsList = listAppender.list; + var className = itemAdapter.getClass().getCanonicalName(); + assertThat(logsList.get(0).getMessage()).isEqualTo("class " + className + " cannot be cast to class de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter (" + className + " and de.bonndan.nivio.input.kubernetes.itemadapters.ServiceItemAdapter are in unnamed module of loader 'app')"); + assertThat(logsList.get(0).getLevel()).isEqualTo(Level.WARN); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/status/BoolStatusTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/status/BoolStatusTest.java new file mode 100644 index 000000000..e7da52fe2 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/status/BoolStatusTest.java @@ -0,0 +1,22 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.input.kubernetes.itemadapters.ItemAdapter; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class BoolStatusTest { + + @Test + void getExtendedStatus() { + var boolStatus = new BoolStatus(); + var extendedStatus = boolStatus.getExtendedStatus(Map.of("testKey", "testValue"), Mockito.mock(ItemAdapter.class)); + assertThat(extendedStatus).isEqualTo(Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition.testkey", "testvalue")); + extendedStatus = boolStatus.getExtendedStatus(Map.of("testKey", "testValue"), null); + assertThat(extendedStatus).isEqualTo(Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".boolcondition.testkey", "testvalue")); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatusTest.java b/src/test/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatusTest.java new file mode 100644 index 000000000..ea09195d5 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/input/kubernetes/status/ReplicaStatusTest.java @@ -0,0 +1,44 @@ +package de.bonndan.nivio.input.kubernetes.status; + +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.input.kubernetes.itemadapters.DeploymentItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.ReplicaSetItemAdapter; +import de.bonndan.nivio.input.kubernetes.itemadapters.StatefulSetItemAdapter; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ReplicaStatusTest { + + @Test + void getExtendedStatusReplicaSet() { + var replicaStatus = new ReplicaStatus(); + var itemAdapter = Mockito.mock(ReplicaSetItemAdapter.class); + Mockito.when(itemAdapter.getReadyReplicas()).thenReturn(1); + Mockito.when(itemAdapter.getReplicas()).thenReturn(1); + var extendedStatus = replicaStatus.getExtendedStatus(Map.of("testKey", "testValue"), itemAdapter); + assertThat(extendedStatus).isEqualTo(Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", "1;1")); + } + + @Test + void getExtendedStatusStatefulSet() { + var replicaStatus = new ReplicaStatus(); + var itemAdapter = Mockito.mock(StatefulSetItemAdapter.class); + Mockito.when(itemAdapter.getReadyReplicas()).thenReturn(1); + Mockito.when(itemAdapter.getReplicas()).thenReturn(1); + var extendedStatus = replicaStatus.getExtendedStatus(Map.of("testKey", "testValue"), itemAdapter); + assertThat(extendedStatus).isEqualTo(Map.of(InputFormatHandlerKubernetes.LABEL_PREFIX + ".replicacondition.replicas", "1;1")); + } + + @Test + void getExtendedStatusItemAdapter() { + var replicaStatus = new ReplicaStatus(); + var itemAdapter = new DeploymentItemAdapter(new Deployment()); + var extendedStatus = replicaStatus.getExtendedStatus(Map.of("testKey", "testValue"), itemAdapter); + assertThat(extendedStatus).isEqualTo(Map.of("testKey", "testValue")); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/model/GroupFactoryTest.java b/src/test/java/de/bonndan/nivio/model/GroupFactoryTest.java index 0ba6c6f20..c0630e768 100644 --- a/src/test/java/de/bonndan/nivio/model/GroupFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/model/GroupFactoryTest.java @@ -5,14 +5,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; -public class GroupFactoryTest { +class GroupFactoryTest { @Test - public void testMerge() { - Group one = new Group("a", "test", "Joe", "a", null, null, "#123123"); + void testMerge() { + Group one = new Group("a", "test", "Joe", null, "mail", "#123123"); - Group two = new Group("a", "test", "Matt", null, "mail", null, null); + Group two = new Group("a", "test", "Matt", "a", null, null); Group merged = GroupFactory.merge(one, two); @@ -23,8 +23,8 @@ public void testMerge() { } @Test - public void usesExistingValues() { - Group in = new Group("a", "foo", "Matt", "abc", "mail", "one", "00ffee"); + void usesExistingValues() { + Group in = new Group("a", "foo", "Matt", "mail", "one", "00ffee"); Group merge = GroupFactory.merge(in, null); assertThat(merge).isNotNull(); @@ -38,9 +38,9 @@ public void usesExistingValues() { } @Test - public void mergeSetsDefaultColor() { - Group one = new Group("a", "test", "Matt", null, "mail", null, null); - Group two = new Group("a", "test", "Matt", null, "mail", null, null); + void mergeSetsDefaultColor() { + Group one = new Group("a", "test", "Matt", "mail", null, null); + Group two = new Group("a", "test", "Matt", "mail", null, null); Group merge = GroupFactory.merge(one, two); assertThat(merge).isNotNull(); diff --git a/src/test/java/de/bonndan/nivio/model/GroupTest.java b/src/test/java/de/bonndan/nivio/model/GroupTest.java index 756370191..e5541569c 100644 --- a/src/test/java/de/bonndan/nivio/model/GroupTest.java +++ b/src/test/java/de/bonndan/nivio/model/GroupTest.java @@ -2,6 +2,7 @@ import org.junit.jupiter.api.Test; +import java.util.LinkedHashSet; import java.util.List; import static de.bonndan.nivio.model.ItemFactory.getTestItem; @@ -16,16 +17,16 @@ void doesNotAllowEmptyIdentifier() { } @Test - void getItemsIsImmutable() { + void getItemsIsSorted() { Group g = new Group("foo", "test"); - assertThrows(Exception.class, () -> g.getItems().add(getTestItem("a", "b"))); + assertThat(g.getItems()).isInstanceOf(LinkedHashSet.class); } @Test void addItemAllowed() { Group g = new Group("foo", "test"); Item item = getTestItem("foo", "b"); - g.addItem(item); + g.addOrReplaceItem(item); assertEquals(1, g.getItems().size()); } @@ -33,14 +34,28 @@ void addItemAllowed() { void addItemForbidden() { Group g = new Group("foo", "test"); Item item = getTestItem("a", "b"); - assertThrows(IllegalArgumentException.class, () -> g.addItem(item)); + assertThrows(IllegalArgumentException.class, () -> g.addOrReplaceItem(item)); + } + + @Test + void replacesItemFQI() { + Group g = new Group("foo", "test"); + Item one = getTestItem("foo", "one"); + g.addOrReplaceItem(one); + assertThat(g.getItems()).containsExactly(one.getFullyQualifiedIdentifier()); + + Item copy = getTestItem("foo", "one"); + copy.setLabel(Label.version, "1"); + + g.addOrReplaceItem(copy); + assertThat(g.getItems()).containsExactly(copy.getFullyQualifiedIdentifier()); } @Test void removeItem() { Group g = new Group("foo", "test"); Item item = getTestItem("foo", "b"); - g.addItem(item); + g.addOrReplaceItem(item); assertEquals(1, g.getItems().size()); boolean b = g.removeItem(item); @@ -52,7 +67,7 @@ void removeItem() { void removeItemFails() { Group g = new Group("foo", "test"); Item item = getTestItem("foo", "b"); - g.addItem(item); + g.addOrReplaceItem(item); boolean b = g.removeItem(getTestItem("foo", "c")); assertThat(b).isFalse(); @@ -61,8 +76,8 @@ void removeItemFails() { @Test void hasNoChanges() { - Group g1 = new Group("foo", "bar", "John", null, null, null, null); - Group g2 = new Group("foo", "bar", "John", null, null, null, null); + Group g1 = new Group("foo", "bar", "John", null, null, null); + Group g2 = new Group("foo", "bar", "John", null, null, null); //when List changes = g1.getChanges(g2); @@ -71,8 +86,8 @@ void hasNoChanges() { @Test void hasChanges() { - Group g1 = new Group("foo", "bar", "John", null, null, null, null); - Group g2 = new Group("foo", "bar", "Doe", null, null, null, null); + Group g1 = new Group("foo", "bar", "John", null, null, null); + Group g2 = new Group("foo", "bar", "Doe", null, null, null); //when List changes = g1.getChanges(g2); diff --git a/src/test/java/de/bonndan/nivio/model/ItemFactoryTest.java b/src/test/java/de/bonndan/nivio/model/ItemFactoryTest.java index fe90fc917..df929d551 100644 --- a/src/test/java/de/bonndan/nivio/model/ItemFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/model/ItemFactoryTest.java @@ -12,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -public class ItemFactoryTest { +class ItemFactoryTest { private ItemDescription landscapeItem; @@ -40,7 +40,7 @@ public void setUp() throws MalformedURLException { } @Test - public void testCreate() { + void testCreate() { Landscape l = LandscapeFactory.createForTesting("testLandscape", "testLandscape").build(); Item created = ItemFactory.fromDescription(landscapeItem, l); @@ -70,7 +70,7 @@ public void testCreate() { } @Test - public void testAssignAll() { + void testAssignAll() { //given Landscape l = LandscapeFactory.createForTesting("testLandscape", "testLandscape").build(); @@ -79,6 +79,7 @@ public void testAssignAll() { update.setDescription("123"); update.setLabel(Label.version, "2000"); update.setLabel("newlabel", "foo"); + update.setType("firewall"); //when Item updated = ItemFactory.assignAll(existing, update); @@ -86,6 +87,7 @@ public void testAssignAll() { //then assertThat(updated).isNotNull(); assertThat(updated.getDescription()).isEqualTo("123"); + assertThat(updated.getType()).isEqualTo("firewall"); assertThat(updated.getLabel(Label.version)).isEqualTo("2000"); assertThat(updated.getLabel("newlabel")).isEqualTo("foo"); } diff --git a/src/test/java/de/bonndan/nivio/model/ItemTest.java b/src/test/java/de/bonndan/nivio/model/ItemTest.java index df9d5550b..e83146a46 100644 --- a/src/test/java/de/bonndan/nivio/model/ItemTest.java +++ b/src/test/java/de/bonndan/nivio/model/ItemTest.java @@ -1,5 +1,7 @@ package de.bonndan.nivio.model; +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.assessment.Assessable; import org.junit.jupiter.api.Test; import java.util.List; @@ -11,10 +13,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; -public class ItemTest { +class ItemTest { @Test - public void equalsWithGroup() { + void equalsWithGroup() { Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); @@ -36,7 +38,7 @@ public void equalsWithGroup() { } @Test - public void equalsWithLandscape() { + void equalsWithLandscape() { Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); @@ -51,22 +53,10 @@ public void equalsWithLandscape() { assertNotEquals(s1, s3); } - @Test - public void labelsAreNotGroupedInApi() { - - Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); - - Item s1 = getTestItem("g1", "a", landscape); - s1.getLabels().put("foo.one", "one"); - s1.getLabels().put("foo.two", "two"); - Map labels = s1.getJSONLabels(); - assertThat(labels).containsKey("foo.one"); - assertThat(labels).containsKey("foo.two"); - } @Test - public void getChangesInLabels() { + void getChangesInLabels() { Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); Item s1 = getTestItem("g1", "a", landscape); @@ -81,7 +71,7 @@ public void getChangesInLabels() { } @Test - public void getChangesInName() { + void getChangesInName() { Item s1 = getTestItemBuilder("g1", "a") .withName("foo") @@ -97,7 +87,7 @@ public void getChangesInName() { } @Test - public void getChangesInDescription() { + void getChangesInDescription() { Item s1 = getTestItemBuilder("g1", "a") .withDescription("foo") @@ -113,7 +103,7 @@ public void getChangesInDescription() { } @Test - public void getChangesInOwner() { + void getChangesInOwner() { Item s1 = getTestItemBuilder("g1", "a") .withOwner("foo") @@ -129,7 +119,7 @@ public void getChangesInOwner() { } @Test - public void getChangesInLinks() { + void getChangesInLinks() { Item s1 = getTestItemBuilder("g1", "a") .withLinks(Map.of("foo", new Link("https://acme.com"))) @@ -145,17 +135,32 @@ public void getChangesInLinks() { } @Test - public void setRelations() { + void setRelations() { Item s1 = getTestItemBuilder("g1", "a").build(); Item s2 = getTestItemBuilder("g1", "b").build(); Item s3 = getTestItemBuilder("g1", "c").build(); - s1.setRelations(Set.of(new Relation(s1, s2))); + s1.setRelations(Set.of(RelationFactory.createForTesting(s1, s2))); assertThat(s1.getRelations()).hasSize(1); //when - s1.setRelations(Set.of(new Relation(s1, s3))); + s1.setRelations(Set.of(RelationFactory.createForTesting(s1, s3))); assertThat(s1.getRelations()).hasSize(1); } + + @Test + void relationsAsAssessmentChildren() { + + Item s1 = getTestItemBuilder("g1", "a").build(); + Item s2 = getTestItemBuilder("g2", "b").build(); + Relation forTesting = RelationFactory.createForTesting(s1, s2); + s1.addOrReplace(forTesting); + + //when + List children = s1.getChildren(); + assertThat(children).hasSize(1); + assertThat(children.get(0)).isEqualTo(forTesting); + + } } diff --git a/src/test/java/de/bonndan/nivio/model/LabeledTest.java b/src/test/java/de/bonndan/nivio/model/LabeledTest.java index 30594f781..e6dccde95 100644 --- a/src/test/java/de/bonndan/nivio/model/LabeledTest.java +++ b/src/test/java/de/bonndan/nivio/model/LabeledTest.java @@ -34,7 +34,7 @@ void groupedByPrefixes() { } @Test - public void setPrefixed() { + void setPrefixed() { ItemDescription itemDescription = new ItemDescription(); itemDescription.setPrefixed(Label.network, "foo"); assertEquals(1, itemDescription.getLabels(Label.network).size()); @@ -44,7 +44,7 @@ public void setPrefixed() { } @Test - public void setLabelsDoesNotOverwriteExistingOnes() { + void setLabelsDoesNotOverwriteExistingOnes() { ItemDescription itemDescription = new ItemDescription(); itemDescription.setLabel("foo", "bar"); @@ -56,14 +56,14 @@ public void setLabelsDoesNotOverwriteExistingOnes() { } @Test - public void withoutPrefixes() { + void withoutPrefixes() { ItemDescription itemDescription = new ItemDescription(); itemDescription.setLabel(Label.costs, "123"); itemDescription.setPrefixed(Label.network, "foo"); itemDescription.setPrefixed(Label.status, "bar"); - itemDescription.setPrefixed(Label.condition, "bar"); + itemDescription.setPrefixed(Label._condition, "bar"); - Map stringStringMap = Labeled.withoutKeys(itemDescription.getLabels(), Label.condition.name(), Label.status.name()); + Map stringStringMap = Labeled.withoutKeys(itemDescription.getLabels(), Label._condition.name(), Label.status.name()); assertThat(stringStringMap).isNotNull(); assertThat(stringStringMap.size()).isEqualTo(2); assertThat(stringStringMap.get(Label.costs.name())).isEqualTo("123"); @@ -96,17 +96,15 @@ void diff() { } @Test - void diffIgnoresAppearanceLabels() { + void diffIgnoresInternalLabels() { //given ItemDescription before = new ItemDescription(); - before.setLabel(Label.color, "123"); - before.setLabel(Label.fill, "aaff33"); - before.setLabel(Label.icon, "foo"); + before.setLabel(Label._filldata, "aaff33"); + before.setLabel(Label._icondata, "foo"); ItemDescription after = new ItemDescription(); - after.setLabel(Label.color, ""); - after.setLabel(Label.fill, ""); - after.setLabel(Label.icon, ""); + after.setLabel(Label._filldata, ""); + after.setLabel(Label._icondata, ""); //when List diff = after.diff(before); @@ -131,4 +129,41 @@ void anySetterAcceptsNumber() { //then assertThat(i.getLabel("foo")).isEqualTo("1"); } + + @Test + void merge() { + ItemDescription i = new ItemDescription(); + i.setLabel("foo1", 1L); + i.setLabel("foo2", 1L); + ItemDescription target = new ItemDescription(); + i.setLabel("foo1", 2L); + i.setLabel("bar", 2L); + + //when + Labeled.merge(i, target); + + //then + assertThat(target.getLabel("foo1")).isEqualTo("2"); + assertThat(target.getLabel("foo2")).isEqualTo("1"); + assertThat(target.getLabel("bar")).isEqualTo("2"); + } + + @Test + void add() { + ItemDescription i = new ItemDescription(); + i.setLabel("foo1", "after"); + i.setLabel("foo2", 1L); + + ItemDescription target = new ItemDescription(); + i.setLabel("foo1", "before"); + i.setLabel("bar", 2L); + + //when + Labeled.add(i, target); + + //then + assertThat(target.getLabel("foo1")).isEqualTo("before"); + assertThat(target.getLabel("foo2")).isEqualTo("1"); + assertThat(target.getLabel("bar")).isEqualTo("2"); + } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java b/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java index b1efea084..fc48f24f9 100644 --- a/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/model/LandscapeFactoryTest.java @@ -12,7 +12,8 @@ import static de.bonndan.nivio.model.ItemFactory.getTestItem; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; class LandscapeFactoryTest { @@ -99,7 +100,7 @@ void fromInputAddsKPIs() { Landscape landscape = LandscapeFactory.createFromInput(description); assertThat(landscape.getKpis()).isNotEmpty(); - assertThat(landscape.getKpis()).hasSize(4); + assertThat(landscape.getKpis()).hasSize(5); } @Test @@ -117,6 +118,6 @@ void recreateAddsKPIs() { Landscape landscape = LandscapeFactory.recreate(existing, description); assertThat(landscape.getKpis()).isNotEmpty(); - assertThat(landscape.getKpis()).hasSize(4); + assertThat(landscape.getKpis()).hasSize(5); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/model/RelationBuilderTest.java b/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java similarity index 70% rename from src/test/java/de/bonndan/nivio/model/RelationBuilderTest.java rename to src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java index 6083f7248..e2a812bd1 100644 --- a/src/test/java/de/bonndan/nivio/model/RelationBuilderTest.java +++ b/src/test/java/de/bonndan/nivio/model/RelationFactoryTest.java @@ -11,7 +11,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -class RelationBuilderTest { +class RelationFactoryTest { private Landscape landscape; @@ -23,7 +23,7 @@ void setUp() { @Test void createProviderDescription() { //when - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "bar"); //then assertThat(providerDescription).isNotNull(); @@ -38,7 +38,7 @@ void createDataflowDescription() { ItemDescription desc = new ItemDescription("foo"); //when - RelationDescription providerDescription = RelationBuilder.createDataflowDescription(desc, "bar"); + RelationDescription providerDescription = RelationFactory.createDataflowDescription(desc, "bar"); //then assertThat(providerDescription).isNotNull(); @@ -55,7 +55,7 @@ void createProviderRelation() { Item bar = ItemFactory.getTestItem("b", "bar"); //when - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); //then assertThat(relation).isNotNull(); @@ -70,23 +70,30 @@ void update() { //given Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); + relation.setLabel("foo1", "bar1"); foo.setRelations(Set.of(relation)); bar.setRelations(Set.of(relation)); landscape.setItems(Set.of(foo, bar)); //landscape contains fooCopy instead of foo! - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "bar"); providerDescription.setFormat("json"); providerDescription.setDescription("huhu"); + providerDescription.setType(RelationType.DATAFLOW); + providerDescription.setLabel("foo1", "bar2"); + providerDescription.setLabel("foo2", "bar2"); //when - Relation newRelation = RelationBuilder.update(relation, providerDescription, landscape); + Relation newRelation = RelationFactory.update(relation, providerDescription, landscape); //then assertThat(newRelation.getSource()).isEqualTo(foo); assertThat(newRelation.getTarget()).isEqualTo(bar); assertThat(newRelation.getFormat()).isEqualTo("json"); + assertThat(newRelation.getType()).isEqualTo(RelationType.DATAFLOW); assertThat(newRelation.getDescription()).isEqualTo("huhu"); + assertThat(newRelation.getLabel("foo1")).isEqualTo("bar2"); + assertThat(newRelation.getLabel("foo2")).isEqualTo("bar2"); } @Test @@ -95,15 +102,15 @@ void updateThrows() { //given Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); foo.setRelations(Set.of(relation)); bar.setRelations(Set.of(relation)); landscape.setItems(Set.of(foo, bar)); //landscape contains fooCopy instead of foo! - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "oops"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "oops"); //when - assertThrows(NoSuchElementException.class, () -> RelationBuilder.update(relation, providerDescription, landscape)); + assertThrows(NoSuchElementException.class, () -> RelationFactory.update(relation, providerDescription, landscape)); } @Test @@ -113,15 +120,15 @@ void updateRegardsReference() { Item foo = ItemFactory.getTestItem("a", "foo"); Item fooCopy = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); - Relation relation = RelationBuilder.createProviderRelation(foo, bar); + Relation relation = RelationFactory.createProviderRelation(foo, bar); foo.setRelations(Set.of(relation)); bar.setRelations(Set.of(relation)); landscape.setItems(Set.of(fooCopy, bar)); //landscape contains fooCopy instead of foo! - RelationDescription providerDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription providerDescription = RelationFactory.createProviderDescription("foo", "bar"); //when - Relation newRelation = RelationBuilder.update(relation, providerDescription, landscape); + Relation newRelation = RelationFactory.update(relation, providerDescription, landscape); //then assertThat(newRelation.getSource() == fooCopy).isTrue(); //ensuring the item in the landscape is used @@ -135,14 +142,16 @@ void create() { Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); landscape.setItems(Set.of(foo, bar)); - RelationDescription relationDescription = RelationBuilder.createProviderDescription("foo", "bar"); + RelationDescription relationDescription = RelationFactory.createProviderDescription("foo", "bar"); + relationDescription.setLabel("foo1", "bar1"); //when - Relation newRelation = RelationBuilder.create(foo, relationDescription, landscape); + Relation newRelation = RelationFactory.create(foo, relationDescription, landscape); //then assertThat(newRelation.getSource()).isEqualTo(foo); assertThat(newRelation.getTarget()).isEqualTo(bar); + assertThat(newRelation.getLabel("foo1")).isEqualTo("bar1"); } @Test @@ -152,9 +161,9 @@ void createThrows() { Item foo = ItemFactory.getTestItem("a", "foo"); Item bar = ItemFactory.getTestItem("b", "bar"); landscape.setItems(Set.of(foo, bar)); - RelationDescription relationDescription = RelationBuilder.createProviderDescription("foo", "oops"); + RelationDescription relationDescription = RelationFactory.createProviderDescription("foo", "oops"); //when - assertThrows(NoSuchElementException.class, () -> RelationBuilder.create(foo, relationDescription, landscape)); + assertThrows(NoSuchElementException.class, () -> RelationFactory.create(foo, relationDescription, landscape)); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/model/RelationTest.java b/src/test/java/de/bonndan/nivio/model/RelationTest.java index f98d90672..557088cf8 100644 --- a/src/test/java/de/bonndan/nivio/model/RelationTest.java +++ b/src/test/java/de/bonndan/nivio/model/RelationTest.java @@ -1,5 +1,6 @@ package de.bonndan.nivio.model; +import de.bonndan.nivio.output.dto.RelationApiModel; import org.junit.jupiter.api.Test; import java.util.List; @@ -16,10 +17,10 @@ void toApiModel() { Item two = getTestItem("foo", "baz"); Relation relation = new Relation(one, two, null, null, RelationType.PROVIDER); - Relation.ApiModel apiModel = new Relation.ApiModel(relation, one); + RelationApiModel apiModel = new RelationApiModel(relation, one); assertThat(apiModel).isNotNull(); - assertThat(apiModel.direction).isEqualTo(Relation.ApiModel.OUTBOUND); + assertThat(apiModel.direction).isEqualTo(RelationApiModel.OUTBOUND); assertThat(apiModel.name).isEqualTo("baz"); assertThat(apiModel.type).isEqualTo(relation.getType()); assertThat(apiModel.source).isEqualTo(relation.getSource()); @@ -32,12 +33,12 @@ void toApiModel() { void inbound() { Item one = getTestItem("foo", "bar"); Item two = getTestItem("foo", "baz"); - Relation relation = new Relation(one, two); + Relation relation = RelationFactory.createForTesting(one, two); - Relation.ApiModel apiModel = new Relation.ApiModel(relation, two); + RelationApiModel apiModel = new RelationApiModel(relation, two); assertThat(apiModel).isNotNull(); - assertThat(apiModel.direction).isEqualTo(Relation.ApiModel.INBOUND); + assertThat(apiModel.direction).isEqualTo(RelationApiModel.INBOUND); assertThat(apiModel.name).isEqualTo("bar"); } @@ -45,12 +46,12 @@ void inbound() { void inboundName() { Item one = getTestItemBuilder("foo", "bar").withName("huhu").build(); Item two = getTestItem("foo", "baz"); - Relation relation = new Relation(one, two); + Relation relation = RelationFactory.createForTesting(one, two); - Relation.ApiModel apiModel = new Relation.ApiModel(relation, two); + RelationApiModel apiModel = new RelationApiModel(relation, two); assertThat(apiModel).isNotNull(); - assertThat(apiModel.direction).isEqualTo(Relation.ApiModel.INBOUND); + assertThat(apiModel.direction).isEqualTo(RelationApiModel.INBOUND); assertThat(apiModel.name).isEqualTo("huhu"); } diff --git a/src/test/java/de/bonndan/nivio/notification/MessagingServiceTest.java b/src/test/java/de/bonndan/nivio/notification/MessagingServiceTest.java index 6b8e268ff..8bacf1b51 100644 --- a/src/test/java/de/bonndan/nivio/notification/MessagingServiceTest.java +++ b/src/test/java/de/bonndan/nivio/notification/MessagingServiceTest.java @@ -1,5 +1,7 @@ package de.bonndan.nivio.notification; +import de.bonndan.nivio.assessment.Assessment; +import de.bonndan.nivio.assessment.AssessmentChangedEvent; import de.bonndan.nivio.input.ProcessingChangelog; import de.bonndan.nivio.input.ProcessingFinishedEvent; import de.bonndan.nivio.input.dto.LandscapeDescription; @@ -66,6 +68,23 @@ void onInputChangedEvent() { assertThat(value.getMessage()).isEqualTo("foo"); } + @Test + void onAssessmentChangeEvent() { + AssessmentChangedEvent event = new AssessmentChangedEvent( + LandscapeFactory.createForTesting("test", "testLandscape").build(), Assessment.empty() + ); + messagingService.onAssessmentChangedEvent(event); + + ArgumentCaptor captor = ArgumentCaptor.forClass(EventNotification.class); + verify(tpl).convertAndSend(eq(WebSocketConfig.TOPIC + WebSocketConfig.EVENTS), captor.capture()); + + EventNotification value = captor.getValue(); + assertNotNull(value); + assertThat(value.getLevel()).isEqualTo("info"); + assertThat(value.getType()).isEqualTo("AssessmentChangedEvent"); + assertThat(value.getLandscape()).isEqualTo("test"); + } + @Test void getLast() { diff --git a/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java b/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java index 64208c9bb..fb2da6b49 100644 --- a/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/observation/LandscapeObserverFactoryTest.java @@ -59,7 +59,7 @@ public void getObservers() throws MalformedURLException { InputFormatHandler handler = mock(InputFormatHandler.class); InputFormatObserver mockObserver = mock(InputFormatObserver.class); - when(handler.getObserver(any(InputFormatObserver.class), any(SourceReference.class))).thenReturn(mockObserver); + when(handler.getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), any(SourceReference.class))).thenReturn(mockObserver); when(formatFactory.getInputFormatHandler(any(SourceReference.class))).thenReturn(handler); when(fileFetcher.get(any(URL.class))).thenReturn(""); @@ -75,7 +75,7 @@ public void getObservers() throws MalformedURLException { verify(formatFactory).getInputFormatHandler(eq(ref1)); - verify(handler).getObserver(any(InputFormatObserver.class), eq(ref1)); + verify(handler).getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), eq(ref1)); } @Test @@ -91,7 +91,7 @@ public void withoutSourceUrl() { description.getSourceReferences().add(ref1); InputFormatHandler handler = mock(InputFormatHandler.class); - when(handler.getObserver(any(InputFormatObserver.class), any(SourceReference.class))).thenReturn(mock(InputFormatObserver.class)); + when(handler.getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), any(SourceReference.class))).thenReturn(mock(InputFormatObserver.class)); when(formatFactory.getInputFormatHandler(any(SourceReference.class))).thenReturn(handler); //when @@ -104,7 +104,7 @@ public void withoutSourceUrl() { assertEquals(1, observers.size()); verify(formatFactory).getInputFormatHandler(eq(ref1)); - verify(handler).getObserver(any(InputFormatObserver.class), eq(ref1)); + verify(handler).getObserver(any(ApplicationEventPublisher.class), any(Landscape.class), eq(ref1)); } private String getRootPath() { diff --git a/src/test/java/de/bonndan/nivio/observation/LandscapeObserverPoolTest.java b/src/test/java/de/bonndan/nivio/observation/LandscapeObserverPoolTest.java index 9da8ece91..d1fdd8b3a 100644 --- a/src/test/java/de/bonndan/nivio/observation/LandscapeObserverPoolTest.java +++ b/src/test/java/de/bonndan/nivio/observation/LandscapeObserverPoolTest.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.*; + class LandscapeObserverPoolTest { private ThreadPoolTaskScheduler scheduler; @@ -19,13 +20,14 @@ class LandscapeObserverPoolTest { void setup() { scheduler = mock(ThreadPoolTaskScheduler.class); scheduledFuture = mock(ScheduledFuture.class); + var observerConfigProperties = mock(ObserverConfigProperties.class); when(scheduler.scheduleWithFixedDelay(any(Runnable.class), anyLong())).thenReturn(scheduledFuture); - landscapeObserverPool = new LandscapeObserverPool(scheduler, 1); + landscapeObserverPool = new LandscapeObserverPool(scheduler, observerConfigProperties); } @Test - public void schedulesRunnables() { + void schedulesRunnables() { InputFormatObserver observer1 = mock(InputFormatObserver.class); InputFormatObserver observer2 = mock(InputFormatObserver.class); InputFormatObserver observer3 = mock(InputFormatObserver.class); @@ -34,11 +36,11 @@ public void schedulesRunnables() { landscapeObserverPool.updateObservers(List.of(observer1, observer2, observer3)); //then - verify(scheduler, times(3)).scheduleWithFixedDelay(any(Runnable.class), eq(1L)); + verify(scheduler, times(3)).scheduleWithFixedDelay(any(Runnable.class), eq(30000L)); } @Test - public void stopsScheduledTasks() { + void stopsScheduledTasks() { InputFormatObserver observer1 = mock(InputFormatObserver.class); InputFormatObserver observer2 = mock(InputFormatObserver.class); landscapeObserverPool.updateObservers(List.of(observer1, observer2)); diff --git a/src/test/java/de/bonndan/nivio/observation/ObserverConfigPropertiesTest.java b/src/test/java/de/bonndan/nivio/observation/ObserverConfigPropertiesTest.java new file mode 100644 index 000000000..fbb12b789 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/observation/ObserverConfigPropertiesTest.java @@ -0,0 +1,25 @@ +package de.bonndan.nivio.observation; + +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest +class ObserverConfigPropertiesTest { + + @Autowired + ObserverConfigProperties observerConfigProperties; + + @Test + void testObserver() { + var map = Map.of("KubernetesObserver", 1); + assertThat(observerConfigProperties.getScanDelay()).isEqualTo(map); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/observation/ObserverRegistryTest.java b/src/test/java/de/bonndan/nivio/observation/ObserverRegistryTest.java index 723d73d51..b3597efdb 100644 --- a/src/test/java/de/bonndan/nivio/observation/ObserverRegistryTest.java +++ b/src/test/java/de/bonndan/nivio/observation/ObserverRegistryTest.java @@ -30,6 +30,7 @@ class ObserverRegistryTest { private Landscape landscape; private ThreadPoolTaskScheduler taskScheduler; private IndexingDispatcher indexingDispatcher; + private ObserverConfigProperties observerConfigProperties; @BeforeEach public void setup() { @@ -37,7 +38,8 @@ public void setup() { taskScheduler = mock(ThreadPoolTaskScheduler.class); observerPoolFactory = mock(LandscapeObserverFactory.class); indexingDispatcher = mock(IndexingDispatcher.class); - observerRegistry = new ObserverRegistry(observerPoolFactory, taskScheduler, indexingDispatcher); + observerConfigProperties = mock(ObserverConfigProperties.class); + observerRegistry = new ObserverRegistry(observerPoolFactory, taskScheduler, indexingDispatcher, observerConfigProperties); } @Test diff --git a/src/test/java/de/bonndan/nivio/output/RenderingTest.java b/src/test/java/de/bonndan/nivio/output/RenderingTest.java index 5b9fc82ae..abb9457c1 100644 --- a/src/test/java/de/bonndan/nivio/output/RenderingTest.java +++ b/src/test/java/de/bonndan/nivio/output/RenderingTest.java @@ -2,24 +2,32 @@ import com.fasterxml.jackson.databind.ObjectMapper; import de.bonndan.nivio.assessment.Assessment; -import de.bonndan.nivio.input.*; +import de.bonndan.nivio.config.ApplicationConfig; +import de.bonndan.nivio.input.FileFetcher; +import de.bonndan.nivio.input.Indexer; +import de.bonndan.nivio.input.InputFormatHandlerFactory; +import de.bonndan.nivio.input.LandscapeDescriptionFactory; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.input.external.LinkHandlerFactory; import de.bonndan.nivio.input.http.CachedResponse; import de.bonndan.nivio.input.http.HttpService; -import de.bonndan.nivio.input.external.LinkHandlerFactory; import de.bonndan.nivio.input.nivio.InputFormatHandlerNivio; import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.model.LandscapeRepository; +import de.bonndan.nivio.output.icons.ExternalIcons; +import de.bonndan.nivio.output.icons.ExternalIconsProvider; import de.bonndan.nivio.output.icons.IconService; import de.bonndan.nivio.output.icons.LocalIcons; -import de.bonndan.nivio.output.icons.ExternalIcons; +import de.bonndan.nivio.output.layout.AppearanceProcessor; +import de.bonndan.nivio.output.layout.LayoutService; import de.bonndan.nivio.output.layout.LayoutedComponent; import de.bonndan.nivio.output.layout.OrganicLayouter; +import de.bonndan.nivio.output.map.RenderingRepository; import de.bonndan.nivio.output.map.svg.MapStyleSheetFactory; -import de.bonndan.nivio.output.map.svg.SVGDocument; import de.bonndan.nivio.output.map.svg.SVGRenderer; import de.bonndan.nivio.util.RootPath; import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; import org.springframework.context.ApplicationEventPublisher; import java.io.File; @@ -43,11 +51,17 @@ public abstract class RenderingTest { protected Indexer indexer; protected LandscapeDescriptionFactory factory; protected HttpService httpService; + private ObjectMapper objectMapper; + private LayoutService layoutService; + private AppearanceProcessor appearanceProcessor; public void setup() throws URISyntaxException { landscapeRepository = new LandscapeRepository(); formatFactory = new InputFormatHandlerFactory(List.of(new InputFormatHandlerNivio(new FileFetcher(new HttpService())))); httpService = mock(HttpService.class); + objectMapper = new ApplicationConfig(null).jackson2ObjectMapperBuilder().build(); + var externalIconsProvider = Mockito.mock(ExternalIconsProvider.class); + CachedResponse response = mock(CachedResponse.class); when(response.getBytes()).thenReturn("foo".getBytes()); @@ -57,46 +71,51 @@ public void setup() throws URISyntaxException { factory = new LandscapeDescriptionFactory(fileFetcher); LinkHandlerFactory linkHandlerFactory = mock(LinkHandlerFactory.class); - IconService iconService = new IconService(new LocalIcons(), new ExternalIcons(httpService)); - indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, mock(ApplicationEventPublisher.class), iconService); + IconService iconService = new IconService(new LocalIcons(), new ExternalIcons(httpService, externalIconsProvider)); + + MapStyleSheetFactory mapStyleSheetFactory = mock(MapStyleSheetFactory.class); + when(mapStyleSheetFactory.getMapStylesheet(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(""); + appearanceProcessor = new AppearanceProcessor(new IconService(new LocalIcons(""), new ExternalIcons(httpService, externalIconsProvider))); + layoutService = new LayoutService( + new AppearanceProcessor(iconService), + new OrganicLayouter(), + new SVGRenderer(mapStyleSheetFactory), + new RenderingRepository(), + mock(ApplicationEventPublisher.class) + ); + indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, mock(ApplicationEventPublisher.class)); } protected Landscape getLandscape(String path) { File file = new File(RootPath.get() + path); LandscapeDescription landscapeDescription = factory.fromYaml(file); indexer.index(landscapeDescription); - return landscapeRepository.findDistinctByIdentifier(landscapeDescription.getIdentifier()).orElseThrow(); + + Landscape landscape = landscapeRepository.findDistinctByIdentifier(landscapeDescription.getIdentifier()).orElseThrow(); + appearanceProcessor.process(landscape); + return landscape; } protected LayoutedComponent debugRenderLandscape(String path, Landscape landscape) throws IOException { - OrganicLayouter layouter = new OrganicLayouter(); - LayoutedComponent graph = layouter.layout(landscape); - toSVG(graph, new Assessment(landscape.applyKPIs(landscape.getKpis())), RootPath.get() + path); + LayoutedComponent graph = layoutService.layout(landscape); + toSVG(landscape, new Assessment(landscape.applyKPIs(landscape.getKpis())), RootPath.get() + path); return graph; } protected String renderLandscape(String path, Landscape landscape) throws IOException { - - OrganicLayouter layouter = new OrganicLayouter(); - LayoutedComponent graph = layouter.layout(landscape); - return toSVG(graph, new Assessment(landscape.applyKPIs(landscape.getKpis())), RootPath.get() + path); + return toSVG(landscape, new Assessment(landscape.applyKPIs(landscape.getKpis())), RootPath.get() + path); } - private String toSVG(LayoutedComponent layoutedComponent, Assessment assessment, String filename) throws IOException { - - MapStyleSheetFactory mapStyleSheetFactory = mock(MapStyleSheetFactory.class); - when(mapStyleSheetFactory.getMapStylesheet(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(""); + private String toSVG(Landscape landscape, Assessment assessment, String filename) throws IOException { File json = new File(filename + "_debug.json"); - new ObjectMapper().writeValue(json, layoutedComponent); + objectMapper.writeValue(json, layoutService.layout(landscape)); - SVGRenderer svgRenderer = new SVGRenderer(mapStyleSheetFactory); - SVGDocument svg = svgRenderer.render(layoutedComponent, assessment, true); + String xml = (String) layoutService.render(landscape, assessment, true); File svgFile = new File(filename + "_debug.svg"); FileWriter fileWriter = new FileWriter(svgFile); - String xml = svg.getXML(); fileWriter.write(xml); fileWriter.close(); return xml; diff --git a/src/test/java/de/bonndan/nivio/output/docs/DocsControllerTest.java b/src/test/java/de/bonndan/nivio/output/docs/DocsControllerTest.java index ac0a2b1ac..4b4f05078 100644 --- a/src/test/java/de/bonndan/nivio/output/docs/DocsControllerTest.java +++ b/src/test/java/de/bonndan/nivio/output/docs/DocsControllerTest.java @@ -8,6 +8,7 @@ import de.bonndan.nivio.model.LandscapeRepository; import de.bonndan.nivio.output.LocalServer; import de.bonndan.nivio.output.icons.ExternalIcons; +import de.bonndan.nivio.output.icons.ExternalIconsProvider; import de.bonndan.nivio.output.icons.IconService; import de.bonndan.nivio.output.icons.LocalIcons; import org.junit.jupiter.api.BeforeAll; @@ -34,8 +35,9 @@ class DocsControllerTest { static void setup() { assessmentRepository = Mockito.mock(AssessmentRepository.class); landscapeRepository = Mockito.mock(LandscapeRepository.class); + var externalIconsProvider = Mockito.mock(ExternalIconsProvider.class); LocalServer localServer = new LocalServer("test"); - IconService iconService = new IconService(new LocalIcons(), new ExternalIcons(new HttpService())); + IconService iconService = new IconService(new LocalIcons(), new ExternalIcons(new HttpService(), externalIconsProvider)); docsController = new DocsController(landscapeRepository, localServer, iconService, assessmentRepository); } diff --git a/src/test/java/de/bonndan/nivio/output/docs/OwnersReportGeneratorTest.java b/src/test/java/de/bonndan/nivio/output/docs/OwnersReportGeneratorTest.java new file mode 100644 index 000000000..1b7b1bfb8 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/docs/OwnersReportGeneratorTest.java @@ -0,0 +1,53 @@ +package de.bonndan.nivio.output.docs; + +import de.bonndan.nivio.assessment.AssessmentFactory; +import de.bonndan.nivio.assessment.kpi.ConditionKPI; +import de.bonndan.nivio.assessment.kpi.KPI; +import de.bonndan.nivio.model.Item; +import de.bonndan.nivio.model.ItemBuilder; +import de.bonndan.nivio.model.LandscapeFactory; +import de.bonndan.nivio.output.LocalServer; +import de.bonndan.nivio.output.icons.IconService; +import org.assertj.core.util.Arrays; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.net.URI; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class OwnersReportGeneratorTest { + + @Test + void toDocument() { + // given + var ownersReportGenerator = new OwnersReportGenerator(Mockito.mock(LocalServer.class), Mockito.mock(IconService.class)); + var conditionKpi = new ConditionKPI(); + var map = new HashMap(); + map.put("test", conditionKpi); + URI uri = URI.create("https://www.nivio.com/"); + String[] tags = Arrays.array("auth", "ui"); + var landscape = LandscapeFactory.createForTesting("test", "test").build(); + Item foo = ItemBuilder.anItem().withLandscape(landscape).withIdentifier("nivio").withGroup("nivio").withAddress(uri).build(); + foo.setTags(tags); + landscape.setItems(Set.of(foo)); + var assessment = AssessmentFactory.createAssessment(landscape, map); + var searchConfig = new SearchConfig(Map.of("title", new String[]{"test"})); + + // when + String document = ownersReportGenerator.toDocument(landscape, assessment, searchConfig); + + // then + assertThat(document).contains("Date: " + ZonedDateTime.now().format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT))) + .contains(searchConfig.getTitle()) + .contains("Address: https://www.nivio.com/") + .contains("Tags: auth, ui") + .doesNotContain("Null"); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/dto/ApiModelTest.java b/src/test/java/de/bonndan/nivio/output/dto/ApiModelTest.java new file mode 100644 index 000000000..7edf93cf9 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/dto/ApiModelTest.java @@ -0,0 +1,57 @@ +package de.bonndan.nivio.output.dto; + +import de.bonndan.nivio.input.kubernetes.InputFormatHandlerKubernetes; +import de.bonndan.nivio.model.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static de.bonndan.nivio.model.ItemFactory.getTestItemBuilder; +import static org.assertj.core.api.Assertions.assertThat; + +class ApiModelTest { + + private Landscape landscape; + private Group group; + private ItemBuilder itemTemplate; + + @BeforeEach + void setUp() { + landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); + group = new Group("g1", landscape.getIdentifier()); + itemTemplate = getTestItemBuilder("g1", "a").withLandscape(landscape).withType("two"); + } + + @Test + void labelsAreNotGroupedInApi() { + + Item s1 = itemTemplate.build(); + s1.getLabels().put("foo.one", "one"); + s1.getLabels().put("foo.two", "two"); + + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + + //when + Map labels = itemApiModel.getLabels(); + + //then + assertThat(labels).containsKey("foo.one").containsKey("foo.two"); + } + + @Test + void labelsAreExcludedInJson() { + + Item s1 = itemTemplate.build(); + s1.getLabels().put(InputFormatHandlerKubernetes.LABEL_PREFIX + ".foo", "one"); + + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + + + //when + Map labels = itemApiModel.getLabels(); + + //then + assertThat(labels).doesNotContainKey(InputFormatHandlerKubernetes.LABEL_PREFIX + ".foo"); + } +} diff --git a/src/test/java/de/bonndan/nivio/output/dto/GroupApiModelTest.java b/src/test/java/de/bonndan/nivio/output/dto/GroupApiModelTest.java new file mode 100644 index 000000000..9d83dba17 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/dto/GroupApiModelTest.java @@ -0,0 +1,79 @@ +package de.bonndan.nivio.output.dto; + +import de.bonndan.nivio.model.FullyQualifiedIdentifier; +import de.bonndan.nivio.model.Group; +import de.bonndan.nivio.model.Label; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class GroupApiModelTest { + GroupApiModel groupApiModel; + + @BeforeEach + void setUp() { + var group = new Group("test", "test", "testOwner", "testDescription", "testContact", "testColor"); + groupApiModel = new GroupApiModel(group, new HashSet<>()); + group.setLabel(Label._icondata, "iconurl,base64"); + } + + @Test + void getFullyQualifiedIdentifier() { + assertThat(groupApiModel.getFullyQualifiedIdentifier()).isEqualTo(FullyQualifiedIdentifier.build("test", "test", "")); + } + + @Test + void getName() { + assertThat(groupApiModel.getName()).isEqualTo("test"); + } + + @Test + void getIdentifier() { + assertThat(groupApiModel.getIdentifier()).isEqualTo("test"); + } + + @Test + void getOwner() { + assertThat(groupApiModel.getOwner()).isEqualTo("testOwner"); + } + + @Test + void getDescription() { + assertThat(groupApiModel.getDescription()).isEqualTo("testDescription"); + } + + @Test + void getContact() { + assertThat(groupApiModel.getContact()).isEqualTo("testContact"); + } + + @Test + void getColor() { + assertThat(groupApiModel.getColor()).isEqualTo("ec0000"); + } + + @Test + void getItems() { + assertThat(groupApiModel.getItems()).isEqualTo(Set.of()); + } + + @Test + void getLabels() { + assertThat(groupApiModel.getLabels()).isEqualTo(Map.of()); + } + + @Test + void getIcon() { + assertThat(groupApiModel.getIcon()).isEqualTo("iconurl,base64"); + } + + @Test + void getLandscapeIdentifier() { + assertThat(groupApiModel.getLandscapeIdentifier()).isEqualTo("test"); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/dto/ItemApiModelTest.java b/src/test/java/de/bonndan/nivio/output/dto/ItemApiModelTest.java new file mode 100644 index 000000000..9e73dda44 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/dto/ItemApiModelTest.java @@ -0,0 +1,192 @@ +package de.bonndan.nivio.output.dto; + +import de.bonndan.nivio.model.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Set; + +import static de.bonndan.nivio.model.ItemFactory.getTestItemBuilder; +import static org.assertj.core.api.Assertions.assertThat; + +class ItemApiModelTest { + + private Landscape landscape; + private ItemBuilder itemTemplate; + private Group group; + + @BeforeEach + void setUp() { + landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); + group = new Group("g1", landscape.getIdentifier()); + try { + itemTemplate = getTestItemBuilder("g1", "a").withAddress(new URI("https://dedica.team/")) + .withDescription("testDescription") + .withOwner("testOwner") + .withIcon("testIcon") + .withContact("testContact") + .withLandscape(landscape).withType("two"); + } catch (URISyntaxException ignored) { + } + } + + @Test + void setsGroupColor() { + + Item s1 = itemTemplate.build(); + group = GroupBuilder.aGroup() + .withIdentifier("g1") + .withLandscapeIdentifier(landscape.getIdentifier()) + .withColor("#aabbcc") + .build(); + + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + + //then + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + } + + @Test + void doesNotOverwriteColor() { + + Item s1 = itemTemplate.withColor("#00000").build(); + group = GroupBuilder.aGroup() + .withIdentifier("g1") + .withLandscapeIdentifier(landscape.getIdentifier()) + .withColor("#aabbcc") + .build(); + + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + + //then + assertThat(itemApiModel.getColor()).isEqualTo(s1.getColor()); + } + + @Test + void iconDataAsIcon() { + + Item s1 = itemTemplate.build(); + s1.setLabel(Label._icondata, "foo"); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + + //then + assertThat(itemApiModel.getIcon()).isEqualTo(s1.getLabel(Label._icondata)); + } + + @Test + void getIdentifier() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getIdentifier()).isEqualTo("a"); + } + + @Test + void getFullyQualifiedIdentifier() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getFullyQualifiedIdentifier()).isEqualTo(FullyQualifiedIdentifier.build("l1", "g1", "a")); + } + + @Test + void getName() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getName()).isEqualTo(""); + } + + @Test + void getOwner() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getOwner()).isEqualTo("testOwner"); + } + + @Test + void getContact() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getContact()).isEqualTo("testContact"); + } + + @Test + void getGroup() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getGroup()).isEqualTo("g1"); + } + + @Test + void getDescription() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getDescription()).isEqualTo("testDescription"); + } + + @Test + void getJSONRelations() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getJSONRelations()).isEqualTo(Map.of()); + } + + @Test + void getType() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getType()).isEqualTo("two"); + } + + @Test + void getAddress() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getAddress()).isEqualTo("https://dedica.team/"); + } + + @Test + void getInterfaces() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getInterfaces()).isEqualTo(Set.of()); + } + + @Test + void getTags() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.getTags()).isEqualTo(new String[0]); + } + + @Test + void hasLinks() { + Item s1 = itemTemplate.withLinks(Map.of("foo", new Link("http://acme.mcom"))).build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getLinks()).hasSize(1); + assertThat(itemApiModel.getLinks().get("foo")) + .isNotNull() + .satisfies(link -> assertThat(link.getHref().toString()).hasToString("http://acme.mcom")); + } + + @Test + void testToString() { + Item s1 = itemTemplate.build(); + ItemApiModel itemApiModel = new ItemApiModel(s1, group); + assertThat(itemApiModel.getColor()).isEqualTo(group.getColor()); + assertThat(itemApiModel.toString()).hasToString("l1/g1/a"); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/dto/LandscapeApiModelTest.java b/src/test/java/de/bonndan/nivio/output/dto/LandscapeApiModelTest.java new file mode 100644 index 000000000..3d913f171 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/dto/LandscapeApiModelTest.java @@ -0,0 +1,94 @@ +package de.bonndan.nivio.output.dto; + +import de.bonndan.nivio.input.ProcessLog; +import de.bonndan.nivio.input.dto.LandscapeSource; +import de.bonndan.nivio.model.FullyQualifiedIdentifier; +import de.bonndan.nivio.model.Label; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeConfig; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class LandscapeApiModelTest { + LandscapeApiModel landscapeApiModel; + LandscapeSource landscapeSource; + LandscapeConfig landscapeConfig; + ProcessLog processLog; + + @BeforeEach + void setUp() { + landscapeSource = Mockito.mock(LandscapeSource.class); + landscapeConfig = Mockito.mock(LandscapeConfig.class); + processLog = Mockito.mock(ProcessLog.class); + var landscape = new Landscape("test", Map.of(), "testName", "testContact", "testOwner", "testDescription", landscapeSource, landscapeConfig, processLog, Map.of()); + landscape.setLabel(Label.icon, "icon"); + landscape.setLabel(Label._icondata, "icon,base64"); + landscapeApiModel = new LandscapeApiModel(landscape); + } + + @Test + void getFullyQualifiedIdentifier() { + assertThat(landscapeApiModel.getFullyQualifiedIdentifier()).isEqualTo(FullyQualifiedIdentifier.build("test", "", "")); + } + + @Test + void getName() { + assertThat(landscapeApiModel.getName()).isEqualTo("testName"); + } + + @Test + void getIdentifier() { + assertThat(landscapeApiModel.getIdentifier()).isEqualTo("test"); + } + + @Test + void getOwner() { + assertThat(landscapeApiModel.getOwner()).isEqualTo("testOwner"); + } + + @Test + void getDescription() { + assertThat(landscapeApiModel.getDescription()).isEqualTo("testDescription"); + } + + @Test + void getContact() { + assertThat(landscapeApiModel.getContact()).isEqualTo("testContact"); + } + + @Test + void getLabels() { + assertThat(landscapeApiModel.getLabels()).isEqualTo(Map.of("icon", "icon")); + } + + @Test + void getIcon() { + assertThat(landscapeApiModel.getIcon()).isEqualTo("icon,base64"); + } + + @Test + void getConfig() { + assertThat(landscapeApiModel.getConfig()).isEqualTo(landscapeConfig); + } + + @Test + void getGroups() { + assertThat(landscapeApiModel.getGroups()).isEqualTo(Set.of()); + } + + @Test + void getLastUpdate() { + assertThat(landscapeApiModel.getLastUpdate()).isNull(); + } + + @Test + void getKpis() { + assertThat(landscapeApiModel.getKpis()).isEqualTo(Map.of()); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/icons/ExternIconYamlTest.java b/src/test/java/de/bonndan/nivio/output/icons/ExternIconYamlTest.java new file mode 100644 index 000000000..c458f2778 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/icons/ExternIconYamlTest.java @@ -0,0 +1,30 @@ +package de.bonndan.nivio.output.icons; + +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest +class ExternIconYamlTest { + @Autowired + ExternalIconsProvider externalIconsProvider; + @Autowired + ExternalIcons externalIconsTest; + + @Test + void init() { + var externalIconsUrl = externalIconsProvider.getUrls().entrySet(); + for (Map.Entry entry : externalIconsUrl) { + Optional url = externalIconsTest.getUrl(entry.getKey()); + assertThat(url).withFailMessage("URL for " + entry.getKey() + " is empty.").isPresent(); + } + } +} diff --git a/src/test/java/de/bonndan/nivio/output/icons/ExternalIconsProviderTest.java b/src/test/java/de/bonndan/nivio/output/icons/ExternalIconsProviderTest.java new file mode 100644 index 000000000..d5f91fda6 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/icons/ExternalIconsProviderTest.java @@ -0,0 +1,53 @@ +package de.bonndan.nivio.output.icons; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + + +@RunWith(SpringRunner.class) +@SpringBootTest +class ExternalIconsProviderTest { + + private Map configMap; + @Autowired + ExternalIconsProvider externalIconsProvider; + + @BeforeEach + void setUp() { + configMap = externalIconsProvider.getUrls(); + } + + @AfterEach + void tearDown() { + externalIconsProvider.setUrls(configMap); + } + + @Test + void getUrls() { + configMap = externalIconsProvider.getUrls(); + var testMap = Map.of("apachehttpd", "http://www.apache.org/logos/res/httpd/httpd.png", + "k8s", "https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png", + "kubernetes", "https://raw.githubusercontent.com/kubernetes/kubernetes/master/logo/logo.png", + "prometheus", "https://raw.githubusercontent.com/prometheus/docs/master/static/prometheus_logo.png", + "redhatkeycloak", "https://raw.githubusercontent.com/keycloak/keycloak-misc/master/logo/keycloak_icon_256px.png", + "redis", "https://redis.io/images/redis-white.png"); + assertThat(externalIconsProvider.getUrls()).isEqualTo(testMap); + } + + + @Test + void setUrls() { + var testMap = Map.of("testKey", "testValue"); + externalIconsProvider.setUrls(testMap); + assertThat(externalIconsProvider.getUrls()).isEqualTo(testMap); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/icons/ExternalIconsTest.java b/src/test/java/de/bonndan/nivio/output/icons/ExternalIconsTest.java index 8d996e557..4c386626b 100644 --- a/src/test/java/de/bonndan/nivio/output/icons/ExternalIconsTest.java +++ b/src/test/java/de/bonndan/nivio/output/icons/ExternalIconsTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import java.net.MalformedURLException; import java.net.URL; @@ -16,7 +17,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.ok; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; class ExternalIconsTest { @@ -26,11 +26,12 @@ class ExternalIconsTest { @BeforeEach public void setup() { + var externalIconsProvider = Mockito.mock(ExternalIconsProvider.class); wireMockServer = new WireMockServer(options().dynamicPort()); wireMockServer.start(); WireMock.configureFor("localhost", wireMockServer.port()); - externalIcons = new ExternalIcons(new HttpService()); + externalIcons = new ExternalIcons(new HttpService(), externalIconsProvider); externalIcons.add("redis", "http://localhost:" + wireMockServer.port() + FAKED_LOGO_PATH); } @@ -40,13 +41,13 @@ void stopWireMockServer() { } @Test - public void returnsEmpty() { + void returnsEmpty() { Optional s = externalIcons.getUrl("foo"); assertThat(s).isEmpty(); } @Test - public void usesVendorIcon() { + void usesVendorIcon() { wireMockServer.stubFor(get(FAKED_LOGO_PATH).willReturn(ok("somedata"))); Optional s = externalIcons.getUrl("redis"); @@ -56,7 +57,7 @@ public void usesVendorIcon() { } @Test - public void usesIconWithImageCacheIcon() { + void usesIconWithImageCacheIcon() { wireMockServer.stubFor(get(FAKED_LOGO_PATH).willReturn(ok("somedata"))); @@ -71,7 +72,7 @@ public void usesIconWithImageCacheIcon() { } @Test - public void loadUrl() throws MalformedURLException { + void loadUrl() throws MalformedURLException { wireMockServer.stubFor(get(FAKED_LOGO_PATH).willReturn(ok("somedata"))); @@ -85,4 +86,6 @@ public void loadUrl() throws MalformedURLException { wireMockServer.verify(1, RequestPatternBuilder.newRequestPattern().withUrl(FAKED_LOGO_PATH)); } + + } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/icons/IconMappingTest.java b/src/test/java/de/bonndan/nivio/output/icons/IconMappingTest.java new file mode 100644 index 000000000..a60a472fc --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/icons/IconMappingTest.java @@ -0,0 +1,40 @@ +package de.bonndan.nivio.output.icons; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +class IconMappingTest { + + private IconMapping iconMapping; + + @BeforeEach + void setup() { + iconMapping = new IconMapping(); + } + + @Test + void loadsNames() { + String name = "gift"; + Optional icon = iconMapping.getIcon(name); + assertThat(icon).isPresent(); + } + + @Test + void loadsAliases() { + String alias = "present"; + Optional icon = iconMapping.getIcon(alias); + assertThat(icon).isPresent(); + assertThat(icon.get()).isEqualTo("gift"); + } + + @Test + void fails() { + String name = "foobarbaz"; + Optional icon = iconMapping.getIcon(name); + assertThat(icon).isEmpty(); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/icons/IconServiceTest.java b/src/test/java/de/bonndan/nivio/output/icons/IconServiceTest.java index dc908ed4d..375d23df3 100644 --- a/src/test/java/de/bonndan/nivio/output/icons/IconServiceTest.java +++ b/src/test/java/de/bonndan/nivio/output/icons/IconServiceTest.java @@ -10,6 +10,7 @@ import java.util.Optional; import static de.bonndan.nivio.model.ItemFactory.getTestItem; +import static de.bonndan.nivio.model.ItemFactory.getTestItemBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.eq; @@ -30,35 +31,40 @@ public void setup() { @Test - public void returnsServiceWithUnknownType() { - Item item = getTestItem("test", "a"); - item.setLabel(Label.type, "asb"); + void returnsServiceWithUnknownType() { + Item item = getTestItemBuilder("test", "a").withType("abs").build(); + String expected = localIcons.getIconUrl(IconMapping.DEFAULT_ICON).orElseThrow(); + + //when + String iconUrl = iconService.getIconUrl(item); - String icon = localIcons.getIconUrl(IconMapping.DEFAULT_ICON.getIcon()).orElseThrow(); - assertThat(iconService.getIconUrl(getTestItem("test", "a"))).isEqualTo(icon); + assertThat(iconUrl).isEqualTo(expected); } @Test - public void returnsType() { - Item item = getTestItem("test", "a"); - item.setLabel(Label.type, "account"); + void returnsType() { + Item item = getTestItemBuilder("test", "a").withType("account").build(); String icon = localIcons.getIconUrl("account").orElseThrow(); assertThat(iconService.getIconUrl(item)).isEqualTo(icon); } @Test - public void doesNotResolvesIconTwice() { + void doesNotResolvesDataUrl() { Item item = getTestItem("test", "a"); - item.setLabel(Label.icon, DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foobar"); + String dataUrl = DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foobar"; + item.setLabel(Label.icon, dataUrl); + + //when + assertThat(iconService.getIconUrl(item)).isEqualTo(dataUrl); verify(externalIcons, never()).getUrl(any(String.class)); verify(externalIcons, never()).getUrl(any(URL.class)); } @Test - public void returnsCustomIcon() { + void returnsCustomIcon() { Item item = getTestItem("test", "a"); item.setLabel(Label.icon, "http://my.icon"); @@ -66,7 +72,7 @@ public void returnsCustomIcon() { } @Test - public void returnsVendorIcon() throws MalformedURLException { + void returnsVendorIcon() throws MalformedURLException { Item item = getTestItem("test", "a"); item.setLabel(Label.icon, "vendor://redis"); @@ -80,7 +86,7 @@ public void returnsVendorIcon() throws MalformedURLException { } @Test - public void getFillUrl() throws MalformedURLException { + void getFillUrl() throws MalformedURLException { when(externalIcons.getUrl(any(URL.class))).thenReturn(Optional.empty()); Optional fillUrl = iconService.getExternalUrl(new URL("http://my.icon")); diff --git a/src/test/java/de/bonndan/nivio/output/icons/LocalIconsTest.java b/src/test/java/de/bonndan/nivio/output/icons/LocalIconsTest.java index f572439c5..fa13e0339 100644 --- a/src/test/java/de/bonndan/nivio/output/icons/LocalIconsTest.java +++ b/src/test/java/de/bonndan/nivio/output/icons/LocalIconsTest.java @@ -1,14 +1,11 @@ package de.bonndan.nivio.output.icons; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Label; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.Base64; import java.util.Optional; -import static de.bonndan.nivio.model.ItemFactory.getTestItem; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -22,13 +19,13 @@ public void setup() { } @Test - public void throwsIfIconsMissing() { + void throwsIfIconsMissing() { assertThrows(RuntimeException.class, () -> new LocalIcons(System.getProperty("java.io.tmpdir"))); } @Test - public void encodesBase64DataUrls() { - Optional icon = localIcons.getIconUrl(IconMapping.DEFAULT_ICON.getIcon()); + void encodesBase64DataUrls() { + Optional icon = localIcons.getIconUrl(IconMapping.DEFAULT_ICON); assertThat(icon).isNotEmpty(); String payload = icon.get().replace(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64, ""); @@ -37,7 +34,7 @@ public void encodesBase64DataUrls() { } @Test - public void returnsDefault() { + void returnsDefault() { String icon = localIcons.getDefaultIcon(); assertThat(icon).isNotEmpty(); @@ -47,10 +44,7 @@ public void returnsDefault() { } @Test - public void returnsTypeIgnoreCase() { - Item item = getTestItem("test", "a"); - item.setLabel(Label.type, ""); - + void returnsTypeIgnoreCase() { assertThat(localIcons.getIconUrl("AccOunT")).isNotEmpty(); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java b/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java index de770b73a..1e3ce5a1e 100644 --- a/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java +++ b/src/test/java/de/bonndan/nivio/output/layout/AllGroupsLayoutTest.java @@ -15,29 +15,41 @@ class AllGroupsLayoutTest { @Test - public void testWithARelation() { + void testWithARelation() { Group a = new Group("a", "test"); + Item bara = getTestItem("a", "bara"); + Item fooa = getTestItem("a", "fooa"); + a.addOrReplaceItem(bara); + a.addOrReplaceItem(fooa); + Group b = new Group("b", "test"); + Item barb = getTestItem("b", "barb"); + Item foob = getTestItem("b", "foob"); + b.addOrReplaceItem(barb); + b.addOrReplaceItem(foob); + Group c = new Group("c", "test"); + Item barc = getTestItem("c", "barc"); + Item fooc = getTestItem("c", "fooc"); + c.addOrReplaceItem(barc); + c.addOrReplaceItem(fooc); - Landscape landscape = LandscapeFactory.createForTesting("test", "testLandscape").build(); + Landscape landscape = LandscapeFactory.createForTesting("test", "testLandscape").withItems(Set.of(fooa, bara, foob, barb, fooc, barc)).build(); - landscape.getGroups().put("a", a); - landscape.getGroups().put("b", b); - landscape.getGroups().put("c", c); + landscape.addGroup(a); + landscape.addGroup(b); + landscape.addGroup(c); - Map map = Map.of("a", getSubLayout(a), - "b", getSubLayout(b), - "c", getSubLayout(c) + Map map = Map.of( + "a", getSubLayout(a, Set.of(bara, fooa)), + "b", getSubLayout(b, Set.of(barb, foob)), + "c", getSubLayout(c, Set.of(barc, fooc)) ); //add some inter-group relations - Item item1 = a.getItems().iterator().next(); - Item item2 = b.getItems().iterator().next(); - Item item3 = c.getItems().iterator().next(); - item1.addOrReplace(new Relation(item1, item2)); - item2.addOrReplace(new Relation(item2, item3)); + bara.addOrReplace(RelationFactory.createForTesting(bara, barb)); + barb.addOrReplace(RelationFactory.createForTesting(barb, barc)); Map groupMap = new LinkedHashMap<>(); landscape.getGroups().forEach(groupMap::put); @@ -52,20 +64,12 @@ public void testWithARelation() { assertEquals(landscape, layoutedLandscape.getComponent()); assertEquals(3, layoutedLandscape.getChildren().size()); - //assert postition is always the same - assertEquals(327, Math.round(layoutedLandscape.getChildren().get(0).getX())); - assertEquals(-503, Math.round(layoutedLandscape.getChildren().get(0).getY())); + //assert position is always the same + assertEquals(-541, Math.round(layoutedLandscape.getChildren().get(0).getX())); + assertEquals(175, Math.round(layoutedLandscape.getChildren().get(0).getY())); } - private SubLayout getSubLayout(Group group) { - - Item bar = getTestItem(group.getIdentifier(), "bar" + group.getIdentifier()); - group.addItem(bar); - - Item baz = getTestItem(group.getIdentifier(), "baz" + group.getIdentifier()); - group.addItem(baz); - baz.addOrReplace(new Relation(baz, bar)); - - return new SubLayout(group, Set.of(bar, baz), new LandscapeConfig.LayoutConfig()); + private SubLayout getSubLayout(Group group, Set items) { + return new SubLayout(group, items, new LandscapeConfig.LayoutConfig()); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/layout/AppearanceProcessorTest.java b/src/test/java/de/bonndan/nivio/output/layout/AppearanceProcessorTest.java new file mode 100644 index 000000000..4eb98985c --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/layout/AppearanceProcessorTest.java @@ -0,0 +1,138 @@ +package de.bonndan.nivio.output.layout; + +import de.bonndan.nivio.model.*; +import de.bonndan.nivio.output.icons.DataUrlHelper; +import de.bonndan.nivio.output.icons.IconService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import static de.bonndan.nivio.model.ItemFactory.getTestItem; +import static de.bonndan.nivio.model.ItemFactory.getTestItemBuilder; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class AppearanceProcessorTest { + + private AppearanceProcessor resolver; + private Landscape landscape; + private IconService iconService; + private Group g1; + private ArrayList items; + + @BeforeEach + public void setup() { + + iconService = mock(IconService.class); + landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); + resolver = new AppearanceProcessor(iconService); + + + g1 = new Group("g1", "landscapeIdentifier"); + landscape.addGroup(g1); + items = new ArrayList<>(); + + Item s1 = getTestItemBuilder("g1", "s1").withLandscape(landscape).withType("loadbalancer").build(); + + items.add(s1); + g1.addOrReplaceItem(s1); + + Item s2 = getTestItem("g1", "s2", landscape); + + s2.setLabel(Label.icon, "https://foo.bar/icon.png"); + items.add(s2); + g1.addOrReplaceItem(s2); + + landscape.setItems(new HashSet<>(items)); + } + + @Test + void setItemIcons_LabelIcon() { + Item s1 = landscape.getItems().pick("s1", "g1"); + s1.setLabel(Label.icon, "https://dedica.team/images/logo_orange_weiss.png"); + when(iconService.getIconUrl(s1)).thenReturn(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); + + // when + resolver.process(landscape); + + // then + assertThat(s1.getLabel(Label._icondata)).isEqualTo(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); + } + + @Test + void setItemIcons_LabelFill() throws MalformedURLException { + Item s1 = landscape.getItems().pick("s1", "g1"); + s1.setLabel(Label.fill, "http://dedica.team/images/portrait.jpeg"); + when(iconService.getExternalUrl(new URL(s1.getLabel(Label.fill)))).thenReturn(java.util.Optional.of(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo")); + + // when + resolver.process(landscape); + + // then + assertThat(s1.getLabel(Label._filldata)).isEqualTo(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); + } + + @Test + void setLandscapeIcons_LabelIcon() throws MalformedURLException { + + // given + landscape.setLabel(Label.icon, "https://dedica.team/images/logo_orange_weiss.png"); + when(iconService.getExternalUrl(new URL(landscape.getLabel(Label.icon)))).thenReturn(java.util.Optional.of(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo")); + + // when + resolver.process(landscape); + + // then + assertThat(landscape.getLabel(Label._icondata)).isEqualTo(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); + } + + @Test + void setLandscapeIcons_LabelFill() throws MalformedURLException { + + // given + landscape.setLabel(Label.fill, "http://dedica.team/images/portrait.jpeg"); + when(iconService.getExternalUrl(new URL(landscape.getLabel(Label.fill)))).thenReturn(java.util.Optional.of(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo")); + + // when + resolver.process(landscape); + + // then + assertThat(landscape.getLabel(Label._filldata)).isEqualTo(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); + } + + @Test + void setGroupIcons_LabelIcon() throws MalformedURLException { + + // given + g1.setLabel(Label.icon, "https://dedica.team/images/logo_orange_weiss.png"); + when(iconService.getExternalUrl(new URL(g1.getLabel(Label.icon)))).thenReturn(java.util.Optional.of(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo")); + + // when + resolver.process(landscape); + + // then + assertThat(g1.getLabel(Label._icondata)).isEqualTo(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); + } + + @Test + void setGroupIcons_LabelFill() throws MalformedURLException { + + // given + g1.setLabel(Label.fill, "http://dedica.team/images/portrait.jpeg"); + when(iconService.getExternalUrl(new URL(g1.getLabel(Label.fill)))).thenReturn(java.util.Optional.of(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo")); + + // when + resolver.process(landscape); + + // then + assertThat(g1.getLabel(Label._filldata)).isEqualTo(DataUrlHelper.DATA_IMAGE_SVG_XML_BASE_64 + "foo"); + } + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/layout/LayoutServiceTest.java b/src/test/java/de/bonndan/nivio/output/layout/LayoutServiceTest.java new file mode 100644 index 000000000..1cd229d3d --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/layout/LayoutServiceTest.java @@ -0,0 +1,59 @@ +package de.bonndan.nivio.output.layout; + +import de.bonndan.nivio.assessment.Assessment; +import de.bonndan.nivio.assessment.AssessmentChangedEvent; +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeFactory; +import de.bonndan.nivio.output.Renderer; +import de.bonndan.nivio.output.map.RenderingRepository; +import de.bonndan.nivio.output.map.svg.SVGDocument; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +class LayoutServiceTest { + + private AppearanceProcessor appearanceProcessor; + private Layouter layouter; + private RenderingRepository renderingRepository; + private LayoutService service; + private Renderer renderer; + private ApplicationEventPublisher eventPublisher; + + @BeforeEach + void setUp() { + appearanceProcessor = mock(AppearanceProcessor.class); + layouter = mock(Layouter.class); + renderer = mock(Renderer.class); + renderingRepository = mock(RenderingRepository.class); + eventPublisher = mock(ApplicationEventPublisher.class); + service = new LayoutService(appearanceProcessor, layouter, renderer, renderingRepository, eventPublisher); + } + + @Test + void onApplicationEvent() { + + //given + Landscape landscape = LandscapeFactory.createForTesting("foo", "foo").build(); + Assessment assessment = new Assessment(Map.of()); + AssessmentChangedEvent e = new AssessmentChangedEvent(landscape, assessment); + when(layouter.layout(eq(landscape))).thenReturn(mock(LayoutedComponent.class)); + when(renderer.render(any(LayoutedComponent.class), eq(assessment), eq(false))).thenReturn(mock(SVGDocument.class)); + when(renderer.getRenderingType()).thenReturn(SVGDocument.class.getSimpleName()); + + //when + service.onApplicationEvent(e); + + //then + verify(appearanceProcessor).process(eq(landscape)); + verify(layouter).layout(eq(landscape)); + verify(renderer).render(any(LayoutedComponent.class), eq(assessment), eq(false)); + verify(renderingRepository).save(eq(SVGDocument.class.getSimpleName()), eq(landscape), any(SVGDocument.class), eq(false)); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java b/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java index a6904e0ee..6d8ac716e 100644 --- a/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java +++ b/src/test/java/de/bonndan/nivio/output/layout/OrganicLayouterTest.java @@ -1,29 +1,25 @@ package de.bonndan.nivio.output.layout; import com.fasterxml.jackson.databind.ObjectMapper; -import de.bonndan.nivio.assessment.Assessment; import de.bonndan.nivio.input.FileFetcher; import de.bonndan.nivio.input.Indexer; import de.bonndan.nivio.input.InputFormatHandlerFactory; -import de.bonndan.nivio.input.external.LinkHandlerFactory; import de.bonndan.nivio.input.csv.InputFormatHandlerCSV; import de.bonndan.nivio.input.dto.GroupDescription; import de.bonndan.nivio.input.dto.ItemDescription; import de.bonndan.nivio.input.dto.LandscapeDescription; import de.bonndan.nivio.input.dto.RelationDescription; +import de.bonndan.nivio.input.external.LinkHandlerFactory; import de.bonndan.nivio.input.http.HttpService; -import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.model.LandscapeFactory; import de.bonndan.nivio.output.RenderingTest; +import de.bonndan.nivio.output.icons.ExternalIcons; +import de.bonndan.nivio.output.icons.ExternalIconsProvider; import de.bonndan.nivio.output.icons.IconService; import de.bonndan.nivio.output.icons.LocalIcons; -import de.bonndan.nivio.output.icons.ExternalIcons; -import de.bonndan.nivio.output.map.svg.MapStyleSheetFactory; -import de.bonndan.nivio.output.map.svg.SVGDocument; -import de.bonndan.nivio.output.map.svg.SVGRenderer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.springframework.context.ApplicationEventPublisher; import java.io.IOException; @@ -32,11 +28,9 @@ import java.util.List; import java.util.Map; -import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; class OrganicLayouterTest extends RenderingTest { @@ -55,29 +49,29 @@ private LayoutedComponent debugRender(String path, boolean debugMode) throws IOE } @Test - public void debugRenderExample() throws IOException { + void debugRenderExample() throws IOException { debugRender("/src/test/resources/example/example_env"); } @Test - public void debugRenderInOut() throws IOException { + void debugRenderInOut() throws IOException { debugRender("/src/test/resources/example/inout"); } @Test - public void debugRenderFourGroups() throws IOException { + void debugRenderFourGroups() throws IOException { debugRender("/src/test/resources/example/example_four_groups"); } @Test - public void renderInout() throws IOException { + void renderInout() throws IOException { String path = "/src/test/resources/example/inout"; Landscape landscape = getLandscape(path + ".yml"); debugRenderLandscape(path, landscape); } @Test - public void debugRenderLargeGraph() throws IOException { + void debugRenderLargeGraph() throws IOException { LandscapeDescription input = new LandscapeDescription("largetest", "largetest", null); @@ -107,7 +101,7 @@ public void debugRenderLargeGraph() throws IOException { } @Test - public void debugRenderLargeGraphSVG() throws IOException { + void debugRenderLargeGraphSVG() throws IOException { LandscapeDescription input = new LandscapeDescription("largetest", "largetest", null); @@ -135,7 +129,7 @@ public void debugRenderLargeGraphSVG() throws IOException { for (int i = 0; i < 20; i++) { var source = descriptionList.get(i); var target = descriptionList.get(i + 20); - source.addRelation(new RelationDescription(source.getIdentifier(), target.getIdentifier())); + source.addOrReplaceRelation(new RelationDescription(source.getIdentifier(), target.getIdentifier())); } indexer.index(input); @@ -145,7 +139,7 @@ public void debugRenderLargeGraphSVG() throws IOException { } @Test - public void renderLandscapeItemModelWithMagicLabels() throws IOException { + void renderLandscapeItemModelWithMagicLabels() throws IOException { ObjectMapper mapper = new ObjectMapper(); ItemDescription model = new ItemDescription(); @@ -171,19 +165,19 @@ public void renderLandscapeItemModelWithMagicLabels() throws IOException { } @Test - public void renderCSV() throws IOException { - + void renderCSV() throws IOException { + var externalIconsProvider = Mockito.mock(ExternalIconsProvider.class); HttpService httpService = new HttpService(); - IconService iconService = new IconService(new LocalIcons(), new ExternalIcons(httpService)); + IconService iconService = new IconService(new LocalIcons(), new ExternalIcons(httpService, externalIconsProvider)); formatFactory = new InputFormatHandlerFactory(List.of(new InputFormatHandlerCSV(new FileFetcher(httpService)))); LinkHandlerFactory linkHandlerFactory = mock(LinkHandlerFactory.class); - indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, mock(ApplicationEventPublisher.class), iconService); + indexer = new Indexer(landscapeRepository, formatFactory, linkHandlerFactory, mock(ApplicationEventPublisher.class)); debugRender("/src/test/resources/example/example_csv", false); } @Test - public void shiftGroupsAndItems() { + void shiftGroupsAndItems() { //given String path = "/src/test/resources/example/inout"; diff --git a/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java b/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java index ac6502bd2..7c121099f 100644 --- a/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java +++ b/src/test/java/de/bonndan/nivio/output/layout/SubLayoutTest.java @@ -1,9 +1,6 @@ package de.bonndan.nivio.output.layout; -import de.bonndan.nivio.model.LandscapeConfig; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.*; import org.junit.jupiter.api.Test; import java.util.HashSet; @@ -20,12 +17,13 @@ public void testWithARelation() { //given Group foo = new Group("foo", "landscapeIdentifier"); - Item bar = getTestItem(foo.getIdentifier(), "bar");; - foo.addItem(bar); + Item bar = getTestItem(foo.getIdentifier(), "bar"); + ; + foo.addOrReplaceItem(bar); Item baz = getTestItem(foo.getIdentifier(), "baz"); - foo.addItem(baz); - baz.addOrReplace(new Relation(baz, bar)); + foo.addOrReplaceItem(baz); + baz.addOrReplace(RelationFactory.createForTesting(baz, bar)); HashSet objects = new HashSet<>(); objects.add(bar); diff --git a/src/test/java/de/bonndan/nivio/output/map/RenderCacheTest.java b/src/test/java/de/bonndan/nivio/output/map/RenderCacheTest.java deleted file mode 100644 index 3dafbc583..000000000 --- a/src/test/java/de/bonndan/nivio/output/map/RenderCacheTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package de.bonndan.nivio.output.map; - -import de.bonndan.nivio.assessment.AssessmentRepository; -import de.bonndan.nivio.input.AppearanceProcessor; -import de.bonndan.nivio.input.ProcessLog; -import de.bonndan.nivio.input.ProcessingChangelog; -import de.bonndan.nivio.input.ProcessingFinishedEvent; -import de.bonndan.nivio.input.dto.LandscapeDescription; -import de.bonndan.nivio.model.Group; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.model.LandscapeFactory; -import de.bonndan.nivio.output.icons.IconService; -import de.bonndan.nivio.output.map.svg.MapStyleSheetFactory; -import de.bonndan.nivio.output.map.svg.SVGRenderer; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.Set; - -import static de.bonndan.nivio.model.ItemFactory.getTestItem; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.*; - -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class RenderCacheTest { - - private RenderCache renderCache; - private MapStyleSheetFactory stylesheetFactory; - private SVGRenderer svgRenderer; - - @BeforeEach - public void setup() { - - stylesheetFactory = mock(MapStyleSheetFactory.class); - svgRenderer = new SVGRenderer(stylesheetFactory); - renderCache = new RenderCache(svgRenderer, new AssessmentRepository()); - when(stylesheetFactory.getMapStylesheet(any(), any())).thenReturn(""); - } - - @Test - void toPNGCached() { - Landscape landscape = getLandscape("test", "testLandscape"); - String first = renderCache.getSVG(landscape, false); - String second = renderCache.getSVG(landscape, false); - - verify(stylesheetFactory, times(1)).getMapStylesheet(any(), any()); - } - - @Test - void cachesBasedOnIdentifier() { - Landscape one = getLandscape("first", "one"); - String first = renderCache.getSVG( - getLandscape("first", "testLandscape"), - false - ); - Landscape two = getLandscape("second", "two"); - //two.setProcessLog(one.getLog()); //sync last update - String second = renderCache.getSVG(two, false); - - verify(stylesheetFactory, times(2)) - .getMapStylesheet(any(), any()); - } - - @Test - void toSVG() { - String svg = renderCache.getSVG(getLandscape("test", "testLandscape"), true); - assertNotNull(svg); - assertTrue(svg.contains("svg")); - } - - @Test - void onProcessingFinishedEvent() { - renderCache.onApplicationEvent(new ProcessingFinishedEvent( - new LandscapeDescription("test", "testLandscape", null), - getLandscape("test", "testLandscape"), - new ProcessingChangelog() - )); - - verify(stylesheetFactory, times(1)).getMapStylesheet(any(), any()); - } - - private Landscape getLandscape(String identifier, String name) { - - ProcessLog test = new ProcessLog(LoggerFactory.getLogger("test"), "test"); - test.info("foo"); - - Landscape landscape = LandscapeFactory.createForTesting(identifier, name) - .withProcessLog(test) - .build(); - - Item item = getTestItem("bar", "foo"); - landscape.setItems(Set.of(item)); - landscape.setItems(Collections.singleton(item)); - - Group bar = new Group("bar", identifier); - bar.addItem(item); - landscape.getGroups().put("bar", bar); - - new AppearanceProcessor(landscape.getLog(), mock(IconService.class)).process(null, landscape); - return landscape; - } -} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/RenderingRepositoryTest.java b/src/test/java/de/bonndan/nivio/output/map/RenderingRepositoryTest.java new file mode 100644 index 000000000..85077a2d0 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/map/RenderingRepositoryTest.java @@ -0,0 +1,42 @@ +package de.bonndan.nivio.output.map; + +import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeFactory; +import de.bonndan.nivio.output.map.svg.SVGDocument; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +class RenderingRepositoryTest { + + private Landscape landscape; + private RenderingRepository renderingRepository; + + @BeforeEach + public void setup() { + landscape = LandscapeFactory.createForTesting("foo", "bar").build(); + renderingRepository = new RenderingRepository(); + } + + @Test + void saveAndGet() { + //given + SVGDocument foo = mock(SVGDocument.class); + renderingRepository.save("foo", landscape, foo, false); + + //when + Optional first = renderingRepository.get("foo", landscape, false); + + //then + assertThat(first).isPresent().get().isEqualTo(foo); + } + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/hex/GroupAreaFactoryTest.java b/src/test/java/de/bonndan/nivio/output/map/hex/GroupAreaFactoryTest.java index ca208266c..0a67c8db9 100644 --- a/src/test/java/de/bonndan/nivio/output/map/hex/GroupAreaFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/hex/GroupAreaFactoryTest.java @@ -29,7 +29,7 @@ class GroupAreaFactoryTest { * https://www.redblobgames.com/grids/hexagons/#coordinates */ @Test - public void getBridges() { + void getBridges() { Set inArea = new HashSet<>(); //vertical with one hex gap inArea.add(new Hex(3, 1, -4)); @@ -42,7 +42,7 @@ public void getBridges() { } @Test - public void addHexesWithClosestPaths() { + void addHexesWithClosestPaths() { Hex one = new Hex(1, 2); Hex two = new Hex(3, 5); @@ -50,15 +50,15 @@ public void addHexesWithClosestPaths() { Item target = getTestItem("group", "target"); Group group = new Group("group", "landscapeIdentifier"); - group.addItem(landscapeItem); - group.addItem(target); + group.addOrReplaceItem(landscapeItem); + group.addOrReplaceItem(target); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(one, landscapeItem); hexesToItems.put(two, target); //when - Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); + Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, Set.of(landscapeItem, target)); //then assertThat(inArea).containsAll(expectedTerritory); @@ -70,7 +70,7 @@ public void addHexesWithClosestPaths() { } @Test - public void justAddsHexAndNeighbours() { + void justAddsHexAndNeighbours() { Hex one = new Hex(1, 2); Hex two = new Hex(3, 3); @@ -78,21 +78,21 @@ public void justAddsHexAndNeighbours() { Item target = getTestItem("group", "target"); Group group = new Group("group", "landscapeIdentifier"); - group.addItem(landscapeItem); + group.addOrReplaceItem(landscapeItem); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(one, landscapeItem); hexesToItems.put(two, target); //when - Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); + Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, Set.of(landscapeItem)); //then assertThat(inArea).isEqualTo(expectedTerritory); } @Test - public void doesNotAddUnnecessaryTiles() { + void doesNotAddUnnecessaryTiles() { Hex one = new Hex(4, 4); Hex two = new Hex(6, 4); @@ -101,21 +101,21 @@ public void doesNotAddUnnecessaryTiles() { Item target = getTestItem("group", "target"); Group group = new Group("group", "landscapeIdentifier"); - group.addItem(landscapeItem); + group.addOrReplaceItem(landscapeItem); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(one, landscapeItem); hexesToItems.put(two, target); //when - Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); - assertThat(inArea).doesNotContain(new Hex(5,2)); - assertThat(inArea).doesNotContain(new Hex(6,2)); - assertThat(inArea).doesNotContain(new Hex(7,2)); + Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, Set.of(landscapeItem, target)); + assertThat(inArea).doesNotContain(new Hex(5, 2)); + assertThat(inArea).doesNotContain(new Hex(6, 2)); + assertThat(inArea).doesNotContain(new Hex(7, 2)); } @Test - public void pathToClosestItemIsPaddedByOneHex() { + void pathToClosestItemIsPaddedByOneHex() { Hex one = new Hex(4, 4); Hex two = new Hex(7, 4); @@ -124,23 +124,23 @@ public void pathToClosestItemIsPaddedByOneHex() { Item target = getTestItem("group", "target"); Group group = new Group("group", "landscapeIdentifier"); - group.addItem(landscapeItem); - group.addItem(target); + group.addOrReplaceItem(landscapeItem); + group.addOrReplaceItem(target); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(one, landscapeItem); hexesToItems.put(two, target); //when - Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); + Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, Set.of(landscapeItem, target)); //then - assertThat(inArea).contains(new Hex(6,3)); - assertThat(inArea).contains(new Hex(5,5)); + assertThat(inArea).contains(new Hex(6, 3)); + assertThat(inArea).contains(new Hex(5, 5)); } @Test - public void allAreaHexesHaveCorrectGroup() { + void allAreaHexesHaveCorrectGroup() { Hex one = new Hex(1, 1, -2); Hex two = new Hex(3, 3, -6); @@ -148,14 +148,14 @@ public void allAreaHexesHaveCorrectGroup() { Item target = getTestItem("group", "target"); Group group = new Group("group", "landscapeIdentifier"); - group.addItem(landscapeItem); + group.addOrReplaceItem(landscapeItem); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(one, landscapeItem); hexesToItems.put(two, target); //when - Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); + Set inArea = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, Set.of(landscapeItem, target)); //then long count = inArea.stream().filter(hex -> hex.group != null).count(); diff --git a/src/test/java/de/bonndan/nivio/output/map/hex/HexTest.java b/src/test/java/de/bonndan/nivio/output/map/hex/HexTest.java index 80e10c190..cc6063cc6 100644 --- a/src/test/java/de/bonndan/nivio/output/map/hex/HexTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/hex/HexTest.java @@ -10,7 +10,7 @@ class HexTest { @Test - public void topLeft() { + void topLeft() { Hex center = new Hex(0,0, 0); List area = new ArrayList<>(); area.add(center); @@ -20,9 +20,16 @@ public void topLeft() { Hex hex = Hex.topLeft(area); //then - assertThat(hex).isNotNull(); - assertThat(hex.q).isEqualTo(0); - assertThat(hex.r).isEqualTo(-1); + assertThat(hex).isNotNull().isEqualTo(new Hex(0,-1)); } + @Test + void getNeighboursDirections() { + //given + Hex center = new Hex(4,3); + List neighbours = center.neighbours(); + + //when + assertThat(center.getDirectionTo(neighbours.get(0))).isEqualTo(Hex.SOUTH_EAST); + } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/HexPathTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/HexPathTest.java index a15eebe75..4a76122ee 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/HexPathTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/HexPathTest.java @@ -7,8 +7,8 @@ import java.awt.geom.Point2D; import java.util.List; +import static de.bonndan.nivio.output.map.hex.Hex.*; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; class HexPathTest { @@ -39,13 +39,19 @@ void getPoints() { @Test void getEndPoint() { - assertThat(hexpath.getEndPoint()).isEqualTo(new Point2D.Double(275.0, 762.9165124598851)); + assertThat(hexpath.getEndPoint()).isEqualTo(new Point2D.Double(278.57142857142856, 764.9784777069909)); } @Test void calcBends() { - List bends = HexPath.calcBends(this.hexes); - assertThat(bends).isNotEmpty().hasSize(1); - assertThat(bends).contains(new Hex(0,3)); + hexpath.calcBends(this.hexes); + List bends = hexpath.getBends(); + assertThat(bends).isNotEmpty() + .hasSize(1) + .contains(new Hex(0,3)); + + List directions = hexpath.getDirections(); + assertThat(directions).isNotEmpty().hasSize(3); + assertThat(directions).isEqualTo(List.of(SOUTH, SOUTH, SOUTH_EAST)); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGBackgroundFactoryTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGBackgroundFactoryTest.java index 3ee134fc7..ecc6f9db9 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGBackgroundFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGBackgroundFactoryTest.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.output.map.svg; import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Group; import de.bonndan.nivio.output.map.hex.Hex; import j2html.tags.ContainerTag; @@ -27,7 +26,7 @@ void getBackgroundTiles() { Group g = new Group("a", "landscapeIdentifier"); Set hexes = Set.of(new Hex(-3, -3), new Hex(10, 10)); - SVGGroupArea svgGroupArea = new SVGGroupArea(g, hexes, List.of(), new StatusValue("foo", Status.GREEN)); + SVGGroupArea svgGroupArea = new SVGGroupArea(g, hexes, List.of(), Status.GREEN); SVGDimension dimension = SVGDimensionFactory.getDimension(List.of(svgGroupArea), List.of()); List backgroundTiles = SVGBackgroundFactory.getBackgroundTiles(dimension); diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java index 85e50ee50..a1b6dd9b7 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGDimensionFactoryTest.java @@ -1,10 +1,9 @@ package de.bonndan.nivio.output.map.svg; import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Group; import de.bonndan.nivio.model.ItemFactory; -import de.bonndan.nivio.model.Relation; +import de.bonndan.nivio.model.RelationFactory; import de.bonndan.nivio.output.map.hex.Hex; import org.junit.jupiter.api.Test; @@ -23,7 +22,7 @@ void boundingBoxes() { Hex one = new Hex(-3, -3); Hex two = new Hex(10, 10); Set hexes = Set.of(one, two); //usually would be much more, but here it is sufficient - SVGGroupArea svgGroupArea = new SVGGroupArea(g, hexes, List.of(), new StatusValue("foo", Status.GREEN)); + SVGGroupArea svgGroupArea = new SVGGroupArea(g, hexes, List.of(), Status.GREEN); //when SVGDimension dimension = SVGDimensionFactory.getDimension(List.of(svgGroupArea), List.of()); @@ -53,11 +52,11 @@ void boundingBoxesWithRelations() { Hex one = new Hex(-3, -3); Hex two = new Hex(10, 10); Set hexes = Set.of(one, two); //usually would be much more, but here it is sufficient - SVGGroupArea svgGroupArea = new SVGGroupArea(g, hexes, List.of(), new StatusValue("foo", Status.GREEN)); + SVGGroupArea svgGroupArea = new SVGGroupArea(g, hexes, List.of(), Status.GREEN); //when Hex three = new Hex(-10, -10); - SVGRelation svgRelation = new SVGRelation(new HexPath(List.of(three)), "aaccee", new Relation(ItemFactory.getTestItem("foo", "bar"), ItemFactory.getTestItem("foo", "baz")), null); + SVGRelation svgRelation = new SVGRelation(new HexPath(List.of(three)), "aaccee", RelationFactory.createForTesting(ItemFactory.getTestItem("foo", "bar"), ItemFactory.getTestItem("foo", "baz")), null); SVGDimension dimension = SVGDimensionFactory.getDimension(List.of(svgGroupArea), List.of(svgRelation)); //then diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGDocumentTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGDocumentTest.java index 5c25ad647..03742c7e9 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGDocumentTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGDocumentTest.java @@ -1,15 +1,25 @@ package de.bonndan.nivio.output.map.svg; +import de.bonndan.nivio.assessment.Assessment; import de.bonndan.nivio.input.http.CachedResponse; import de.bonndan.nivio.model.Landscape; import de.bonndan.nivio.output.RenderingTest; +import de.bonndan.nivio.output.layout.LayoutedComponent; +import j2html.tags.DomContent; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.stubbing.OngoingStubbing; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.StringUtils; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import static org.assertj.core.api.Assertions.as; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -18,26 +28,27 @@ class SVGDocumentTest extends RenderingTest { - @BeforeEach + @BeforeEach public void setup() throws URISyntaxException { super.setup(); - } + } @Test - public void renderInout() throws IOException { + void renderInout() throws IOException { String path = "/src/test/resources/example/inout"; Landscape landscape = getLandscape(path + ".yml"); String svg = renderLandscape(path, landscape); assertTrue(svg.contains("svg version=\"1.1\"")); assertTrue(svg.contains("class=\"title\">Input and Output")); + assertTrue(svg.contains("class=\"logo\"")); assertThat(svg).contains("Docker Compose files")); } @Test - public void renderCustomFill() throws IOException { - String path = "/src/test/resources/example/dedica"; + void renderCustomFill() throws IOException { + String path = "/src/test/resources/example/dedica"; Landscape landscape = getLandscape(path + ".yml"); //when @@ -52,7 +63,7 @@ public void renderCustomFill() throws IOException { } @Test - public void embedsExternalImages() throws IOException, URISyntaxException { + void embedsExternalImages() throws IOException, URISyntaxException { String path = "/src/test/resources/example/dedica"; CachedResponse response = mock(CachedResponse.class); when(response.getBytes()).thenReturn("foo".getBytes()); @@ -64,10 +75,12 @@ public void embedsExternalImages() throws IOException, URISyntaxException { String svg = renderLandscape(path, landscape); //then - assertThat(svg).doesNotContain("https://dedica.team/images/logo_orange_weiss.png"); //external image, to be replaced - assertThat(svg).doesNotContain("https://dedica.team/images/logo.png"); //map logo - assertThat(svg).doesNotContain("danielpozzi.jpg"); //external image, to be replaced - assertThat(svg).contains("fill=\"url(#Wm05dg==)\""); //pattern for "foo" response + assertThat(svg) + .doesNotContain("https://dedica.team/images/logo_orange_weiss.png") //external image, to be replaced + .doesNotContain("https://dedica.team/images/logo.png") //map logo + .doesNotContain("danielpozzi.jpg") //external image, to be replaced + .contains("fill=\"url(#Wm05dg==)\""); //pattern for "foo" response } + } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactoryTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactoryTest.java index c5614bc5d..6a46aa1d1 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaOutlineFactoryTest.java @@ -1,7 +1,6 @@ package de.bonndan.nivio.output.map.svg; import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.assessment.StatusValue; import de.bonndan.nivio.model.Group; import de.bonndan.nivio.model.Item; import de.bonndan.nivio.output.map.hex.GroupAreaFactory; @@ -12,35 +11,36 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.*; +import java.util.List; +import java.util.Set; import static de.bonndan.nivio.model.ItemFactory.getTestItem; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; class SVGGroupAreaOutlineFactoryTest { @Test @DisplayName("Ensure that items far apart have one outline") - public void twoSeparateHexe() { + void twoSeparateHexes() { Hex e1 = new Hex(0, 10, -10); Hex e2 = new Hex(0, 20, -20); - Set occupied = Set.of(e1, e2); Item item1 = getTestItem("foo", "bar"); Item item2 = getTestItem("foo", "baz"); - Group foo = new Group("foo", "landscapeIdentifier", null, null, null, null, "005500"); - foo.addItem(item1); - foo.addItem(item2); + Group foo = new Group("foo", "landscapeIdentifier", null, null, null, "005500"); + foo.addOrReplaceItem(item1); + foo.addOrReplaceItem(item2); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(e1, item1); hexesToItems.put(e2, item2); - Set area = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), foo); + Set area = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), foo, Set.of(item1, item2)); - SVGGroupArea group = SVGGroupArea.forGroup(foo, area, new StatusValue("foo", Status.GREEN), false); + SVGGroupArea group = SVGGroupArea.forGroup(foo, area, Status.GREEN, false); Set groupArea = group.getGroupArea(); //when diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaTest.java index 9849a0fb8..1e3468f0a 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGGroupAreaTest.java @@ -1,15 +1,15 @@ package de.bonndan.nivio.output.map.svg; import de.bonndan.nivio.assessment.Status; -import de.bonndan.nivio.assessment.StatusValue; -import de.bonndan.nivio.model.*; +import de.bonndan.nivio.model.Group; +import de.bonndan.nivio.model.Item; import de.bonndan.nivio.output.map.hex.GroupAreaFactory; import de.bonndan.nivio.output.map.hex.Hex; import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; import org.junit.jupiter.api.Test; -import java.util.*; +import java.util.Set; import static de.bonndan.nivio.model.ItemFactory.getTestItem; import static de.bonndan.nivio.output.map.svg.SVGDocument.DATA_IDENTIFIER; @@ -19,7 +19,7 @@ class SVGGroupAreaTest { @Test - public void hasFQI() { + void hasFQI() { Hex e1 = new Hex(1, 1, -2); Hex e2 = new Hex(3, 3, -6); @@ -27,21 +27,21 @@ public void hasFQI() { Item landscapeItem2 = getTestItem("group", "bar"); Group group = new Group("group", "foo"); - group.addItem(landscapeItem); - group.addItem(landscapeItem2); + group.addOrReplaceItem(landscapeItem); + group.addOrReplaceItem(landscapeItem2); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(e1, landscapeItem); hexesToItems.put(e2, landscapeItem2); - Set area = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); - SVGGroupArea svgGroupArea = SVGGroupArea.forGroup(group, area, new StatusValue("foo", Status.GREEN), false); + Set area = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, Set.of(landscapeItem, landscapeItem2)); + SVGGroupArea svgGroupArea = SVGGroupArea.forGroup(group, area, Status.GREEN, false); assertThat(svgGroupArea.render().render()).contains(group.getFullyQualifiedIdentifier().jsonValue()); } @Test - public void supportsVisualFocus() { + void supportsVisualFocus() { Hex e1 = new Hex(1, 1, -2); Hex e2 = new Hex(3, 3, -6); @@ -49,15 +49,15 @@ public void supportsVisualFocus() { Item landscapeItem2 = getTestItem("group", "bar"); Group group = new Group("group", "foo"); - group.addItem(landscapeItem); - group.addItem(landscapeItem2); + group.addOrReplaceItem(landscapeItem); + group.addOrReplaceItem(landscapeItem2); BidiMap hexesToItems = new DualHashBidiMap<>(); hexesToItems.put(e1, landscapeItem); hexesToItems.put(e2, landscapeItem2); - Set area = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group); - SVGGroupArea svgGroupArea = SVGGroupArea.forGroup(group, area, new StatusValue("foo", Status.GREEN), false); + Set area = GroupAreaFactory.getGroup(hexesToItems.inverseBidiMap(), group, Set.of(landscapeItem, landscapeItem2)); + SVGGroupArea svgGroupArea = SVGGroupArea.forGroup(group, area, Status.GREEN, false); //then String render1 = svgGroupArea.render().render(); diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGItemTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGItemTest.java index bbd4f9369..f9fdd673e 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGItemTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGItemTest.java @@ -2,10 +2,11 @@ import de.bonndan.nivio.model.Group; import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.LandscapeFactory; import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeFactory; import de.bonndan.nivio.output.layout.LayoutedComponent; import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,18 +16,23 @@ import static de.bonndan.nivio.output.map.svg.SVGDocument.DATA_IDENTIFIER; import static de.bonndan.nivio.output.map.svg.SVGDocument.VISUAL_FOCUS_UNSELECTED; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; class SVGItemTest { - @Test - @DisplayName("ensure item uses proper fqi as id") - public void regression184() { - Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); + private Item foo; + @BeforeEach + void setup() { + Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); // item has no group - Item foo = new Item("foo", landscape, Group.COMMON, null, null, null, - null, null, null, null); + foo = new Item("foo", landscape, Group.COMMON, null, null, null, + null, null, null, null, null); + } + + @Test + @DisplayName("ensure item uses proper fqi as id") + void regression184() { SVGItem svgItem = new SVGItem(null, new LayoutedComponent(foo), List.of(), new Point2D.Double(1, 1)); assertThat(svgItem.render().render()).contains("l1/common/foo"); @@ -34,31 +40,22 @@ public void regression184() { @Test @DisplayName("contains x and y data") - public void xyData() { - Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); - - // item has no group - Item foo = new Item("foo", landscape, "null", null, null, null, - null, null, null, null); + void xyData() { + SVGItem svgItem = new SVGItem(null, new LayoutedComponent(foo), List.of(), new Point2D.Double(1, 2.0303030)); - SVGItem svgItem = new SVGItem(null, new LayoutedComponent(foo), List.of(), new Point2D.Double(1, 2.0303030)); assertTrue(svgItem.render().render().contains("data-x=\"1.00\"")); assertTrue(svgItem.render().render().contains("data-y=\"2.03\"")); } @Test - public void supportsVisualFocus() { - Landscape landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); - - // item has no group - Item foo = new Item("foo", landscape, "null", null, null, null, - null, null, null, null); + void supportsVisualFocus() { - SVGItem svgItem = new SVGItem(null, new LayoutedComponent(foo), List.of(), new Point2D.Double(1, 2.0303030)); + SVGItem svgItem = new SVGItem(null, new LayoutedComponent(foo), List.of(), new Point2D.Double(1, 2.0303030)); //then String render1 = svgItem.render().render(); - Assertions.assertThat(render1).contains(DATA_IDENTIFIER); - Assertions.assertThat(render1).contains(VISUAL_FOCUS_UNSELECTED); + Assertions.assertThat(render1) + .contains(DATA_IDENTIFIER) + .contains(VISUAL_FOCUS_UNSELECTED); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java index cd21a7409..033588882 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRelationTest.java @@ -30,18 +30,18 @@ class SVGRelationTest { @BeforeEach void setup() { - landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); - foo = getTestItem(Group.COMMON, "foo", landscape); - bar = getTestItem(Group.COMMON, "bar", landscape); - hexpath = new HexPath(List.of(new Hex(1,2), new Hex(1,3))); - statusValue = new StatusValue("foo", Status.GREEN); + landscape = LandscapeFactory.createForTesting("l1", "l1Landscape").build(); + foo = getTestItem(Group.COMMON, "foo", landscape); + bar = getTestItem(Group.COMMON, "bar", landscape); + hexpath = new HexPath(List.of(new Hex(1, 2), new Hex(1, 3))); + statusValue = new StatusValue("foo", "bar", Status.GREEN, ""); } @Test @DisplayName("items without groups use proper fqi") - public void relationContainsBothEnds() { + void relationContainsBothEnds() { - Relation itemRelationItem = new Relation(foo, bar); + Relation itemRelationItem = RelationFactory.createForTesting(foo, bar); SVGRelation svgRelation = new SVGRelation(hexpath, "aabbee", itemRelationItem, statusValue); DomContent render = svgRelation.render(); String render1 = render.render(); @@ -52,7 +52,7 @@ public void relationContainsBothEnds() { } @Test - public void providerRelationsContainsEndpoint() { + void providerRelationsContainsEndpoint() { Relation itemRelationItem = new Relation(foo, bar, "test", "test", RelationType.PROVIDER); @@ -67,7 +67,7 @@ public void providerRelationsContainsEndpoint() { @Disabled // dataflow has no endpoint marker anymore/yet @Test - public void dataflowRelationsContainsEndpoint() { + void dataflowRelationsContainsEndpoint() { //given Relation relation = new Relation(foo, bar, "test", "test", RelationType.DATAFLOW); @@ -82,7 +82,7 @@ public void dataflowRelationsContainsEndpoint() { } @Test - public void relationIsNotDashedWhenNotPlanned() { + void relationIsNotDashedWhenNotPlanned() { //only works with provider relations, because dataflow inner path is dashed Relation itemRelationItem = new Relation(foo, bar, "test", "test", RelationType.PROVIDER); @@ -97,7 +97,7 @@ public void relationIsNotDashedWhenNotPlanned() { } @Test - public void dataflowRelationIsDashed() { + void dataflowRelationIsDashed() { Relation itemRelationItem = new Relation(foo, bar, "test", "test", RelationType.DATAFLOW); @@ -111,7 +111,7 @@ public void dataflowRelationIsDashed() { } @Test - public void supportsVisualFocus() { + void supportsVisualFocus() { Relation itemRelationItem = new Relation(foo, bar, "test", "test", RelationType.DATAFLOW); SVGRelation svgRelation = new SVGRelation(hexpath, "aabbee", itemRelationItem, statusValue); @@ -125,13 +125,28 @@ public void supportsVisualFocus() { assertThat(render1).contains(VISUAL_FOCUS_UNSELECTED); } + @Test + void weightDeterminesStrokeWidth() { + + Relation itemRelationItem = new Relation(foo, bar, "test", "test", RelationType.PROVIDER); + itemRelationItem.setLabel(Label.weight, "2.44"); + + //when + SVGRelation svgRelation = new SVGRelation(hexpath, "aabbee", itemRelationItem, statusValue); + DomContent render = svgRelation.render(); + + //then + String render1 = render.render(); + var width = Math.round(5 * 2.44f); + assertThat(render1).contains("stroke-width=\"" + width + "\""); + } + @Test @DisplayName("The dataflow marker is not null") - public void marker() { + void marker() { ContainerTag containerTag = SVGRelation.dataflowMarker(); assertThat(containerTag).isNotNull(); assertThat(containerTag.getTagName()).isEqualTo("marker"); - } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRendererTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRendererTest.java index da77719b2..944dd6c05 100644 --- a/src/test/java/de/bonndan/nivio/output/map/svg/SVGRendererTest.java +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SVGRendererTest.java @@ -29,10 +29,10 @@ void testRendering() { LayoutedComponent lc = getLayoutedLandscape(foo); //when - SVGDocument render = svgRenderer.render(lc, new Assessment(foo.applyKPIs(foo.getKpis())),true); + String rendered = svgRenderer.render(lc, new Assessment(foo.applyKPIs(foo.getKpis())),true); //check svg xml is returned - assertTrue(render.getXML().contains("svg version=\"1.1\"")); + assertTrue(rendered.contains("svg version=\"1.1\"")); } private LayoutedComponent getLayoutedLandscape(Landscape foo) { diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SvgRelationEndMarkerTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SvgRelationEndMarkerTest.java new file mode 100644 index 000000000..1f718cf79 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SvgRelationEndMarkerTest.java @@ -0,0 +1,58 @@ +package de.bonndan.nivio.output.map.svg; + +import de.bonndan.nivio.model.RelationType; +import org.junit.jupiter.api.Test; + +import java.awt.geom.Point2D; + +import static de.bonndan.nivio.output.map.hex.Hex.*; +import static org.assertj.core.api.Assertions.assertThat; + +class SvgRelationEndMarkerTest { + + @Test + void provider() { + SvgRelationEndMarker red = new SvgRelationEndMarker(new Point2D.Double(0, 0), RelationType.PROVIDER, "red", NORTH); + + String render = red.render().render(); + + assertThat(render).isEqualTo(""); + } + + @Test + void markerHasColor() { + SvgRelationEndMarker red = new SvgRelationEndMarker(new Point2D.Double(0, 0), RelationType.DATAFLOW, "red", NORTH); + + String render = red.render().render(); + + assertThat(render).contains("fill=\"red\""); + } + + @Test + void dataflowMarkerPointsUp() { + SvgRelationEndMarker red = new SvgRelationEndMarker(new Point2D.Double(0, 0), RelationType.DATAFLOW, "red", NORTH); + + String render = red.render().render(); + + assertThat(render).contains("rotate(0 "); + } + + @Test + void dataflowMarkerPointsSE() { + SvgRelationEndMarker red = new SvgRelationEndMarker(new Point2D.Double(0, 0), RelationType.DATAFLOW, "red", SOUTH_EAST); + + String render = red.render().render(); + + assertThat(render).contains("rotate(-240 "); + } + + @Test + void markerSetOutward() { + SvgRelationEndMarker red = new SvgRelationEndMarker(new Point2D.Double(0, 0), RelationType.DATAFLOW, "red", SOUTH); + + String render = red.render().render(); + + assertThat(render).contains("translate(-25.0 -50.0) "); + } + +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/output/map/svg/SvgRelationLabelTest.java b/src/test/java/de/bonndan/nivio/output/map/svg/SvgRelationLabelTest.java new file mode 100644 index 000000000..0a7187208 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/output/map/svg/SvgRelationLabelTest.java @@ -0,0 +1,29 @@ +package de.bonndan.nivio.output.map.svg; + +import org.junit.jupiter.api.Test; + +import java.awt.geom.Point2D; + +import static org.assertj.core.api.Assertions.assertThat; + +class SvgRelationLabelTest { + + @Test + void render() { + SvgRelationLabel svgRelationLabel = new SvgRelationLabel("foo", + new Point2D.Float(10f, 10f), + new Point2D.Float(20f, 20f), + "red", + true + ); + + assertThat(svgRelationLabel).isNotNull(); + + String render = svgRelationLabel.render().render(); + assertThat(render) + .contains("text-anchor=\"middle\"") + .contains("transform=\"translate(10.0 0.0) rotate(45.0 0 0)\"") + .contains("foo") + .contains("fill=\"red\""); + } +} \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/search/ItemIndexTest.java b/src/test/java/de/bonndan/nivio/search/ItemIndexTest.java index 45a5d84ad..b19dc412b 100644 --- a/src/test/java/de/bonndan/nivio/search/ItemIndexTest.java +++ b/src/test/java/de/bonndan/nivio/search/ItemIndexTest.java @@ -2,11 +2,7 @@ import de.bonndan.nivio.assessment.Assessment; import de.bonndan.nivio.input.dto.ItemDescription; -import de.bonndan.nivio.model.FullyQualifiedIdentifier; -import de.bonndan.nivio.model.Item; -import de.bonndan.nivio.model.Landscape; -import de.bonndan.nivio.model.LandscapeFactory; -import de.bonndan.nivio.util.URLHelper; +import de.bonndan.nivio.model.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -17,12 +13,16 @@ import static de.bonndan.nivio.model.ItemFactory.getTestItem; import static de.bonndan.nivio.model.ItemFactory.getTestItemBuilder; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; class ItemIndexTest { private ArrayList items; private Landscape landscape; + private Item s1; + private Item s2; + private Item s3; @BeforeEach public void setup() throws URISyntaxException { @@ -31,20 +31,20 @@ public void setup() throws URISyntaxException { items = new ArrayList<>(); - Item s1 = getTestItemBuilder("g1", "s1").withName("foo").withLandscape(landscape).build(); + s1 = getTestItemBuilder("g1", "s1").withName("foo").withLandscape(landscape).build(); items.add(s1); - Item s2 = getTestItemBuilder("g1", "s2").withName("bar").withLandscape(landscape).build(); + s2 = getTestItemBuilder("g1", "s2").withName("bar").withLandscape(landscape).build(); items.add(s2); - Item s3 = getTestItemBuilder("g2", "hasaddress").withAddress(new URI("https://foo.bar/")).withLandscape(landscape).build(); + s3 = getTestItemBuilder("g2", "hasaddress").withAddress(new URI("https://foo.bar/")).withLandscape(landscape).build(); items.add(s3); landscape.setItems(new HashSet<>(items)); } @Test - public void pickFails() { + void pickFails() { assertThrows(RuntimeException.class, () -> landscape.getItems().pick("s1", "xxx")); assertThrows(RuntimeException.class, () -> landscape.getItems().pick("s3", "g1")); @@ -52,7 +52,7 @@ public void pickFails() { @Test - public void pick() { + void pick() { assertNotNull(landscape.getItems().pick("s1", "g1")); assertNotNull(landscape.getItems().pick("s2", "g1")); @@ -62,13 +62,13 @@ public void pick() { } @Test - public void pickGracefulWithoutGroup() { + void pickGracefulWithoutGroup() { assertNotNull(landscape.getItems().pick("s2", null)); } @Test - public void pickGracefulFails() { + void pickGracefulFails() { Item s2 = getTestItem("g2", "s2", landscape); items.add(s2); @@ -78,7 +78,7 @@ public void pickGracefulFails() { } @Test - public void queryUrl() { + void queryUrl() { //given landscape.getSearchIndex().indexForSearch(landscape, new Assessment(Map.of())); @@ -92,7 +92,7 @@ public void queryUrl() { } @Test - public void retrieve() { + void retrieve() { //given landscape.getSearchIndex().indexForSearch(landscape, new Assessment(Map.of())); @@ -106,4 +106,41 @@ public void retrieve() { assertThat(search).contains(items.get(0)); assertThat(search).contains(items.get(1)); } + + @Test + void retrieveThrowsNoSuchElement() { + //given + landscape.getSearchIndex().indexForSearch(landscape, new Assessment(Map.of())); + + //when + Set q = Set.of(ItemFactory.getTestItem("foo", "bar").getFullyQualifiedIdentifier()); + + //then + assertThrows(NoSuchElementException.class, () -> landscape.getItems().retrieve(q)); + } + + @Test + void retrieveKeepsOrder() { + //given + landscape.getSearchIndex().indexForSearch(landscape, new Assessment(Map.of())); + + //when + Set q = Set.of(s1.getFullyQualifiedIdentifier(), s2.getFullyQualifiedIdentifier()); + Collection search = landscape.getItems().retrieve(q); + + //then + assertThat(search).isNotEmpty() + .hasSize(2) + .containsExactlyInAnyOrder(s1, s2); + + + //when + q = Set.of(s2.getFullyQualifiedIdentifier(), s1.getFullyQualifiedIdentifier()); + search = landscape.getItems().retrieve(q); + + //then + assertThat(search).isNotEmpty() + .hasSize(2) + .containsExactlyInAnyOrder(s2, s1); + } } diff --git a/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java b/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java index 838d15ffc..8f2c2d3a5 100644 --- a/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java +++ b/src/test/java/de/bonndan/nivio/search/SearchDocumentFactoryTest.java @@ -20,7 +20,6 @@ import static de.bonndan.nivio.model.ItemFactory.getTestItemBuilder; import static de.bonndan.nivio.search.SearchDocumentFactory.*; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.in; import static org.junit.jupiter.api.Assertions.*; class SearchDocumentFactoryTest { @@ -34,12 +33,12 @@ void setup() throws MalformedURLException { .withDescription("Lorem ipsum") .withContact("info@acme.com") .withOwner("Marketing") + .withType("app") .build(); item.setLabel("foo", "bar"); item.setLabel("foo2", "bar2"); item.setLabel(Label.network + ".foonet", "foonet"); item.setLabel(Label.network + ".barnet", "barnet"); - item.setLabel(Label.type, "app"); item.setLink("wiki", new URL("http://foo.bar.baz")); item.setTags(new String[]{"one", "two"}); item.setLabel(Label.framework.withPrefix("java"), "8"); @@ -47,7 +46,7 @@ void setup() throws MalformedURLException { } @Test - public void generatesDocument() { + void generatesDocument() { //given @@ -64,7 +63,7 @@ public void generatesDocument() { assertEquals(item.getLabel("foo"), document.get("foo")); assertEquals(item.getLabel("foo2"), document.get("foo2")); - assertEquals(item.getLabel(Label.type), document.get("type")); + assertEquals(item.getType(), document.get("type")); assertEquals(item.getLinks().get("wiki").getHref().toString(), document.get("wiki")); String[] tag = document.getValues("tag"); @@ -78,24 +77,28 @@ public void generatesDocument() { assertTrue(networks.contains("barnet")); List frameworksValue = Arrays.asList(document.getValues(LUCENE_FIELD_FRAMEWORK)); - assertThat(frameworksValue).contains("java"); - assertThat(frameworksValue).contains("spring boot"); + assertThat(frameworksValue).contains("java").contains("spring boot"); //per-framework field List frameworks = document.getFields().stream().map(indexableField -> indexableField.name()).collect(Collectors.toList()); assertThat(frameworks).contains("java"); String javaVersion = Arrays.stream(document.getValues("java")).findFirst().orElseThrow(); assertThat(javaVersion).isEqualTo("8"); + + String genericField = document.get(LUCENE_FIELD_GENERIC); + assertThat(genericField).contains("java").contains("spring").contains("boot"); + assertThat(genericField).contains("bar2"); //label + assertThat(genericField).doesNotContain("2.0.1"); //not framework version/value } @Test - public void addsKPIFacets() { + void addsKPIFacets() { //given List statusValues = new ArrayList<>(); - StatusValue foo = new StatusValue("foo", Status.RED, "xyz"); + StatusValue foo = new StatusValue("test", "foo", Status.RED, "xyz"); statusValues.add(foo); - StatusValue bar = new StatusValue("bar", Status.GREEN, "bar"); + StatusValue bar = new StatusValue("test", "bar", Status.GREEN, "bar"); statusValues.add(bar); - StatusValue summary = new StatusValue(StatusValue.SUMMARY_LABEL + ".foo", Status.RED, ""); + StatusValue summary = StatusValue.summary("test", List.of(foo, bar)); statusValues.add(summary); //when @@ -111,7 +114,7 @@ public void addsKPIFacets() { assertThat(barFacet).isNotNull(); assertThat(barFacet.path[0]).isEqualTo("GREEN"); - FacetField summaryFacet = getField(KPI_FACET_PREFIX + StatusValue.SUMMARY_LABEL, document.getFields()); + FacetField summaryFacet = getField(KPI_FACET_PREFIX + StatusValue.SUMMARY_FIELD_VALUE, document.getFields()); assertThat(summaryFacet).isNotNull(); assertThat(summaryFacet.path[0]).isEqualTo("RED"); } diff --git a/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java b/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java index a57a9d336..97c117acb 100644 --- a/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java +++ b/src/test/java/de/bonndan/nivio/search/SearchIndexingEventListenerTest.java @@ -1,41 +1,38 @@ package de.bonndan.nivio.search; import de.bonndan.nivio.assessment.Assessment; +import de.bonndan.nivio.assessment.AssessmentChangedEvent; import de.bonndan.nivio.assessment.AssessmentFactory; -import de.bonndan.nivio.assessment.AssessmentRepository; import de.bonndan.nivio.input.ProcessingChangelog; import de.bonndan.nivio.input.ProcessingFinishedEvent; import de.bonndan.nivio.input.dto.LandscapeDescription; +import de.bonndan.nivio.model.FullyQualifiedIdentifier; import de.bonndan.nivio.model.Item; import de.bonndan.nivio.model.Landscape; +import de.bonndan.nivio.model.LandscapeFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import java.util.Map; -import java.util.Optional; import static org.mockito.Mockito.*; class SearchIndexingEventListenerTest { - private AssessmentRepository assessmentRepository; private Landscape landscape; private SearchIndexingEventListener listener; @BeforeEach void setUp() { - assessmentRepository = mock(AssessmentRepository.class); landscape = mock(Landscape.class); - listener = new SearchIndexingEventListener(assessmentRepository); + when(landscape.getFullyQualifiedIdentifier()).thenReturn(FullyQualifiedIdentifier.from("foo")); + listener = new SearchIndexingEventListener(); } @Test - void onProcessingFinishedEvent() { + void onAssessmentChangedEvent() { //given - var assessment = AssessmentFactory.createAssessment(landscape); - when(assessmentRepository.createAssessment(eq(landscape))).thenReturn(assessment); - ProcessingFinishedEvent e = new ProcessingFinishedEvent(new LandscapeDescription("foo"), landscape, new ProcessingChangelog()); + AssessmentChangedEvent e = new AssessmentChangedEvent(landscape, Assessment.empty()); SearchIndex searchIndex = mock(SearchIndex.class); when(landscape.getSearchIndex()).thenReturn(searchIndex); ItemIndex itemIndex = mock(ItemIndex.class); @@ -47,32 +44,6 @@ void onProcessingFinishedEvent() { //then verify(landscape).getSearchIndex(); - verify(landscape).getKpis(); - verify(landscape).applyKPIs(any()); - verify(assessmentRepository).createAssessment(eq(landscape)); - verify(searchIndex).indexForSearch(eq(landscape), any(Assessment.class)); - } - - @Test - void onProcessingFinishedEventAssessmentRepoNull() { - //given - var assessment = AssessmentFactory.createAssessment(landscape); - when(assessmentRepository.getAssessment(Mockito.any())).thenReturn(Optional.empty()); - when(assessmentRepository.createAssessment(Mockito.any())).thenReturn(assessment); - ProcessingFinishedEvent e = new ProcessingFinishedEvent(new LandscapeDescription("foo"), landscape, new ProcessingChangelog()); - SearchIndex searchIndex = mock(SearchIndex.class); - when(landscape.getSearchIndex()).thenReturn(searchIndex); - ItemIndex itemIndex = mock(ItemIndex.class); - when(landscape.getItems()).thenReturn(itemIndex); - when(landscape.getKpis()).thenReturn(Map.of()); - - //when - listener.onProcessingFinishedEvent(e); - - //then - verify(landscape).getSearchIndex(); - verify(landscape).getKpis(); - verify(landscape).applyKPIs(any()); verify(searchIndex).indexForSearch(eq(landscape), any(Assessment.class)); } } \ No newline at end of file diff --git a/src/test/java/de/bonndan/nivio/util/FrontendMappingTest.java b/src/test/java/de/bonndan/nivio/util/FrontendMappingTest.java new file mode 100644 index 000000000..14d421912 --- /dev/null +++ b/src/test/java/de/bonndan/nivio/util/FrontendMappingTest.java @@ -0,0 +1,53 @@ +package de.bonndan.nivio.util; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +class FrontendMappingTest { + + @Autowired + FrontendMapping frontendMapping; + + @Test + @Order(1) + void getKeys() { + var testMap = Map.of("shortname", "short name", "END_OF_LIFE", "end of life"); + assertThat(frontendMapping.getKeys()).isEqualTo(testMap); + } + + @Test + @Order(2) + void setKeys() { + var testMap = Map.of("testKey", "testValue"); + frontendMapping.setKeys(testMap); + assertThat(frontendMapping.getKeys()).isEqualTo(testMap); + } + + @Test + @Order(3) + void getDescription() { + var testMap = Map.of("END_OF_LIFE", "An end-of-life product is a product at the end of the product lifecycle which prevents users from receiving updates, indicating that the product is at the end of its useful life."); + assertThat(frontendMapping.getDescriptions()).isEqualTo(testMap); + } + + @Test + @Order(4) + void setDescription() { + var testMap = Map.of("testKey", "testValue"); + frontendMapping.setDescriptions(testMap); + assertThat(frontendMapping.getDescriptions()).isEqualTo(testMap); + } +} \ No newline at end of file diff --git a/src/test/resources/example/dedica.dot b/src/test/resources/example/dedica.dot index 3168b6a94..a272ddf67 100644 --- a/src/test/resources/example/dedica.dot +++ b/src/test/resources/example/dedica.dot @@ -43,6 +43,20 @@ digraph G { nivio_fill= "http://dedica.team/images/marvinschoening.jpeg" ] + daniel2 [ + nivio_name = "Daniel Brünker", + nivio_contact= "daniel.bruenker@dedica.team", + nivio_group= dedica + nivio_fill= "http://dedica.team/images/danielbruenker.jpeg" + ] + + jennifer [ + nivio_name = "Jennifer Arps", + nivio_contact= "jennifer@dedica.team", + nivio_group= dedica + nivio_fill= "http://dedica.team/images/jenniferarps.jpeg" + ] + dedica -> matthias [nivio_type = provider] dedica -> daniel [nivio_type = provider] dedica -> jan [nivio_type = provider] diff --git a/src/test/resources/example/dedica.yml b/src/test/resources/example/dedica.yml index c24b766d4..c3d135298 100644 --- a/src/test/resources/example/dedica.yml +++ b/src/test/resources/example/dedica.yml @@ -5,11 +5,11 @@ identifier: dedica.team name: The dedica Consulting Team contact: info@dedica.team description: The IT consulting team. +icon: https://dedica.team/images/logo.png config: branding: mapStylesheet: http://localhost:8080/css/dedica_map.css - mapLogo: https://dedica.team/images/logo.png groups: dedica: @@ -58,5 +58,19 @@ items: name: Marvin Schöning group: dedica fill: http://dedica.team/images/marvinschoening.jpeg + providedBy: + - dedica + + - identifier: daniel2 + name: Daniel Brünker + group: dedica + fill: http://dedica.team/images/danielbruenker.jpeg + providedBy: + - dedica + + - identifier: jennifer + name: Jennifer Arps + group: dedica + fill: http://dedica.team/images/jenniferarps.jpeg providedBy: - dedica \ No newline at end of file diff --git a/src/test/resources/example/dedica_dot.yml b/src/test/resources/example/dedica_dot.yml index f43858d5d..34d94f624 100644 --- a/src/test/resources/example/dedica_dot.yml +++ b/src/test/resources/example/dedica_dot.yml @@ -2,6 +2,8 @@ identifier: dedica.team name: The dedica Consulting Team contact: info@dedica.team description: The IT consulting team. +icon: https://dedica.team/images/logo_orange_weiss.png + config: branding: diff --git a/src/test/resources/example/example_k8s.yml b/src/test/resources/example/example_k8s.yml index e091a4676..c63389f6d 100644 --- a/src/test/resources/example/example_k8s.yml +++ b/src/test/resources/example/example_k8s.yml @@ -2,7 +2,7 @@ identifier: k8s:example name: Kubernetes example sources: - format: kubernetes - url: http://192.168.99.100:8080?namespace=default&groupLabel=release + url: http://10.96.0.1:8443?namespace=default&groupLabel=release config: kpis: diff --git a/src/test/resources/example/example_typo.yml b/src/test/resources/example/example_typo.yml index 826534e4f..a628c417a 100644 --- a/src/test/resources/example/example_typo.yml +++ b/src/test/resources/example/example_typo.yml @@ -3,4 +3,4 @@ name: Landscape example contact: mail@acme.org itemss: - - identifier: foo \ No newline at end of file + - identifier: foo diff --git a/src/test/resources/example/inout.yml b/src/test/resources/example/inout.yml index f9b8f821f..31e3aac7e 100644 --- a/src/test/resources/example/inout.yml +++ b/src/test/resources/example/inout.yml @@ -1,11 +1,11 @@ identifier: inout name: Input and Output description: Misuses the landscape graph to show the input and output possibilities of nivio. +icon: https://dedica.team/images/logo_orange_weiss.png config: branding: mapStylesheet: http://localhost:8080/css/inout.css - mapLogo: https://dedica.team/images/logo_orange_weiss.png groups: output: diff --git a/src/test/resources/example/internals.yml b/src/test/resources/example/internals.yml index 4dc84473b..6a7760d2b 100644 --- a/src/test/resources/example/internals.yml +++ b/src/test/resources/example/internals.yml @@ -2,6 +2,7 @@ identifier: nivio.internals name: Internal Workflows contact: info@dedica.team description: The workflow end to end +icon: https://dedica.team/images/logo_orange_weiss.png groups: start: @@ -15,6 +16,9 @@ groups: reports: name: Reporting description: Written Reports + observation: + name: Observation + description: Observation of input changed items: @@ -25,6 +29,7 @@ items: icon: sprout relations: - target: config + type: provider - identifier: config name: Config Files @@ -33,6 +38,17 @@ items: icon: file-multiple relations: - target: sources/parsing + type: dataflow + label: IndexEvent + + - identifier: observerpool + name: Observer Pool + description: Observers for each landscape watching for changes + group: observation + relations: + - target: sources/parsing + type: dataflow + label: InputChangedEvent - identifier: parsing group: sources @@ -40,6 +56,7 @@ items: icon: file-cog relations: - target: sources/factory + type: dataflow - identifier: factory group: sources @@ -48,13 +65,15 @@ items: icon: factory relations: - target: sources/environment + type: dataflow - identifier: environment group: sources - description: A partial or complete landscape graph consisting of DTOs that is merge into the landscape graph. + description: A partial or complete landscape graph consisting of DTOs that is merged into the landscape graph. note: See LandscapeDescription.java relations: - target: indexing/indexing + type: dataflow - identifier: indexing group: indexing @@ -62,18 +81,21 @@ items: note: See Indexer.java relations: - target: indexing/templates + type: dataflow - identifier: templates group: indexing description: Dynamic batch assignment of item values based on templates relations: - target: indexing/speciallabels + type: dataflow - identifier: speciallabels group: indexing description: Applies labels prefixed with "nivio" to item fields. relations: - target: indexing/greedy + type: dataflow - identifier: greedy name: items on the fly @@ -81,6 +103,7 @@ items: description: Creates items on the fly if nivio is configured "greedy". relations: - target: indexing/dynrelations + type: dataflow - identifier: dynrelations group: indexing @@ -88,31 +111,36 @@ items: description: Finds relation endpoints based on regexes or queries relations: - target: indexing/groups + type: dataflow - identifier: groups group: indexing description: Adds groups relations: - target: indexing/diff + type: dataflow - identifier: diff group: indexing description: Updates item fiels, adds and removes items relations: - target: indexing/grouping + type: dataflow - identifier: grouping group: indexing description: Resolves grouping queries to assign items to groups relations: - target: indexing/magic + type: dataflow - identifier: magic - name: magic relations + name: detect relations group: indexing description: Parses item labels to find clues on relations (like database links). relations: - target: indexing/relations + type: dataflow - identifier: relations name: relations @@ -120,16 +148,17 @@ items: description: Sets regular relations relations: - target: indexing/enrich + type: dataflow - identifier: enrich name: enrich data group: indexing - lifecycle: PLAN description: Adds data to item fields from external sources (links) links: issue: https://github.com/dedica-team/nivio/issues/97 relations: - target: graph/graph + type: dataflow # # graph @@ -141,7 +170,8 @@ items: icon: graphql relations: - target: assessment/kpis - - target: rendering/sublayout + type: dataflow + label: ProcessingFinishedEvent - target: reports/html # @@ -153,6 +183,7 @@ items: description: Loads the KPIs that have been configured for the landscape relations: - target: assessment/visitor + type: dataflow - identifier: visitor name: visit components @@ -160,10 +191,28 @@ items: description: Visits all landscape components in order to apply KPIs relations: - target: assessment/assessment + type: dataflow - identifier: assessment group: assessment description: Collects all KPIs from all components as map (containing FullyQualifiedIdenfiers) + relations: + - target: rendering/sublayout + type: dataflow + label: AssessmentChangedEvent + - target: search/search + type: dataflow + label: AssessmentChangedEvent + + # + # search + # + - identifier: search + name: in-group layout + group: search + icon: search + description: Indexes the landscape and the assessments + # # rendering @@ -175,6 +224,7 @@ items: description: Layouts the items of one group and provides a container for the group to hold all items relations: - target: rendering/layout + type: dataflow - identifier: layout name: group layout @@ -183,6 +233,7 @@ items: description: Layouts the group containers as graph nodes, edges are connections between items of different groups relations: - target: rendering/hex + type: dataflow - identifier: hex name: hex mapping @@ -191,6 +242,7 @@ items: description: Projection of items onto a hex map by transforming previously calculated x-y coordinates to q-r hex coordinates relations: - target: rendering/pathfinding + type: dataflow - identifier: pathfinding note: see PathFinder.java @@ -199,8 +251,11 @@ items: description: A* pathfinding to draw item relations (graph edges) relations: - target: rendering/svg + type: dataflow + label: LayoutChangedEvent - identifier: svg + name: RenderCache group: rendering shortname: 🌈 description: Renders item, pathes and groups diff --git a/src/test/resources/example/pet_clinic.yml b/src/test/resources/example/pet_clinic.yml index dfb282b11..a2dec127d 100644 --- a/src/test/resources/example/pet_clinic.yml +++ b/src/test/resources/example/pet_clinic.yml @@ -2,6 +2,7 @@ identifier: petclinic name: ACME Pet Clinic contact: mail@acme.io description: The Pet clinic IT landscape +icon: https://dedica.team/images/logo_orange_weiss.png config: greedy: false @@ -9,11 +10,12 @@ config: radiation: description: Radiation level in mrem label: radiation - messageTemplate: "Level: %s mrem" + messageTemplate: "level: %s mrem" ranges: GREEN: 0;99.999999 YELLOW: 100;199.999999 - RED: 200;499.999999 + ORANGE: 200;399.999999 + RED: 400;499.999999 BROWN: 500;1000000 diff --git a/src/test/resources/example/services/pet_clinic_billing.yml b/src/test/resources/example/services/pet_clinic_billing.yml index abedbf484..ae50a2aea 100644 --- a/src/test/resources/example/services/pet_clinic_billing.yml +++ b/src/test/resources/example/services/pet_clinic_billing.yml @@ -23,6 +23,8 @@ items: relations: - type: dataflow target: emailer + description: Sends PDF invoices to customers + weight: 2.3 tags: - java - backend diff --git a/src/test/resources/example/services/pet_clinic_customers.yml b/src/test/resources/example/services/pet_clinic_customers.yml index 7262e25a7..d618580af 100644 --- a/src/test/resources/example/services/pet_clinic_customers.yml +++ b/src/test/resources/example/services/pet_clinic_customers.yml @@ -3,6 +3,7 @@ groups: owner: Louis Armstrong description: The customer portal and self service color: "#234234" + icon: https://dedica.team/images/logo_orange_weiss.png items: - identifier: web diff --git a/src/test/resources/example/services/pet_clinic_xray.yml b/src/test/resources/example/services/pet_clinic_xray.yml index e7f7c2b04..51fb97a51 100644 --- a/src/test/resources/example/services/pet_clinic_xray.yml +++ b/src/test/resources/example/services/pet_clinic_xray.yml @@ -17,7 +17,8 @@ items: - identifier: sensor group: xray - type: radioactive + type: sensor + icon: radioactive statuses: - label: radiation status: red diff --git a/src/test/resources/example/services/test_relation.csv b/src/test/resources/example/services/test_relation.csv new file mode 100644 index 000000000..079009714 --- /dev/null +++ b/src/test/resources/example/services/test_relation.csv @@ -0,0 +1,2 @@ +service;id;desc;targets +"a relation";"foo;bar";This does nothing;