update previews
This commit is contained in:
parent
faa9599849
commit
a86e79d652
2 changed files with 1896 additions and 31 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -14,6 +14,7 @@ defmodule ZoeyscomputerWeb.GistLive.OgImage do
|
||||||
@code_start_x 80
|
@code_start_x 80
|
||||||
@font_size 24
|
@font_size 24
|
||||||
@char_width 12
|
@char_width 12
|
||||||
|
@space_width @char_width
|
||||||
|
|
||||||
defp font_face_styles do
|
defp font_face_styles do
|
||||||
"""
|
"""
|
||||||
|
|
@ -52,24 +53,32 @@ defmodule ZoeyscomputerWeb.GistLive.OgImage do
|
||||||
font-family: 'Iosevka' !important;
|
font-family: 'Iosevka' !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.background { fill: #0D1117; }
|
/* Catppuccin Macchiato Theme Colors */
|
||||||
.title { fill: #ffffff; font-family: system-ui, -apple-system, sans-serif; }
|
.background { fill: #24273a; } /* base */
|
||||||
.description { fill: #8B949E; font-family: system-ui, -apple-system, sans-serif; }
|
.title { fill: #cad3f5; font-family: system-ui, -apple-system, sans-serif; } /* text */
|
||||||
.code-background { fill: #161B22; }
|
.description { fill: #8087a2; font-family: system-ui, -apple-system, sans-serif; } /* overlay1 */
|
||||||
|
.code-background { fill: #1e2030; } /* crust */
|
||||||
|
|
||||||
/* Syntax Highlighting Colors */
|
/* Syntax Highlighting Colors - Catppuccin Macchiato */
|
||||||
.c, .cm, .cp, .c1, .cs { fill: #768390; } /* Comment */
|
.c, .cm, .cp, .c1, .cs { fill: #8087a2; } /* Comment - overlay1 */
|
||||||
.k, .kc, .kd, .kn, .kp, .kr, .kt { fill: #f47067; } /* Keyword */
|
.k, .kc, .kd, .kn, .kp, .kr, .kt { fill: #c6a0f6; } /* Keyword - mauve */
|
||||||
.s, .sb, .sc, .sd, .s2, .se, .sh, .si, .sx, .sr, .s1, .ss { fill: #96d0ff; } /* String */
|
.s, .sb, .sc, .sd, .s2, .se, .sh, .si, .sx, .sr, .s1, .ss { fill: #a6da95; } /* String - green */
|
||||||
.n, .na, .nc, .no, .nd, .ni, .ne, .nf, .nl, .nn, .nx, .py, .nt, .nv, .vc, .vg, .vi { fill: #adbac7; } /* Name */
|
.n, .na, .nc, .no, .nd, .ni, .ne, .nf, .nl, .nn, .nx, .py, .nt, .nv, .vc, .vg, .vi { fill: #8aadf4; } /* Name - blue */
|
||||||
.nb, .bp { fill: #f69d50; } /* Built-in */
|
.nb, .bp { fill: #f5a97f; } /* Built-in - peach */
|
||||||
.m, .mf, .mh, .mi, .mo, .il { fill: #6cb6ff; } /* Number */
|
.m, .mf, .mh, .mi, .mo, .il { fill: #f5bde6; } /* Number - pink */
|
||||||
.o, .ow { fill: #f47067; } /* Operator */
|
.o, .ow { fill: #91d7e3; } /* Operator - sky */
|
||||||
.p { fill: #adbac7; } /* Punctuation */
|
.p { fill: #cad3f5; } /* Punctuation - text */
|
||||||
.w { fill: #E6EDF3; } /* Whitespace */
|
.w { fill: #cad3f5; } /* Whitespace - text */
|
||||||
.l { fill: #6cb6ff; } /* Literal */
|
.l { fill: #8aadf4; } /* Literal - blue */
|
||||||
.default { fill: #E6EDF3; } /* Default text color */
|
.default { fill: #cad3f5; } /* Default text color - text */
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Gradient definition -->
|
||||||
|
<linearGradient id="fade" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stop-color="#1e2030" stop-opacity="0"/>
|
||||||
|
<stop offset="50%" stop-color="#1e2030" stop-opacity="0"/>
|
||||||
|
<stop offset="100%" stop-color="#181926" stop-opacity="1"/>
|
||||||
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
<!-- Background -->
|
<!-- Background -->
|
||||||
|
|
@ -85,12 +94,15 @@ defmodule ZoeyscomputerWeb.GistLive.OgImage do
|
||||||
</text>
|
</text>
|
||||||
|
|
||||||
<!-- Code Preview Background -->
|
<!-- Code Preview Background -->
|
||||||
<rect x="60" y="160" width="1080" height="420" class="code-background" rx="8"/>
|
<rect x="60" y="160" width="1080" height="600" class="code-background" rx="8"/>
|
||||||
|
|
||||||
<!-- Code Content -->
|
<!-- Code Content -->
|
||||||
<g font-family="Iosevka" font-size="#{@font_size}">
|
<g font-family="Iosevka" font-size="#{@font_size}">
|
||||||
#{code_lines}
|
#{code_lines}
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
|
<!-- Gradient Overlay -->
|
||||||
|
<rect x="0" y="160" width="1200" height="600" fill="url(#fade)" rx="8"/>
|
||||||
</svg>
|
</svg>
|
||||||
"""
|
"""
|
||||||
end
|
end
|
||||||
|
|
@ -100,43 +112,64 @@ defmodule ZoeyscomputerWeb.GistLive.OgImage do
|
||||||
|> String.split("\n")
|
|> String.split("\n")
|
||||||
|> Enum.with_index()
|
|> Enum.with_index()
|
||||||
|> Enum.map_join("\n", fn {line, index} ->
|
|> Enum.map_join("\n", fn {line, index} ->
|
||||||
|
indent_level = calculate_indent_level(line)
|
||||||
y_position = @code_start_y + index * @line_height
|
y_position = @code_start_y + index * @line_height
|
||||||
render_line(String.trim(line), y_position)
|
render_line(String.trim_leading(line), y_position, indent_level)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp render_line("", _y_position), do: ""
|
defp calculate_indent_level(line) do
|
||||||
|
leading_spaces =
|
||||||
|
line
|
||||||
|
|> String.replace(~r/^(\s+).*$/, "\\1")
|
||||||
|
|> String.length()
|
||||||
|
|
||||||
defp render_line(line, y_position) do
|
div(leading_spaces, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp render_line("", _y_position, _indent), do: ""
|
||||||
|
|
||||||
|
defp render_line(line, y_position, indent_level) do
|
||||||
spans = parse_spans(line)
|
spans = parse_spans(line)
|
||||||
|
indent_offset = indent_level * 2 * @space_width
|
||||||
|
|
||||||
spans
|
spans
|
||||||
|> Enum.reduce({[], 0}, fn {content, class}, {spans, x_offset} ->
|
|> Enum.reduce({[], indent_offset}, fn {content, class}, {spans, x_offset} ->
|
||||||
span = render_span(content, class, x_offset, y_position)
|
unescaped_content = unescape_html(content)
|
||||||
{[span | spans], x_offset + String.length(content)}
|
span = render_span(unescaped_content, class, x_offset, y_position)
|
||||||
|
{[span | spans], x_offset + String.length(unescaped_content) * @char_width}
|
||||||
end)
|
end)
|
||||||
|> elem(0)
|
|> elem(0)
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|> Enum.join("\n")
|
|> Enum.join("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp unescape_html(text) do
|
||||||
|
text
|
||||||
|
|> String.replace("&", "&")
|
||||||
|
|> String.replace("<", "<")
|
||||||
|
|> String.replace(">", ">")
|
||||||
|
|> String.replace(""", "\"")
|
||||||
|
|> String.replace("'", "'")
|
||||||
|
|> String.replace("'", "'")
|
||||||
|
|> String.replace("/", "/")
|
||||||
|
|> String.replace("/", "/")
|
||||||
|
|> String.replace(" ", " ")
|
||||||
|
end
|
||||||
|
|
||||||
defp parse_spans(""), do: []
|
defp parse_spans(""), do: []
|
||||||
|
|
||||||
defp parse_spans(line) do
|
defp parse_spans(line) do
|
||||||
# Handle non-span text first
|
|
||||||
line
|
line
|
||||||
|> String.split(~r{(<span.*?>|</span>)}, include_captures: true)
|
|> String.split(~r{(<span.*?>|</span>)}, include_captures: true)
|
||||||
|> Enum.reduce({[], nil}, fn
|
|> Enum.reduce({[], nil}, fn
|
||||||
# Opening span tag
|
|
||||||
<<"<span class=\"", rest::binary>>, {acc, nil} ->
|
<<"<span class=\"", rest::binary>>, {acc, nil} ->
|
||||||
class = rest |> String.replace_suffix("\">", "")
|
class = rest |> String.replace_suffix("\">", "")
|
||||||
{acc, class}
|
{acc, class}
|
||||||
|
|
||||||
# Closing span tag
|
|
||||||
"</span>", {acc, _class} ->
|
"</span>", {acc, _class} ->
|
||||||
{acc, nil}
|
{acc, nil}
|
||||||
|
|
||||||
# Content within or outside spans
|
|
||||||
content, {acc, class} when byte_size(content) > 0 ->
|
content, {acc, class} when byte_size(content) > 0 ->
|
||||||
{[{content, class || "default"} | acc], class}
|
{[{content, class || "default"} | acc], class}
|
||||||
|
|
||||||
|
|
@ -148,8 +181,10 @@ defmodule ZoeyscomputerWeb.GistLive.OgImage do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp render_span(content, class, x_offset, y_position) when byte_size(content) > 0 do
|
defp render_span(content, class, x_offset, y_position) when byte_size(content) > 0 do
|
||||||
x = @code_start_x + x_offset * @char_width
|
x = @code_start_x + x_offset
|
||||||
"<text x=\"#{x}\" y=\"#{y_position}\" class=\"#{class}\">#{escape_text(content)}</text>"
|
# Re-escape the content for the SVG output
|
||||||
|
safe_content = escape_text(content)
|
||||||
|
"<text x=\"#{x}\" y=\"#{y_position}\" class=\"#{class}\">#{safe_content}</text>"
|
||||||
end
|
end
|
||||||
|
|
||||||
defp render_span(_, _, _, _), do: ""
|
defp render_span(_, _, _, _), do: ""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue