Преглед изворни кода

Studio app icons: Azure AD B2C, Azure Connect, CAS Connect, cidaas Connect

Integrations sit on the white plate. Azure AD B2C and Azure Connect carry
the Entra marks (thesvg.org azure-azure-ad-b2c / azure-entra-connect),
cidaas its own mark without the wordmark; the artwork is kept as it is,
scaled to 50px and centred, with the united outline of every shape as
the 10% shadow. CAS Connect uses the Lucide fingerprint-pattern glyph,
flattened, in the zinc gradient the gray plates use.

The generator gains the white plate (dark glyph) and an artwork mode.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Andrey Yasko пре 1 месец
родитељ
комит
17c4522467

Разлика између датотеке није приказан због своје велике величине
+ 3 - 49
modules/boonex/azure_b2c_con/template/images/icons/std-icon.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 49
modules/boonex/azure_connect/template/images/icons/std-icon.svg


Разлика између датотеке није приказан због своје велике величине
+ 3 - 24
modules/boonex/cas_connect/template/images/icons/std-icon.svg


+ 23 - 73
modules/boonex/cidaas_connect/template/images/icons/std-icon.svg

@@ -1,75 +1,25 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 24.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-	 viewBox="0 0 288 286.9" style="enable-background:new 0 0 288 286.9;" xml:space="preserve">
-<style type="text/css">
-	.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#F04923;}
-	.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#F9AE1C;}
-	.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#F89521;}
-	.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#F47422;}
-	.st4{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
-	.st5{fill:#565656;}
-</style>
-<g>
-	<g>
-		<g id="Rounded_Rectangle_1">
-			<g>
-				<path class="st0" d="M179.3,38.3c-20-20-52.4-20-72.4,0L7.7,137.5l99.1,99.2c20,20,52.4,20,72.4,0l99.2-99.1L179.3,38.3z"/>
-			</g>
-		</g>
-		<g id="Rounded_Rectangle_1_copy">
-			<g>
-				<path class="st1" d="M223.1,82.2L88.5,218.4l18.3,18.3c20,20,52.4,20,72.4,0l99.2-99.1L223.1,82.2z"/>
-			</g>
-		</g>
-		<g id="Rounded_Rectangle_1_copy_2">
-			<g>
-				<path class="st2" d="M224.5,83.6l-45.2-45.2c-20-20-52.4-20-72.4,0L7.7,137.5l96.7,96.8C211,193,223.2,107.6,224.5,83.6z"/>
-			</g>
-		</g>
-		<g id="Rounded_Rectangle_1_copy_4">
-			<g>
-				<path class="st3" d="M190.3,49.4l-11-11c-20-20-52.4-20-72.4,0L7.7,137.5l65.9,65.9C88.5,198.3,180.1,162.8,190.3,49.4z"/>
-			</g>
-		</g>
-		<g id="Rounded_Rectangle_1_copy_3">
-			<g>
-				<path class="st0" d="M151.1,24c-15.6-2.5-32.2,2.3-44.2,14.4L7.7,137.5l29.9,30C50.1,163.4,138.8,131.3,151.1,24z"/>
-			</g>
-		</g>
-		<g id="Ellipse_1">
-			<g>
-				<path class="st4" d="M148.5,189.4c-25.1-4-44.3-25.5-44.3-51.5c0-25.6,18.7-46.9,43.3-51.3c2.6-4,5.5-7.8,8.7-11.2
-					c-34.7,1.9-62.3,29-62.3,62.1c0,33.3,27.8,60.5,62.8,62.2C153.7,196.5,151,193,148.5,189.4z"/>
-			</g>
-		</g>
-		<g id="Rectangle_1">
-			<g>
-				<path class="st4" d="M133.3,137.9v-0.8c0-12.4,10-22.4,22.4-22.4h16.5V105h-17.3c-17.2,0-31.1,13.9-31.1,31.1v3.5
-					c0,17.2,13.9,31.1,31.1,31.1h20v-10.3h-19.2C143.4,160.3,133.3,150.3,133.3,137.9z"/>
-			</g>
-		</g>
-		<g id="Ellipse_2">
-			<g>
-				<path class="st4" d="M172.5,75.2c-10.9,0-19.7,8.8-19.7,19.7c0,1.4,0.1,2.7,0.4,4.1h10.6c-0.5-1.1-0.7-2.4-0.7-3.6
-					c0-5.3,4.3-9.6,9.6-9.6s9.6,4.3,9.6,9.6c0,4.9-3.7,8.9-8.4,9.5v0.1h-18.3c3.4,5.8,9.7,9.7,17,9.7c10.9,0,19.7-8.8,19.7-19.7
-					C192.2,84.1,183.4,75.2,172.5,75.2z"/>
-			</g>
-		</g>
-		<g id="Ellipse_2_copy">
-			<g>
-				<path class="st4" d="M175.6,160.3h-6.3c-6.2,1-11.4,4.9-14.2,10.3h16.6v0c0.3,0,0.6,0,0.9,0c5.3,0,9.6,4.3,9.6,9.6
-					s-4.3,9.6-9.6,9.6s-9.6-4.3-9.6-9.6c0-1.2,0.2-2.3,0.6-3.4H153c-0.1,1-0.2,2-0.2,3c0,10.9,8.8,19.7,19.7,19.7
-					c10.9,0,19.7-8.8,19.7-19.7C192.2,169.9,185,161.8,175.6,160.3z"/>
-			</g>
-		</g>
-	</g>
-	<g>
-		<path class="st5" d="M278.7,242.3c0,5.6-4.4,10-10.1,10c-5.7,0-10.2-4.4-10.2-10c0-5.5,4.5-9.9,10.2-9.9
-			C274.3,232.4,278.7,236.8,278.7,242.3z M260.9,242.3c0,4.4,3.3,7.9,7.7,7.9c4.3,0,7.5-3.5,7.5-7.8c0-4.4-3.2-7.9-7.6-7.9
-			C264.2,234.4,260.9,238,260.9,242.3z M267,247.5h-2.3v-9.9c0.9-0.2,2.2-0.3,3.8-0.3c1.9,0,2.7,0.3,3.4,0.7c0.5,0.4,1,1.2,1,2.2
-			c0,1.1-0.8,1.9-2,2.3v0.1c1,0.4,1.5,1.1,1.8,2.4c0.3,1.5,0.5,2.1,0.7,2.5h-2.5c-0.3-0.4-0.5-1.3-0.8-2.4c-0.2-1.1-0.8-1.6-2-1.6
-			H267V247.5z M267.1,241.9h1.1c1.3,0,2.3-0.4,2.3-1.4c0-0.9-0.7-1.5-2.1-1.5c-0.6,0-1,0.1-1.3,0.1V241.9z"/>
-	</g>
+<svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="80" height="80" fill="url(#paint0_linear_cidaascon)"/>
+<g transform="translate(13.844 17.150) scale(0.14628)">
+<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M224.5,31.1c-25.2-25.3-66.2-25.3-91.4,0L7.9,156.2l125.1,125.2c25.2,25.3,66.2,25.3,91.4,0l125.2-125.1      L224.5,31.1z" fill-rule="evenodd" clip-rule="evenodd" fill="#F04923" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M279.9,86.4L110,258.2l23.1,23.1c25.2,25.3,66.2,25.3,91.4,0l125.2-125.1L279.9,86.4z" fill-rule="evenodd" clip-rule="evenodd" fill="#F9AE1C" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M281.6,88.1l-57-57.1c-25.2-25.3-66.2-25.3-91.4,0L7.9,156.2L130,278.3C264.6,226.2,280,118.4,281.6,88.1z" fill-rule="evenodd" clip-rule="evenodd" fill="#F89521" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M238.5,45l-13.9-13.9c-25.2-25.3-66.2-25.3-91.4,0L7.9,156.2l83.2,83.2C110,233,225.6,188.1,238.5,45z" fill-rule="evenodd" clip-rule="evenodd" fill="#F47422" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M188.9,12.9c-19.7-3.1-40.6,2.9-55.8,18.1L7.9,156.2L45.7,194C61.6,188.9,173.5,148.4,188.9,12.9z" fill-rule="evenodd" clip-rule="evenodd" fill="#F04923" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M185.6,221.6c-31.7-5-55.9-32.2-55.9-64.9c0-32.3,23.6-59.2,54.6-64.7c3.3-5.1,7-9.8,11-14.2      c-43.8,2.5-78.6,36.6-78.6,78.4c0,42,35.1,76.3,79.3,78.4C192.3,230.6,188.8,226.3,185.6,221.6z" fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M166.5,156.7v-1c0-15.6,12.7-28.3,28.3-28.3h20.8v-12.3h-21.8c-21.6,0-39.2,17.5-39.2,39.2v4.4      c0,21.6,17.5,39.2,39.2,39.2H219v-13h-24.2C179.2,185,166.5,172.3,166.5,156.7z" fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M216,77.6c-13.7,0-24.9,11.1-24.9,24.9c0,1.8,0.2,3.5,0.5,5.1h13.3c-0.6-1.4-0.9-3-0.9-4.6      c0-6.7,5.4-12.1,12.1-12.1c6.7,0,12.1,5.4,12.1,12.1c0,6.2-4.6,11.2-10.6,12v0.1h-23.1c4.3,7.3,12.3,12.3,21.4,12.3      c13.7,0,24.9-11.1,24.9-24.9S229.7,77.6,216,77.6z" fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" />
+			<svg:path xmlns:svg="http://www.w3.org/2000/svg" d="M220,185h-8.1c-7.8,1.3-14.4,6.2-18,13h21v0.1c0.4,0,0.8-0.1,1.2-0.1c6.7,0,12.1,5.4,12.1,12.1      s-5.4,12.1-12.1,12.1c-6.7,0-12.1-5.4-12.1-12.1c0-1.5,0.3-2.9,0.8-4.3h-13.5c-0.2,1.2-0.3,2.5-0.3,3.7      c0,13.7,11.1,24.9,24.9,24.9s24.9-11.1,24.9-24.9C240.8,197.2,231.8,186.9,220,185z" fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" />
+			
 </g>
+<g transform="translate(13.844 18.150) scale(0.14628)">
+<path fill-rule="evenodd" fill="black" fill-opacity="0.1" d="M150.50 18.59 L148.25 19.74 L146.03 20.98 L143.87 22.31 L141.77 23.72 L139.73 25.21 L137.74 26.79 L135.81 28.44 L133.93 30.19 L7.90 156.20 L133.18 281.58 L134.45 282.81 L135.74 283.99 L137.05 285.14 L138.41 286.26 L140.99 288.22 L143.65 290.05 L145.02 290.91 L146.43 291.74 L149.26 293.29 L152.18 294.69 L155.16 295.95 L158.21 297.05 L161.30 298.00 L164.45 298.79 L167.64 299.43 L170.86 299.90 L174.09 300.21 L177.33 300.36 L180.60 300.35 L183.84 300.17 L187.07 299.83 L189.43 299.48 L191.78 299.04 L194.12 298.52 L196.44 297.90 L198.72 297.21 L200.98 296.42 L203.20 295.56 L205.39 294.62 L207.55 293.59 L209.66 292.48 L211.72 291.31 L213.75 290.05 L215.72 288.72 L217.65 287.31 L219.52 285.83 L221.35 284.27 L222.82 282.94 L224.25 281.55 L349.70 156.20 L281.60 88.10 L224.27 30.67 L222.19 28.70 L220.04 26.84 L217.82 25.07 L215.51 23.40 L213.74 22.22 L211.94 21.10 L210.09 20.04 L208.21 19.05 L206.29 18.11 L204.35 17.24 L202.38 16.43 L200.38 15.69 L198.36 15.01 L196.32 14.41 L194.26 13.87 L192.17 13.40 L190.07 12.99 L187.97 12.66 L185.85 12.40 L183.71 12.20 L181.58 12.08 L179.43 12.03 L177.28 12.05 L175.15 12.13 L173.00 12.29 L170.88 12.52 L168.75 12.82 L166.65 13.19 L164.55 13.63 L162.49 14.13 L160.42 14.71 L158.39 15.35 L156.38 16.06 L154.39 16.84 L152.43 17.68 Z"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_cidaascon" x1="40" y1="0" x2="40" y2="80" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F3F4F6"/>
+<stop offset="1" stop-color="#E5E7EB"/>
+</linearGradient>
+
+</defs>
 </svg>

+ 91 - 2
scripts/studio_icon_from_lucide.py

@@ -24,6 +24,12 @@ PLATES = {
     'green':  ('#059669', '#065F46'),
     'orange': ('#D97706', '#92400E'),
     'purple': ('#7C3AED', '#5B21B6'),
+    'red':    ('#F43F5E', '#BE123C'),
+    'white':  ('#F3F4F6', '#E5E7EB'),
+}
+# glyph gradient (top, bottom): white fading out on a coloured plate, zinc on the white plate
+GLYPH = {
+    'white': ('#71717A', '#3F3F46'),
 }
 
 ICONS = [
@@ -34,6 +40,17 @@ ICONS = [
     ('modules/boonex/lucid/template/images/icons/std-icon.svg', 'lucid', 'purple', 'layout-panel-top', 80),
     ('modules/boonex/mapshow/template/images/icons/std-icon.svg', 'mapshow', 'green', 'map', 80),
     ('studio/template/images/modules/bx_polls.svg', 'polls', 'green', 'vote', 72),
+    ('modules/boonex/cas_connect/template/images/icons/std-icon.svg', 'cas', 'white', 'fingerprint-pattern', 80),
+]
+
+# Brand artwork on the white plate: the source SVG's shapes are copied as they are (fills, gradients), scaled to
+# ART_WIDTH px and centred; the shadow is the united outline of every shape, filled black/10 and shifted 1px down.
+# 'skip' drops shapes by class or id (wordmarks, registered marks). The source files are not part of the repo.
+ART_WIDTH = 50
+ART = [
+    # ('modules/boonex/azure_b2c_con/template/images/icons/std-icon.svg', 'azrb2c', '<thesvg.org azure-azure-ad-b2c default.svg>', ()),
+    # ('modules/boonex/azure_connect/template/images/icons/std-icon.svg', 'azrcon', '<thesvg.org azure-entra-connect default.svg>', ()),
+    # ('modules/boonex/cidaas_connect/template/images/icons/std-icon.svg', 'cidaascon', '<cidaas logo-cidaas-vertical-color-print.svg>', ('st5',)),
 ]
 
 STROKE = 2.0      # Lucide stroke width, in its 24-unit space
@@ -122,6 +139,8 @@ def shape_to_d(shape):
 
 def icon(uid, plate, d, size):
     c1, c2 = PLATES[plate]
+    g1, g2 = GLYPH.get(plate, ('white', 'white'))
+    g2_opacity = '' if plate in GLYPH else ' stop-opacity="0.6"'
     if size == 80:
         t, ts, s = '13.6 13.6', '13.6 14.6', '2.2'
     else:
@@ -140,14 +159,79 @@ def icon(uid, plate, d, size):
 <stop offset="1" stop-color="{c2}"/>
 </linearGradient>
 <linearGradient id="paint1_linear_{uid}" x1="12" y1="2" x2="12" y2="22" gradientUnits="userSpaceOnUse">
-<stop stop-color="white"/>
-<stop offset="1" stop-color="white" stop-opacity="0.6"/>
+<stop stop-color="{g1}"/>
+<stop offset="1" stop-color="{g2}"{g2_opacity}/>
 </linearGradient>
 </defs>
 </svg>
 '''
 
 
+def art_icon(uid, src, skip, size=80):
+    """White plate, the source artwork scaled to ART_WIDTH and centred, its united outline as the shadow."""
+    from shapely.geometry import Polygon
+    ns = '{http://www.w3.org/2000/svg}'
+    root = ET.parse(src).getroot()
+    # class fills from a <style> block become attributes, so the art survives being inlined next to other icons
+    css = {}
+    for st in root.iter(ns + 'style'):
+        for cls, body in re.findall(r'\.([\w-]+)\s*\{([^}]*)\}', st.text or ''):
+            css[cls] = dict(kv.split(':', 1) for kv in body.split(';') if ':' in kv)
+    inner, polys = [], []
+    for el in list(root):
+        if el.tag in (ns + 'style', ns + 'defs') and el.tag == ns + 'style':
+            continue
+    defs = ''.join(ET.tostring(el, encoding='unicode') for el in root.iter(ns + 'defs'))
+    xs, ys = [], []
+
+    def walk(el):
+        tag = el.tag.split('}')[-1]
+        if tag in ('style', 'defs'):
+            return
+        if el.attrib.get('class') in skip or el.attrib.get('id') in skip:
+            return
+        d = element_to_d(el)
+        if d:
+            for cls in el.attrib.pop('class', '').split():
+                for k, v in css.get(cls, {}).items():
+                    el.set(k.strip(), v.strip())
+            for pts in sample(d):
+                if len(pts) > 2:
+                    polys.append(Polygon(pts).buffer(0))
+                    xs.extend(x for x, _ in pts)
+                    ys.extend(y for _, y in pts)
+            inner.append(ET.tostring(el, encoding='unicode'))
+            return
+        for c in el:
+            walk(c)
+
+    for el in list(root):
+        walk(el)
+    x0, x1, y0, y1 = min(xs), max(xs), min(ys), max(ys)
+    s = ART_WIDTH / (x1 - x0)
+    tx, ty = (size - (x1 - x0) * s) / 2 - x0 * s, (size - (y1 - y0) * s) / 2 - y0 * s
+    shadow = shape_to_d(unary_union(polys).simplify(TOL / s, preserve_topology=True))
+    body = ''.join(inner).replace('xmlns:ns0="http://www.w3.org/2000/svg"', '').replace('ns0:', '')
+    c1, c2 = PLATES['white']
+    return f'''<svg width="{size}" height="{size}" viewBox="0 0 {size} {size}" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="{size}" height="{size}" fill="url(#paint0_linear_{uid})"/>
+<g transform="translate({tx:.3f} {ty:.3f}) scale({s:.5f})">
+{body}
+</g>
+<g transform="translate({tx:.3f} {ty + 1:.3f}) scale({s:.5f})">
+<path fill-rule="evenodd" fill="black" fill-opacity="0.1" d="{shadow}"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_{uid}" x1="{size / 2:g}" y1="0" x2="{size / 2:g}" y2="{size}" gradientUnits="userSpaceOnUse">
+<stop stop-color="{c1}"/>
+<stop offset="1" stop-color="{c2}"/>
+</linearGradient>
+{defs}
+</defs>
+</svg>
+'''
+
+
 for rel, uid, plate, glyph, size in ICONS:
     shape = glyph_outline(glyph)
     d = shape_to_d(shape)
@@ -155,3 +239,8 @@ for rel, uid, plate, glyph, size in ICONS:
     with open(ROOT + '/' + rel, 'w') as fh:
         fh.write(icon(uid, plate, d, size))
     print(f'{rel}: {glyph} -> {n} outline(s), {len(d)} chars')
+
+for rel, uid, src, skip in ART:
+    with open(ROOT + '/' + rel, 'w') as fh:
+        fh.write(art_icon(uid, src, skip))
+    print(f'{rel}: art from {src}')

Неке датотеке нису приказане због велике количине промена