mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-08-02 10:15:58 +08:00
Add blog to docs (#484)
* Adding social card infrastructure * Upgrades doc project to .NET 6 * Adds Playwright * Changes the console to a web project for Playwright * Adds social card template * Added blog content * Parallelized social image processing * Updating CI to use .NET 6 for docs build
This commit is contained in:
113
docs/src/Pipelines/SocialCardPipeline.cs
Normal file
113
docs/src/Pipelines/SocialCardPipeline.cs
Normal file
@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Playwright;
|
||||
using Statiq.Common;
|
||||
using Statiq.Core;
|
||||
using Statiq.Web;
|
||||
using Statiq.Web.Modules;
|
||||
using Statiq.Web.Pipelines;
|
||||
|
||||
namespace Docs.Pipelines
|
||||
{
|
||||
public class SocialImages : Pipeline
|
||||
{
|
||||
public SocialImages()
|
||||
{
|
||||
Dependencies.AddRange(nameof(Inputs));
|
||||
|
||||
ProcessModules = new ModuleList
|
||||
{
|
||||
new GetPipelineDocuments(ContentType.Content),
|
||||
|
||||
// Filter to non-archive content
|
||||
new FilterDocuments(Config.FromDocument(doc => !Archives.IsArchive(doc))),
|
||||
|
||||
// Process the content
|
||||
new CacheDocuments
|
||||
{
|
||||
new AddTitle(),
|
||||
new SetDestination(true),
|
||||
new ExecuteIf(Config.FromSetting(WebKeys.OptimizeContentFileNames, true))
|
||||
{
|
||||
new OptimizeFileName()
|
||||
},
|
||||
new GenerateSocialImage(),
|
||||
}
|
||||
};
|
||||
|
||||
OutputModules = new ModuleList { new WriteFiles() };
|
||||
}
|
||||
}
|
||||
|
||||
class GenerateSocialImage : ParallelModule
|
||||
{
|
||||
private IPlaywright _playwright;
|
||||
private IBrowser _browser;
|
||||
private WebApplication _app;
|
||||
|
||||
protected override async Task BeforeExecutionAsync(IExecutionContext context)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder();
|
||||
builder.Logging.ClearProviders();
|
||||
|
||||
builder.Services
|
||||
.AddRazorPages()
|
||||
.WithRazorPagesRoot("/src/SocialCards/");
|
||||
|
||||
_app = builder.Build();
|
||||
_app.MapRazorPages();
|
||||
_app.UseStaticFiles(new StaticFileOptions
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(
|
||||
Path.Combine(builder.Environment.ContentRootPath, "src/SocialCards")),
|
||||
RequestPath = "/static"
|
||||
});
|
||||
|
||||
await _app.StartAsync().ConfigureAwait(false);
|
||||
|
||||
_playwright = await Playwright.CreateAsync().ConfigureAwait(false);
|
||||
_browser = await _playwright.Chromium.LaunchAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override async Task FinallyAsync(IExecutionContext context)
|
||||
{
|
||||
await _browser.DisposeAsync().ConfigureAwait(false);
|
||||
_playwright.Dispose();
|
||||
await _app.DisposeAsync().ConfigureAwait(false);
|
||||
await base.FinallyAsync(context);
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<IDocument>> ExecuteInputAsync(IDocument input, IExecutionContext context)
|
||||
{
|
||||
var url = _app.Urls.FirstOrDefault(u => u.StartsWith("http://"));
|
||||
var page = await _browser.NewPageAsync(new BrowserNewPageOptions
|
||||
{
|
||||
ViewportSize = new ViewportSize { Width = 1200, Height = 618 },
|
||||
}
|
||||
);
|
||||
|
||||
var title = input.GetString("Title");
|
||||
var description = input.GetString("Description");
|
||||
var highlights = input.GetList<string>("Highlights") ?? Array.Empty<string>();
|
||||
|
||||
await page.GotoAsync($"{url}/?title={title}&desc={description}&highlights={string.Join("||", highlights)}");
|
||||
var bytes = await page.ScreenshotAsync();
|
||||
|
||||
var destination = input.Destination.InsertSuffix("-social").ChangeExtension("png");
|
||||
var doc = context.CreateDocument(
|
||||
input.Source,
|
||||
destination,
|
||||
new MetadataItems { { "DocId", input.Id }},
|
||||
context.GetContentProvider(bytes));
|
||||
|
||||
return new[] { doc };
|
||||
}
|
||||
}
|
||||
}
|
BIN
docs/src/SocialCards/CascadiaCodePL.woff2
Normal file
BIN
docs/src/SocialCards/CascadiaCodePL.woff2
Normal file
Binary file not shown.
120
docs/src/SocialCards/index.cshtml
Normal file
120
docs/src/SocialCards/index.cshtml
Normal file
@ -0,0 +1,120 @@
|
||||
@page
|
||||
@using Markdig
|
||||
@model Docs.SocialCards.SocialCardModel
|
||||
|
||||
@{
|
||||
Layout = null;
|
||||
}
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="static/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container">
|
||||
<div id="console">
|
||||
<div class="line"><span style="color:var(--brightBlack)">╭─</span><span style="color:var(--folder)"></span><span style="background-color:var(--folder);color:var(--black)"> ~/spectre.console</span><span style="color:var(--folder);background-color:var(--dotnet)"></span><span style="background-color:var(--blue)"> .NET 5.0 </span><span style="color:var(--dotnet);background-color:var(--git)"></span><span style="background-color:var(--git);color:var(--background)">  main </span><span style="color:var(--git)"></span></div>
|
||||
<div class="line"><span style="color:var(--brightBlack)">╰─</span> dotnet run</div>
|
||||
<div class="line"></div>
|
||||
<div class="line">╭────────────────────────────────────────────────────────╮</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">│ │</div>
|
||||
<div class="line">╰────────────────────────────────────────────────────────╯</div>
|
||||
|
||||
<div id="title"><span style="color:var(--brightPurple)">@Model.Title</span></div>
|
||||
<div id="content">
|
||||
@if (string.IsNullOrWhiteSpace(Model.Description) == false)
|
||||
{
|
||||
<p>@Html.Raw(Markdown.ToHtml(Model.Description))</p>
|
||||
}
|
||||
@if (string.IsNullOrWhiteSpace(Model.Highlights) == false)
|
||||
{
|
||||
<ul>
|
||||
@foreach (var highlight in Model.Highlights.Split("||"))
|
||||
{
|
||||
<li>@Html.Raw(Markdown.ToHtml(highlight))</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
@if (string.IsNullOrWhiteSpace(Model.Footer) == false)
|
||||
{
|
||||
<div id="footer"><span style="color:var(--brightBlack)">@Html.Raw(@Markdown.ToHtml(@Model.Footer))</span></div>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<svg id="logo" version="1.0" xmlns="http://www.w3.org/2000/svg" width="1270.000000pt" height="1270.000000pt" viewBox="0 0 1270.000000 1270.000000" preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.16, written by Peter Selinger 2001-2019
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,1270.000000) scale(0.100000,-0.100000)" stroke="none">
|
||||
<path d="M799 10610 c-199 -48 -354 -191 -414 -383 l-25 -78 0 -3084 0 -3084
|
||||
25 -79 c45 -141 155 -270 289 -335 124 -61 -80 -57 2819 -57 l2646 0 5 -43 c3
|
||||
-23 8 -71 11 -105 13 -137 88 -334 179 -471 57 -85 187 -219 247 -254 25 -15
|
||||
76 -34 112 -43 87 -22 163 -7 246 46 120 78 195 211 234 411 l23 124 14 -55
|
||||
c63 -263 172 -511 326 -741 94 -142 229 -291 313 -348 272 -185 583 -197 750
|
||||
-30 66 67 84 109 89 215 4 90 4 91 -51 230 -108 276 -137 477 -122 868 l7 196
|
||||
77 0 c55 0 118 -11 229 -39 l154 -38 50 -84 c103 -172 221 -427 277 -599 38
|
||||
-120 70 -274 86 -412 8 -75 21 -155 29 -178 37 -106 117 -199 220 -253 51 -26
|
||||
202 -35 283 -17 83 18 193 97 268 192 157 199 256 485 286 825 11 122 6 524
|
||||
-7 583 -5 24 -1 26 62 43 64 16 67 16 80 0 39 -50 109 -215 149 -351 25 -85
|
||||
55 -174 67 -199 73 -156 261 -206 441 -117 65 32 110 70 159 135 128 169 178
|
||||
414 157 764 -8 143 -38 350 -55 376 -2 4 7 25 22 46 77 112 168 344 200 504
|
||||
l16 86 87 28 c188 60 391 170 498 269 132 122 183 230 183 383 0 71 -5 98 -24
|
||||
138 -24 52 -82 112 -138 141 -52 28 -205 30 -378 5 -80 -11 -179 -23 -220 -27
|
||||
l-75 -6 -29 56 c-33 65 -137 182 -211 236 -75 55 -156 94 -382 181 -110 43
|
||||
-221 87 -245 100 -54 27 -92 69 -125 138 -25 52 -26 59 -20 180 4 69 16 200
|
||||
26 291 52 430 53 809 5 1170 -54 405 -249 740 -569 979 -136 102 -297 190
|
||||
-419 231 l-36 12 0 433 c0 433 0 434 -25 512 -52 167 -171 292 -341 360 l-69
|
||||
28 -4215 2 c-2318 0 -4231 -3 -4251 -7z m8363 -1476 c417 -53 735 -193 962
|
||||
-423 98 -98 155 -175 210 -282 84 -160 117 -292 141 -559 28 -313 17 -684 -30
|
||||
-1025 -9 -60 -18 -164 -22 -230 -10 -208 22 -314 136 -452 76 -91 124 -118
|
||||
391 -218 307 -116 377 -155 450 -249 23 -31 41 -58 39 -60 -2 -2 -47 8 -99 21
|
||||
-131 35 -268 36 -360 3 -132 -47 -248 -116 -364 -218 -163 -143 -516 -488
|
||||
-703 -687 -350 -372 -504 -514 -701 -644 -348 -231 -878 -408 -1322 -442 -409
|
||||
-31 -796 45 -1059 208 -111 69 -249 210 -292 298 -32 65 -34 76 -33 165 1 104
|
||||
23 178 85 287 75 131 137 194 430 441 181 152 251 295 250 511 -1 152 -16 223
|
||||
-117 560 -35 117 -61 217 -58 222 3 5 20 9 38 9 55 0 217 31 261 50 53 23 103
|
||||
73 132 131 43 88 56 187 59 437 2 266 -1 258 91 292 108 40 254 21 330 -45 35
|
||||
-30 35 -32 53 -170 41 -311 106 -484 206 -546 48 -29 168 -48 381 -59 188 -10
|
||||
432 -1 548 20 76 14 206 56 266 86 64 32 122 101 144 170 15 49 17 82 12 253
|
||||
-5 198 -27 398 -52 482 -42 146 -125 221 -290 265 -57 15 -108 19 -268 19
|
||||
l-197 0 0 45 c0 120 -37 255 -82 300 -76 77 -210 5 -291 -157 -31 -60 -67
|
||||
-184 -67 -229 0 -27 -6 -34 -41 -50 -65 -29 -159 -98 -195 -144 -34 -43 -67
|
||||
-119 -79 -181 l-6 -35 -57 28 c-114 57 -270 58 -379 2 -61 -31 -70 -21 -49 54
|
||||
33 118 16 442 -29 536 -38 79 -114 84 -188 12 -68 -66 -136 -230 -137 -330 l0
|
||||
-29 -61 7 c-34 3 -93 6 -131 6 l-69 0 6 48 c14 97 56 282 84 368 155 475 486
|
||||
821 963 1008 108 42 308 94 430 110 62 9 124 17 138 20 76 11 479 5 592 -10z
|
||||
m-7029 -78 c18 -8 261 -243 569 -552 582 -584 560 -559 543 -651 -6 -33 -69
|
||||
-101 -523 -557 -553 -554 -564 -564 -644 -551 -89 15 -151 110 -128 198 10 37
|
||||
65 95 463 495 l452 452 -472 473 c-414 414 -472 477 -478 510 -25 132 98 235
|
||||
218 183z m7169 -1405 c164 -57 201 -136 234 -502 37 -414 9 -486 -212 -558
|
||||
-155 -50 -298 -64 -579 -57 -249 6 -398 23 -439 50 -95 62 -177 346 -180 621
|
||||
-1 135 0 142 28 203 50 109 148 179 304 218 149 37 329 53 567 50 191 -2 216
|
||||
-4 277 -25z m-2002 -174 c95 -34 118 -52 152 -114 52 -94 63 -159 62 -368 -1
|
||||
-358 -44 -479 -187 -520 -146 -42 -612 -65 -727 -36 -153 38 -196 98 -226 316
|
||||
-16 120 -31 487 -21 527 9 35 89 121 140 151 99 58 228 76 522 73 200 -2 214
|
||||
-3 285 -29z m-1604 -443 c45 -33 67 -70 71 -121 5 -59 -25 -117 -77 -147 -35
|
||||
-21 -47 -21 -980 -24 -520 -2 -964 0 -988 3 -57 8 -116 60 -130 115 -19 75 12
|
||||
146 78 182 34 17 75 18 1017 16 974 -3 982 -3 1009 -24z m5329 -2140 c66 -7
|
||||
173 -14 237 -14 103 0 146 5 247 26 24 5 24 5 18 -64 -15 -159 -89 -371 -180
|
||||
-515 l-43 -68 -57 113 c-72 145 -160 261 -318 422 l-126 128 51 -7 c28 -3 105
|
||||
-13 171 -21z m-812 -652 c53 -41 140 -115 193 -165 96 -91 224 -231 224 -245
|
||||
0 -5 -30 -18 -67 -30 -79 -25 -305 -84 -308 -80 -1 2 -12 53 -24 113 -28 135
|
||||
-70 268 -127 402 -24 57 -44 106 -44 109 0 9 43 -20 153 -104z m-1173 -560
|
||||
c-9 -4 -271 61 -315 78 -29 11 -28 12 79 55 59 24 111 46 114 49 3 3 33 -36
|
||||
67 -87 34 -50 59 -93 55 -95z" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
31
docs/src/SocialCards/index.cshtml.cs
Normal file
31
docs/src/SocialCards/index.cshtml.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Docs.SocialCards{
|
||||
public class SocialCardModel : PageModel
|
||||
{
|
||||
[BindProperty(Name = "title", SupportsGet = true)]
|
||||
public string Title { get; set; }
|
||||
|
||||
[BindProperty(Name = "desc", SupportsGet = true)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[BindProperty(Name = "highlights", SupportsGet = true)]
|
||||
public string Highlights { get; set; }
|
||||
|
||||
[BindProperty(Name = "footer", SupportsGet = true)]
|
||||
public string Footer { get; set; }
|
||||
|
||||
private readonly ILogger<SocialCardModel> _logger;
|
||||
|
||||
public SocialCardModel(ILogger<SocialCardModel> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
148
docs/src/SocialCards/styles.css
Normal file
148
docs/src/SocialCards/styles.css
Normal file
@ -0,0 +1,148 @@
|
||||
@font-face {
|
||||
font-family: 'CascadiaCodePL';
|
||||
src: url('CascadiaCodePL.woff2') format('woff2');
|
||||
}
|
||||
|
||||
* {
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
:root {
|
||||
--height: 618px;
|
||||
--width:1200px;
|
||||
--line-height: 39px;
|
||||
--padding: 20px;
|
||||
--rows: calc((--var(--height) - var(--padding) * 2) / var(--line-height));
|
||||
--background: #1E2127;
|
||||
--black: #000000;
|
||||
--blue: #61AFEF;
|
||||
--brightBlack: #5C6370;
|
||||
--brightBlue: #61AFEF;
|
||||
--brightCyan: #56B6C2;
|
||||
--brightGreen: #98C379;
|
||||
--brightPurple: #C678DD;
|
||||
--brightRed: #E06C75;
|
||||
--brightWhite: #FFFFFF;
|
||||
--brightYellow: #D19A66;
|
||||
--cyan: #56B6C2;
|
||||
--foreground: #5C6370;
|
||||
--green: #98C379;
|
||||
--purple: #C678DD;
|
||||
--red: #E06C75;
|
||||
--white: #ABB2BF;
|
||||
--yellow: #D19A66;
|
||||
--folder: var(--yellow);
|
||||
--dotnet: var(--blue);
|
||||
--git: var(--green);
|
||||
}
|
||||
|
||||
|
||||
body{
|
||||
font-family:'CascadiaCodePL',monospace;
|
||||
font-weight:400;
|
||||
font-size: calc(var(--line-height) - 5px);
|
||||
}
|
||||
|
||||
#container {
|
||||
background-color: var(--background);
|
||||
color: #fff;
|
||||
width: calc(var(--width) - var(--padding) * 2);
|
||||
height: calc(var(--height) - var(--padding) * 2);
|
||||
padding:var(--padding);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#console{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.line{
|
||||
height:var(--line-height);
|
||||
width:100%;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#title{
|
||||
position: absolute;
|
||||
left: 3ch;
|
||||
top: calc(3 * var(--line-height));
|
||||
margin: 0 -3px;
|
||||
padding: 0 3px;
|
||||
background:var(--background);
|
||||
z-index:4;
|
||||
}
|
||||
|
||||
#content{
|
||||
position: absolute;
|
||||
left: 3ch;
|
||||
top: calc(5 * var(--line-height));;
|
||||
height:calc(var(--height) - 7 * var(--line-height));
|
||||
width: 53ch;
|
||||
line-height:var(--line-height);
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
#content p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#content p + ul {
|
||||
margin-top:var(--line-height);
|
||||
}
|
||||
|
||||
#content strong {
|
||||
color: var(--yellow);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#content em, #content i {
|
||||
color: var(--blue);
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#content ul {
|
||||
list-style: "*";
|
||||
margin-left: 1ch;
|
||||
}
|
||||
|
||||
#content ul li {
|
||||
padding-left:1ch;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#footer{
|
||||
position: absolute;
|
||||
top: calc(var(--height) - var(--padding) - var(--line-height) * 3);
|
||||
left : 3ch;
|
||||
background:var(--background);
|
||||
width:51ch;
|
||||
z-index:4;
|
||||
}
|
||||
|
||||
#logo{
|
||||
height:calc(var(--line-height) * 2.5);
|
||||
width:calc(var(--line-height) * 2.5);
|
||||
position:absolute;
|
||||
right:2ch;
|
||||
top:calc(var(--padding) / 2);
|
||||
fill: var(--white);
|
||||
opacity:.4;
|
||||
}
|
||||
|
||||
#container::before {
|
||||
/* fake scan lines */
|
||||
content: " ";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
|
||||
z-index: 200;
|
||||
background-size: 100% 4px, 5px 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
Reference in New Issue
Block a user