Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sprite library and spritesets #265

Merged
merged 2 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions scripts/gilbarbaraImageSpriteParser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import re
import json
import urllib.request

GILBARBARA_ICON_URL = "https://raw.githubusercontent.com/plantuml-stdlib/gilbarbara-plantuml-sprites/v1.1"
SPRITE_FILE_URL = "https://raw.githubusercontent.com/rabelenda/gilbarbara-plantuml-sprites/refs/heads/master/sprites-list.md"
OUTPUT_FILE_JSON = "../src/main/resources/sprites/gilbarbara_image_sprites.json"
URL_VAR_NAME = "GILBARBARA_PNG_URL"
ADDITIOANL_DEFINITIONS = [URL_VAR_NAME + " " + GILBARBARA_ICON_URL+"/pngs"]


def icon_names_to_path():
sprite_defs = urllib.request.urlopen(SPRITE_FILE_URL).readlines()
icon_name_to_path = {}
for sprite_def in sprite_defs[5:]:
sprite_values = sprite_def.decode("utf-8").split("|")
name = sprite_values[1] + "-img"
icon = sprite_values[2]
icon_path = re.search(r"\((.+)\)", icon).group(1).replace("pngs","")
icon_path = "img:" + GILBARBARA_ICON_URL + icon_path
icon_name_to_path[name] = icon_path
return icon_name_to_path


if __name__ == "__main__":
json_sprites = []
for name, url in icon_names_to_path().items():
json_sprites.append(
{
"@type": "ImageSprite",
"name": "logos-" + name,
"url": url.replace(GILBARBARA_ICON_URL, URL_VAR_NAME),
}
)

sprite_set = {}
sprite_set["name"] = "gilbarbara PNG sprites"
sprite_set["source"] = GILBARBARA_ICON_URL
sprite_set["additionalDefinitions"] = ADDITIOANL_DEFINITIONS
sprite_set["sprites"] = json_sprites
with open(OUTPUT_FILE_JSON, "w") as f:
f.write(json.dumps(sprite_set))
271 changes: 271 additions & 0 deletions scripts/standardLibSpriteParser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
import json
from collections import OrderedDict
import os
import glob

STANDARD_LIB_FOLDER = "../../plantuml-stdlib/stdlib"
STANDARD_LIB_FOLDER_URL = "https://github.com/plantuml/plantuml-stdlib/tree/master/stdlib"

AWS_STANDARD_LIB_FOLDER = "/awslib14/"
AWS_OUTPUT_FILE_PATH = "../src/main/resources/sprites/aws_stdlib_sprites.json"

AZURE_STANDARD_LIB_FOLDER = "/azure/"
AZURE_OUTPUT_FILE_PATH = "../src/main/resources/sprites/azure_stdlib_sprites.json"

ELASTIC_STANDARD_LIB_FOLDER = "/elastic/"
ELASTIC_OUTPUT_FILE_PATH = "../src/main/resources/sprites/elastic_stdlib_sprites.json"

GCP_STANDARD_LIB_FOLDER = "/gcp/"
GCP_OUTPUT_FILE_PATH = "../src/main/resources/sprites/gcp_stdlib_sprites.json"

K8S_STANDARD_LIB_FOLDER = "/k8s/"
K8S_OUTPUT_FILE_PATH = "../src/main/resources/sprites/k8s_stdlib_sprites.json"

CLOUDINSIGHT_STANDARD_LIB_FOLDER = "/cloudinsight/"
CLOUDINSIGHT_OUTPUT_FILE_PATH = (
"../src/main/resources/sprites/cloudinsight_stdlib_sprites.json"
)


MATERIAL_STANDARD_LIB_FOLDER = "/material/"
MATERIAL_OUTPUT_FILE_PATH = "../src/main/resources/sprites/material_stdlib_sprites.json"

LOGOS_STANDARD_LIB_FOLDER = "/logos/"
LOGOS_OUTPUT_FILE_PATH = "../src/main/resources/sprites/logos_stdlib_sprites.json"

OFFICE_STANDARD_LIB_FOLDER = "/office/"
OFFICE_OUTPUT_FILE_PATH = "../src/main/resources/sprites/office_stdlib_sprites.json"

OSA_STANDARD_LIB_FOLDER = "/osa/"
OSA_OUTPUT_FILE_PATH = "../src/main/resources/sprites/osa_stdlib_sprites.json"

TUPADR3_STANDARD_LIB_FOLDER = "/tupadr3/"
TUPADR3_OUTPUT_FILE_PATH = "../src/main/resources/sprites/tupadr3_stdlib_sprites.json"

# violet
AWS_COLOR_NEBULA = "#C925D1"
# green
AWS_COLOR_ENDOR = "#7AA116"
# orange
AWS_COLOR_SMILE = "#ED7100"
# pink
AWS_COLOR_COSMOS = "#E7157B"
# purple
AWS_COLOR_GALAXY = "#8C4FFF"
# red
AWS_COLOR_MARS = "#DD344C"
# turquoise
AWS_COLOR_ORBIT = "#01A88D"
# Default (blue)
AWS_COLOR_SQUID = "#232F3E"


def elastic_name_function(path):
name = path.replace("/", "-")
deduplicated_name = "-".join(OrderedDict.fromkeys(name.split("-")))
return deduplicated_name.replace("_", "-")


def default_name_function(path):
return path.replace("/", "-").replace("_", "-")


def k8s_name_function(path):
return default_name_function(path).replace("OSS-", "")


def aws_name_function(path):
return default_name_function(path).replace("lib14", "")


def aws_color_by_group(group):
color = AWS_COLOR_SQUID
if group in ["Customer", "Enablement", "Database", "DeveloperTools", "Satellite"]:
color = AWS_COLOR_NEBULA
elif group in ["CloudFinancialManagement", "InternetOfThings", "Storage"]:
color = AWS_COLOR_ENDOR
elif group in [
"Blockchain",
"Compute",
"Containers",
"Media Services",
"QuantumTechnologies",
]:
color = AWS_COLOR_SMILE
elif group in ["ApplicationIntegration", "ManagementGovernance"]:
color = AWS_COLOR_COSMOS
elif group in ["Analytics", "Games", "NetworkingContentDelivery", "Serverless"]:
color = AWS_COLOR_GALAXY
elif group in [
"BusinessApplications",
"ContactCenter",
"FrontEndWebMobile",
"Robotics",
"Security",
"Identity",
"Compliance",
]:
color = AWS_COLOR_MARS
elif group in ["EndUserComputing", "MachineLearning", "MigrationTransfer"]:
color = AWS_COLOR_ORBIT
return color


def write_sprite_set(
output_file,
sprite_set_name,
sprite_set_source,
json_sprites,
additional_includes,
):
with open(output_file, "w") as f:
sprite_set = {}
sprite_set["name"] = sprite_set_name
sprite_set["source"] = sprite_set_source
if additional_includes:
sprite_set["additionalIncludes"] = additional_includes
sprite_set["sprites"] = json_sprites
f.write(json.dumps(sprite_set))


def create_sprites(
paths,
color_function,
name_function,
reference_function
):
json_sprites = []
for path in paths:
category = path.split("/")[1]
sprite = {}
sprite["@type"] = "PlantUmlSprite"
sprite["name"] = name_function(path)
sprite["path"] = "<" + path + ">"
if reference_function:
sprite["reference"] = reference_function(path)
if color_function:
sprite["color"] = color_function(category)
json_sprites.append(sprite)
return json_sprites


def parse_paths(path_to_icon_folder, fileending):
paths = []
for full_path in glob.iglob(
path_to_icon_folder + "**/**/*[!LARGE|all]*" + fileending, recursive=True
):
relativ_path = full_path.replace(STANDARD_LIB_FOLDER, "")
norm_path = os.path.normpath(relativ_path)
icon_path = norm_path.replace(os.sep, "/").replace(fileending, "")
paths.append(icon_path[1:])
return paths


def process_sprite_folder(
sprite_source_folder,
output_file,
sprite_set_name,
sprite_fileending=".puml",
additional_includes=None,
color_function=None,
name_function=default_name_function,
reference_function=None
):
paths = parse_paths(STANDARD_LIB_FOLDER+sprite_source_folder, sprite_fileending)
json_sprites = create_sprites(
paths=paths,
color_function=color_function,
name_function=name_function,
reference_function=reference_function
)
write_sprite_set(
output_file=output_file,
sprite_set_name=sprite_set_name,
sprite_set_source=STANDARD_LIB_FOLDER_URL+sprite_source_folder,
json_sprites=json_sprites,
additional_includes=additional_includes,
)


if __name__ == "__main__":
process_sprite_folder(
sprite_source_folder=AWS_STANDARD_LIB_FOLDER,
output_file=AWS_OUTPUT_FILE_PATH,
sprite_set_name="AWS plantuml-stdlib Sprites",
additional_includes=["<awslib14/AWSCommon>"],
color_function=aws_color_by_group,
name_function=aws_name_function,
)

process_sprite_folder(
sprite_source_folder=AZURE_STANDARD_LIB_FOLDER,
output_file=AZURE_OUTPUT_FILE_PATH,
sprite_set_name="Azure plantuml-stdlib Sprites",
additional_includes=["<azure/AzureCommon>"],
color_function=lambda _: "#0072C6",
)

process_sprite_folder(
sprite_source_folder=ELASTIC_STANDARD_LIB_FOLDER,
output_file=ELASTIC_OUTPUT_FILE_PATH,
sprite_set_name="Elastic plantuml-stdlib Sprites",
color_function=lambda _: "#51D0C8",
sprite_fileending="-sprite.puml",
name_function=elastic_name_function,
)

process_sprite_folder(
sprite_source_folder=GCP_STANDARD_LIB_FOLDER,
output_file=GCP_OUTPUT_FILE_PATH,
sprite_set_name="Google Cloud Platform plantuml-stdlib Sprites",
additional_includes=["<gcp/GCPCommon>"],
color_function=lambda _: "#79B3FE",
)

process_sprite_folder(
sprite_source_folder=K8S_STANDARD_LIB_FOLDER,
output_file=K8S_OUTPUT_FILE_PATH,
sprite_set_name="Kubernetes plantuml-stdlib Sprites",
additional_includes=["<k8s/Common>"],
color_function=lambda _: "#66ABDD",
name_function=k8s_name_function,
)

process_sprite_folder(
sprite_source_folder=CLOUDINSIGHT_STANDARD_LIB_FOLDER,
output_file=CLOUDINSIGHT_OUTPUT_FILE_PATH,
sprite_set_name="Cloudinsight plantuml-stdlib Sprites",
color_function=lambda _: "#23a3dd",
)

process_sprite_folder(
sprite_source_folder=MATERIAL_STANDARD_LIB_FOLDER,
output_file=MATERIAL_OUTPUT_FILE_PATH,
sprite_set_name="Google Material plantuml-stdlib Sprites",
reference_function=lambda path: "ma_"+path.split("/")[-1]
)

process_sprite_folder(
sprite_source_folder=LOGOS_STANDARD_LIB_FOLDER,
output_file=LOGOS_OUTPUT_FILE_PATH,
sprite_set_name="Logos plantuml-stdlib Sprites",
)

process_sprite_folder(
sprite_source_folder=OFFICE_STANDARD_LIB_FOLDER,
output_file=OFFICE_OUTPUT_FILE_PATH,
sprite_set_name="Office plantuml-stdlib Sprites",
)

process_sprite_folder(
sprite_source_folder=OSA_STANDARD_LIB_FOLDER,
output_file=OSA_OUTPUT_FILE_PATH,
sprite_set_name="Open Security Architecture plantuml-stdlib Sprites",
sprite_fileending="-sprite.puml",
)

process_sprite_folder(
sprite_source_folder=TUPADR3_STANDARD_LIB_FOLDER,
output_file=TUPADR3_OUTPUT_FILE_PATH,
sprite_set_name="TUPADR3 plantuml-stdlib Sprites",
)
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package com.github.chriskn.structurizrextension.api.icons

import com.github.chriskn.structurizrextension.api.view.style.sprite.PUmlSprite
import java.net.MalformedURLException
import java.net.URI
import java.net.URL

internal const val AWS_ICON_URL = "https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/v11.1/dist/"
internal const val AWS_ICON_URL = "https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/v18.0/dist/"
internal const val AWS_ICON_COMMONS = "${AWS_ICON_URL}AWSCommon.puml"

// TODO deprecate
/**
* Registry containing the available icons.
*
Expand Down Expand Up @@ -36,7 +34,7 @@ object IconRegistry {
}

internal fun validate(name: String, url: String) {
require(name.isNotBlank()) { "Icon name cannot be blank" }
require(name.isNotBlank()) { "Icon name must not be blank" }
require(url.endsWith(PUML_FILE_EXTENSION)) {
"Icon URL needs to point to .puml file but was $url"
}
Expand All @@ -56,7 +54,7 @@ object IconRegistry {
/**
* @return The file name of an icon with the given name (case-insensitive) or null if no icon with the given name exists.
*/
@Deprecated("use spriteForName instead")
@Deprecated("use sprite API instead")
internal fun iconFileNameFor(name: String?): String? {
return if (name == null || !exists(name)) {
null
Expand All @@ -69,22 +67,6 @@ object IconRegistry {
}
}

/**
* @param name the name of the sprite
* @return the PumlSprite for a given name or null if no sprites exists
*/
internal fun spriteForName(name: String?): PUmlSprite? {
if (name == null || !exists(name)) {
return null
}
val url = iconNameToIconUrl[name.lowercase()]
val iconFileName = iconFileNameFor(name)
if (url == null || iconFileName == null) {
return null
}
return PUmlSprite(name = iconFileName, url = url.toString())
}

internal fun reset() {
iconNameToIconUrl.clear()
iconNameToIconUrl.putAll(commonIcons.mapValues { URI(it.value).toURL() })
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.github.chriskn.structurizrextension.api.model

import com.github.chriskn.structurizrextension.api.icons.IconRegistry
import com.github.chriskn.structurizrextension.api.view.style.sprite.Sprite
import com.github.chriskn.structurizrextension.api.view.sprite.sprites.Sprite
import com.structurizr.model.Component
import com.structurizr.model.Container
import com.structurizr.model.StaticStructureElement
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.github.chriskn.structurizrextension.api.model

import com.github.chriskn.structurizrextension.api.icons.IconRegistry
import com.github.chriskn.structurizrextension.api.view.style.sprite.Sprite
import com.github.chriskn.structurizrextension.api.view.sprite.sprites.Sprite
import com.structurizr.model.Element
import com.structurizr.model.InteractionStyle

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.github.chriskn.structurizrextension.api.model

import com.github.chriskn.structurizrextension.api.icons.IconRegistry
import com.github.chriskn.structurizrextension.api.view.style.sprite.Sprite
import com.github.chriskn.structurizrextension.api.view.sprite.sprites.Sprite
import com.structurizr.model.Container
import com.structurizr.model.DeploymentElement
import com.structurizr.model.DeploymentNode
Expand Down
Loading