detached 8c4b359

feat(assets): add SVG styling and automation script for logo shading

commit
8c4b3593c44315f86ae956ecb89dd9ebd35f009e
author
bnema · · 2025-10-29 17:38 UTC
parent
65d1092
signature
GPG Unverified2B82207D370127A0 The key is unknown
2 files · +102 -8
M assets/archup-logo.svg +3 -8
@@ -1,5 +1,5 @@
11 <?xml version="1.0" encoding="UTF-8"?>
2-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 240" width="1000" height="240">
2+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 240" width="750" height="180">
33 <defs>
44 <style>
55 text {
@@ -9,12 +9,7 @@
99 white-space: pre;
1010 text-anchor: middle;
1111 }
12+ .shade { fill: #2d4a6b; }
1213 </style>
1314 </defs>
14- <text x="500" y="40">░█████╗░██████╗░░█████╗░██╗░░██╗██╗░░░██╗██████╗░</text>
15- <text x="500" y="80">██╔══██╗██╔══██╗██╔══██╗██║░░██║██║░░░██║██╔══██╗</text>
16- <text x="500" y="120">███████║██████╔╝██║░░╚═╝███████║██║░░░██║██████╔╝</text>
17- <text x="500" y="160">██╔══██║██╔══██╗██║░░██╗██╔══██║██║░░░██║██╔═══╝░</text>
18- <text x="500" y="200">██║░░██║██║░░██║╚█████╔╝██║░░██║╚██████╔╝██║░░░░░</text>
19- <text x="500" y="240">╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝░╚═════╝░╚═╝░░░░░</text>
20-</svg>
15+ <text x="500" y="40"><tspan class="shade">░</tspan>█████╗<tspan class="shade">░</tspan>██████╗<tspan class="shade">░░</tspan>█████╗<tspan class="shade">░</tspan>██╗<tspan class="shade">░░</tspan>██╗██╗<tspan class="shade">░░░</tspan>██╗██████╗<tspan class="shade">░</tspan></text> <text x="500" y="80">██╔══██╗██╔══██╗██╔══██╗██║<tspan class="shade">░░</tspan>██║██║<tspan class="shade">░░░</tspan>██║██╔══██╗</text> <text x="500" y="120">███████║██████╔╝██║<tspan class="shade">░░</tspan>╚═╝███████║██║<tspan class="shade">░░░</tspan>██║██████╔╝</text> <text x="500" y="160">██╔══██║██╔══██╗██║<tspan class="shade">░░</tspan>██╗██╔══██║██║<tspan class="shade">░░░</tspan>██║██╔═══╝<tspan class="shade">░</tspan></text> <text x="500" y="200">██║<tspan class="shade">░░</tspan>██║██║<tspan class="shade">░░</tspan>██║╚█████╔╝██║<tspan class="shade">░░</tspan>██║╚██████╔╝██║<tspan class="shade">░░░░░</tspan></text> <text x="500" y="240">╚═╝<tspan class="shade">░░</tspan>╚═╝╚═╝<tspan class="shade">░░</tspan>╚═╝<tspan class="shade">░</tspan>╚════╝<tspan class="shade">░</tspan>╚═╝<tspan class="shade">░░</tspan>╚═╝<tspan class="shade">░</tspan>╚═════╝<tspan class="shade">░</tspan>╚═╝<tspan class="shade">░░░░░</tspan></text></svg>
@@ -1,5 +1,5 @@
1 <?xml version="1.0" encoding="UTF-8"?>1 <?xml version="1.0" encoding="UTF-8"?>
2-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 240" width="1000" height="240">2+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 240" width="750" height="180">
3 <defs>3 <defs>
4 <style>4 <style>
5 text {5 text {
@@ -9,12 +9,7 @@
9 white-space: pre;9 white-space: pre;
10 text-anchor: middle;10 text-anchor: middle;
11 }11 }
12+ .shade { fill: #2d4a6b; }
12 </style>13 </style>
13 </defs>14 </defs>
14- <text x="500" y="40">░█████╗░██████╗░░█████╗░██╗░░██╗██╗░░░██╗██████╗░</text>15+ <text x="500" y="40"><tspan class="shade">░</tspan>█████╗<tspan class="shade">░</tspan>██████╗<tspan class="shade">░░</tspan>█████╗<tspan class="shade">░</tspan>██╗<tspan class="shade">░░</tspan>██╗██╗<tspan class="shade">░░░</tspan>██╗██████╗<tspan class="shade">░</tspan></text> <text x="500" y="80">██╔══██╗██╔══██╗██╔══██╗██║<tspan class="shade">░░</tspan>██║██║<tspan class="shade">░░░</tspan>██║██╔══██╗</text> <text x="500" y="120">███████║██████╔╝██║<tspan class="shade">░░</tspan>╚═╝███████║██║<tspan class="shade">░░░</tspan>██║██████╔╝</text> <text x="500" y="160">██╔══██║██╔══██╗██║<tspan class="shade">░░</tspan>██╗██╔══██║██║<tspan class="shade">░░░</tspan>██║██╔═══╝<tspan class="shade">░</tspan></text> <text x="500" y="200">██║<tspan class="shade">░░</tspan>██║██║<tspan class="shade">░░</tspan>██║╚█████╔╝██║<tspan class="shade">░░</tspan>██║╚██████╔╝██║<tspan class="shade">░░░░░</tspan></text> <text x="500" y="240">╚═╝<tspan class="shade">░░</tspan>╚═╝╚═╝<tspan class="shade">░░</tspan>╚═╝<tspan class="shade">░</tspan>╚════╝<tspan class="shade">░</tspan>╚═╝<tspan class="shade">░░</tspan>╚═╝<tspan class="shade">░</tspan>╚═════╝<tspan class="shade">░</tspan>╚═╝<tspan class="shade">░░░░░</tspan></text></svg>
15- <text x="500" y="80">██╔══██╗██╔══██╗██╔══██╗██║░░██║██║░░░██║██╔══██╗</text>
16- <text x="500" y="120">███████║██████╔╝██║░░╚═╝███████║██║░░░██║██████╔╝</text>
17- <text x="500" y="160">██╔══██║██╔══██╗██║░░██╗██╔══██║██║░░░██║██╔═══╝░</text>
18- <text x="500" y="200">██║░░██║██║░░██║╚█████╔╝██║░░██║╚██████╔╝██║░░░░░</text>
19- <text x="500" y="240">╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝░╚═════╝░╚═╝░░░░░</text>
20-</svg>
A assets/update-svg-shades.py +99 -0
@@ -0,0 +1,99 @@
1+#!/usr/bin/env python3
2+"""
3+Script to update SVG logo by wrapping all '░' characters in tspan elements
4+with a specific color class while keeping other characters unchanged.
5+"""
6+
7+import re
8+import sys
9+
10+def process_svg_line(line):
11+ """
12+ Process a text line in the SVG, wrapping all '░' characters in tspan elements.
13+
14+ Args:
15+ line: A line from the SVG file
16+
17+ Returns:
18+ Modified line with '░' characters wrapped in tspan elements
19+ """
20+ # Check if this is a text element line
21+ if '<text x=' not in line:
22+ return line
23+
24+ # Extract the text content between > and </text>
25+ match = re.match(r'(.*<text[^>]*>)(.*)(</text>.*)', line)
26+ if not match:
27+ return line
28+
29+ prefix, content, suffix = match.groups()
30+
31+ # First, strip any existing tspan elements to get clean text
32+ clean_content = re.sub(r'<tspan[^>]*>(.*?)</tspan>', r'\1', content)
33+
34+ # Split content into segments: shade characters and other characters
35+ segments = []
36+ current_segment = ""
37+ current_is_shade = False
38+
39+ for char in clean_content:
40+ is_shade = (char == '░')
41+
42+ if current_segment == "":
43+ # Start new segment
44+ current_segment = char
45+ current_is_shade = is_shade
46+ elif is_shade == current_is_shade:
47+ # Continue current segment
48+ current_segment += char
49+ else:
50+ # Save current segment and start new one
51+ segments.append((current_segment, current_is_shade))
52+ current_segment = char
53+ current_is_shade = is_shade
54+
55+ # Don't forget the last segment
56+ if current_segment:
57+ segments.append((current_segment, current_is_shade))
58+
59+ # Build the new content with tspan wrappers for shade characters
60+ new_content = ""
61+ for segment, is_shade in segments:
62+ if is_shade:
63+ new_content += f'<tspan class="shade">{segment}</tspan>'
64+ else:
65+ new_content += segment
66+
67+ return prefix + new_content + suffix
68+
69+
70+def main():
71+ input_file = "archup-logo.svg"
72+ output_file = "archup-logo-updated.svg"
73+
74+ try:
75+ with open(input_file, 'r', encoding='utf-8') as f:
76+ lines = f.readlines()
77+
78+ # Process each line
79+ processed_lines = [process_svg_line(line) for line in lines]
80+
81+ # Write output
82+ with open(output_file, 'w', encoding='utf-8') as f:
83+ f.writelines(processed_lines)
84+
85+ print(f"✓ Successfully processed {input_file}")
86+ print(f"✓ Output written to {output_file}")
87+ print(f"\nTo replace the original file, run:")
88+ print(f" mv {output_file} {input_file}")
89+
90+ except FileNotFoundError:
91+ print(f"Error: {input_file} not found", file=sys.stderr)
92+ sys.exit(1)
93+ except Exception as e:
94+ print(f"Error: {e}", file=sys.stderr)
95+ sys.exit(1)
96+
97+
98+if __name__ == "__main__":
99+ main()
@@ -0,0 +1,99 @@
1+#!/usr/bin/env python3
2+"""
3+Script to update SVG logo by wrapping all '░' characters in tspan elements
4+with a specific color class while keeping other characters unchanged.
5+"""
6+
7+import re
8+import sys
9+
10+def process_svg_line(line):
11+ """
12+ Process a text line in the SVG, wrapping all '░' characters in tspan elements.
13+
14+ Args:
15+ line: A line from the SVG file
16+
17+ Returns:
18+ Modified line with '░' characters wrapped in tspan elements
19+ """
20+ # Check if this is a text element line
21+ if '<text x=' not in line:
22+ return line
23+
24+ # Extract the text content between > and </text>
25+ match = re.match(r'(.*<text[^>]*>)(.*)(</text>.*)', line)
26+ if not match:
27+ return line
28+
29+ prefix, content, suffix = match.groups()
30+
31+ # First, strip any existing tspan elements to get clean text
32+ clean_content = re.sub(r'<tspan[^>]*>(.*?)</tspan>', r'\1', content)
33+
34+ # Split content into segments: shade characters and other characters
35+ segments = []
36+ current_segment = ""
37+ current_is_shade = False
38+
39+ for char in clean_content:
40+ is_shade = (char == '░')
41+
42+ if current_segment == "":
43+ # Start new segment
44+ current_segment = char
45+ current_is_shade = is_shade
46+ elif is_shade == current_is_shade:
47+ # Continue current segment
48+ current_segment += char
49+ else:
50+ # Save current segment and start new one
51+ segments.append((current_segment, current_is_shade))
52+ current_segment = char
53+ current_is_shade = is_shade
54+
55+ # Don't forget the last segment
56+ if current_segment:
57+ segments.append((current_segment, current_is_shade))
58+
59+ # Build the new content with tspan wrappers for shade characters
60+ new_content = ""
61+ for segment, is_shade in segments:
62+ if is_shade:
63+ new_content += f'<tspan class="shade">{segment}</tspan>'
64+ else:
65+ new_content += segment
66+
67+ return prefix + new_content + suffix
68+
69+
70+def main():
71+ input_file = "archup-logo.svg"
72+ output_file = "archup-logo-updated.svg"
73+
74+ try:
75+ with open(input_file, 'r', encoding='utf-8') as f:
76+ lines = f.readlines()
77+
78+ # Process each line
79+ processed_lines = [process_svg_line(line) for line in lines]
80+
81+ # Write output
82+ with open(output_file, 'w', encoding='utf-8') as f:
83+ f.writelines(processed_lines)
84+
85+ print(f"✓ Successfully processed {input_file}")
86+ print(f"✓ Output written to {output_file}")
87+ print(f"\nTo replace the original file, run:")
88+ print(f" mv {output_file} {input_file}")
89+
90+ except FileNotFoundError:
91+ print(f"Error: {input_file} not found", file=sys.stderr)
92+ sys.exit(1)
93+ except Exception as e:
94+ print(f"Error: {e}", file=sys.stderr)
95+ sys.exit(1)
96+
97+
98+if __name__ == "__main__":
99+ main()

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 0

    ↑↓ moveenter openesc close