Skip to content

Commit

Permalink
Feature/improve image processing (#117)
Browse files Browse the repository at this point in the history
* Keep only generated images in production

* Remove necessity of processing images on local
  • Loading branch information
robinsonzimmermann authored May 2, 2024
1 parent 17080e0 commit 0e545e2
Show file tree
Hide file tree
Showing 30 changed files with 302 additions and 133 deletions.
23 changes: 22 additions & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"src/assets",
{
"glob": "**/*.*",
"input": "content/authors/avatars/dist",
"input": "content/authors/avatars",
"output": "/authors"
},
{
Expand Down Expand Up @@ -79,6 +79,27 @@
"maximumError": "6kb"
}
],
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "**/*.*",
"input": "content/authors/avatars",
"output": "/authors",
"ignore": ["*.*"]
},
{
"glob": "**/*.*",
"input": "content/posts",
"output": "/",
"ignore": ["**/assets/*.*"]
},
{
"glob": "authors.json",
"input": "content/authors",
"output": "/"
}
],
"outputHashing": "all"
},
"development": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ First, you need a base, if you have no work experience with production Kubernete

Here some nice intros:

![The illustrated Children’s Guide to Kubernetes](https://www.youtube.com/embed/4ht22ReBjno)
<iframe width="560" height="315" src="https://www.youtube.com/embed/4ht22ReBjno?si=2oahPZeHL9Ae8N5m" title="The illustrated Children’s Guide to Kubernetes" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

![Kubernetes explained](https://www.youtube.com/embed/aSrqRSk43lY)
<iframe width="560" height="315" src="https://www.youtube.com/embed/aSrqRSk43lY?si=PDEbpNpT_9ZwonKp" title="Kubernetes explained" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

For something more academic I would recommend following the course:

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"scripts": {
"ng": "ng",
"prestart": "npm run posts:update && npm run images:authors && npm run images:posts && npm run build:utils",
"prestart": "npm run posts:update && npm run build:utils",
"start": "ng serve",
"prebuild": "npm run posts:update && npm run images:authors && npm run images:posts",
"build": "ng build",
Expand Down
10 changes: 8 additions & 2 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ApplicationConfig,
SecurityContext,
importProvidersFrom,
isDevMode,
} from '@angular/core';
import { provideRouter, withInMemoryScrolling } from '@angular/router';

Expand All @@ -13,8 +14,9 @@ import { MarkdownModule, MarkdownService } from 'ngx-markdown';
import { HttpClient, provideHttpClient, withFetch } from '@angular/common/http';
import markdownConfig from './markdown.config';
import { DOCUMENT } from '@angular/common';
import { AUTHORS_AVATAR_PATH_TOKEN } from './core/config/configuration-tokens';
import { HtmlInMarkdownService } from './core/services/html-in-markdown.service';
import { AssetsService } from './core/services/assets.service';
import { AUTHORS_AVATAR_PATH_TOKEN, USE_PROCESSED_IMAGES } from './core/config/configuration-tokens';

export const appConfig: ApplicationConfig = {
providers: [
Expand All @@ -37,11 +39,15 @@ export const appConfig: ApplicationConfig = {
{
provide: APP_INITIALIZER,
useFactory: markdownConfig,
deps: [MarkdownService, DOCUMENT, HtmlInMarkdownService],
deps: [MarkdownService, DOCUMENT, HtmlInMarkdownService, AssetsService],
},
{
provide: AUTHORS_AVATAR_PATH_TOKEN,
useValue: 'authors',
},
{
provide: USE_PROCESSED_IMAGES,
useValue: !isDevMode(),
}
],
};
6 changes: 4 additions & 2 deletions src/app/components/author/author.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
lg: size === 'lg',
muted: muted
}">
<div
<blog-avatar
class="author__avatar"
[ngStyle]="{ 'background-image': 'url(' + imagePath + ')' }"></div>
[url]="author.displayAvatar?.[size]"
format="circle"
></blog-avatar>
<div class="author__details">
<div class="author__fullname">{{ author.fullname }}</div>
@if (size === 'lg') {
Expand Down
8 changes: 0 additions & 8 deletions src/app/components/author/author.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@
&__avatar {
width: 1.2rem;
height: 1.2rem;
min-width: 1.2rem;
border-radius: 100rem;
background-size: cover;
background-position: center;

img {
width: 100%;
}
}
&__fullname {
font-weight: 500;
Expand Down
14 changes: 5 additions & 9 deletions src/app/components/author/author.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Component, Inject, Input } from '@angular/core';
import { Component, Input } from '@angular/core';
import { Author } from '../../core/model/author.model';
import { NgClass, NgStyle } from '@angular/common';
import { AUTHORS_AVATAR_PATH_TOKEN } from '../../core/config/configuration-tokens';
import { RouterLink } from '@angular/router';
import { ImageSize } from '../../core/model/content.model';
import { AvatarComponent } from '../avatar/avatar.component';

@Component({
selector: 'blog-author',
standalone: true,
imports: [NgStyle, NgClass, RouterLink],
imports: [NgStyle, NgClass, RouterLink, AvatarComponent],
templateUrl: './author.component.html',
styleUrl: './author.component.scss',
})
Expand All @@ -24,14 +25,9 @@ export class AuthorComponent {
this.author = value;
}
}
@Input() size: string = 'sm';
@Input() size: ImageSize = 'sm';
@Input() muted = false;

author!: Author;

get imagePath() {
return `${this.basePath}/${this.size}/${this.author.avatar}`;
}

constructor(@Inject(AUTHORS_AVATAR_PATH_TOKEN) protected basePath: string) {}
}
47 changes: 43 additions & 4 deletions src/app/components/avatar/avatar.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,43 @@
<img
[src]="'authors/lg/' + url"
onerror="this.src='authors/lg/placeholder.jpg'"
alt="avatar" />
<div class="avatar avatar__{{format}}" [ngClass]="{ 'avatar__shadow': shadow }">
@if (placeholder) {
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="483" height="483"
viewBox="0 0 878.63037 483" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<circle id="fff0188c-9915-4c0d-8339-9317a77083e8" data-name="Ellipse 276" cx="441.8526"
cy="99.21067" r="70.6659" fill="#DDDEE0" />
<path id="ac220ed6-7c3f-4d1e-8d82-3295770c496a-5146" data-name="Path 1461"
d="M668.54008,246.746a81.61376,81.61376,0,0,0-46.43-35.49166l-8.6754,6.33079v-8.22035a75.12281,75.12281,0,0,0-14.03207-.81741l-7.48468,6.7722V209.11a80.83444,80.83444,0,0,0-55.76328,33.16889c-16.25407,23.43225-18.99783,56.03165-3.01076,79.65191,4.38811-13.48715,9.71486-26.14193,14.1043-39.62775a39.91571,39.91571,0,0,0,10.39873.05039l5.339-12.45857,1.49177,11.93136c16.54971-1.44138,41.0963-4.60742,56.785-7.50784l-1.52581-9.15355,9.12769,7.606c4.80635-1.10624,7.66041-2.11028,7.42476-2.87726,11.66844,18.81119,25.94847,30.82566,37.61558,49.63682C678.33663,293.0056,683.43725,270.95065,668.54008,246.746Z"
transform="translate(-160.68481 -208.5)" fill="#919294" />
<path
d="M754.51974,489.43043c-2.43-14.61929-4.93649-29.51921-11.73089-42.68893-4.46552-8.62629-11.55394-16.84664-21.1096-18.55231a20.4215,20.4215,0,0,1-5.49659-1.27245c-2.79985-1.34871-40.42516-22.82733-46.40535-26.56828-5.13471-3.21152-13.24023-9.158-17.32725-9.158-4.11163-.09038-19.87765,3.579-81.41374-1.23129,0,0-16.90485,6.66319-29.98543,14.74285-.19823-.13063-63.869,34.06031-66.261,33.97034-4.53005-.19075-8.74079,2.70971-11.33775,6.36219-2.5963,3.65239-3.81429,8.174-5.08948,12.54576,13.90677,30.97,26.6308,61.97961,40.5389,92.94963a7.93068,7.93068,0,0,1,1.00579,3.81454,9.30964,9.30964,0,0,1-1.7302,3.81453c-6.82034,10.95592-6.60348,24.736-5.85845,37.61284.74569,12.87686,1.66766,26.47839-4.087,38.02019-1.56523,3.16878-3.60075,6.06924-5.08948,9.238-3.48634,7.17681-4.74624,30.13086-2.71,37.84166l255.12065,7.30869C730.06748,673.1021,754.51974,489.43043,754.51974,489.43043Z"
transform="translate(-160.68481 -208.5)" fill="#AEAFB0" />
<path id="bb46eb08-8e3e-4ac5-913b-26d221d967b9-5147" data-name="Path 1421"
d="M436.31023,551.90313a45.04293,45.04293,0,0,0-.15258,11.10851l3.65653,52.51275c.34331,4.94938.68117,9.88653,1.14573,14.82359.87734,9.58136,2.18792,19.08639,3.81455,28.57778a5.08966,5.08966,0,0,0,5.21639,4.94937c16.096,3.40585,32.72612,3.26965,49.15321,2.34185,25.067-1.39909,89.1978-4.0461,93.11589-9.13583s1.63483-13.32231-3.474-17.43793-89.73865-14.14932-89.73865-14.14932c.82693-6.55285,3.32139-12.72429,5.68777-18.946,4.25049-11.03491,8.22035-22.43228,8.29664-34.2533s-4.37719-24.24962-14.0607-31.02182c-7.9656-5.5597-18.22129-6.591-27.928-6.3621-7.06238.203-19.26485-1.48907-25.71553,1.27245C440.22288,538.431,437.26387,546.90479,436.31023,551.90313Z"
transform="translate(-160.68481 -208.5)" fill="#DFE0E2" />
<path id="efe93a1e-ccdd-49fd-af5f-e26394aa0937-5148" data-name="Path 1430"
d="M457.62676,458.523a13.16962,13.16962,0,0,0-2.82413,4.51753A213.58786,213.58786,0,0,0,436.862,536.35613a7.32926,7.32926,0,0,1-.82693,3.55028,15.53466,15.53466,0,0,1-1.87049,2.023,7.02422,7.02422,0,0,0,.84,9.89817q.17346.1463.35609.28121c2.09937-3.95082,7.125-5.24231,11.59215-5.58556,21.38872-1.692,42.28155,8.25852,63.73432,7.50784-1.51355-5.23-3.69057-10.25571-4.92486-15.54841-5.4589-23.50169,8.15632-49.08916-.19073-71.72579-1.6675-4.52979-4.45348-8.98325-8.84294-10.96818a23.55527,23.55527,0,0,0-5.66189-1.49858c-5.42075-.97952-16.21183-5.166-21.45275-3.48622-1.93452.624-2.69742,2.44268-4.3009,3.54209C462.87722,455.90186,459.64576,456.474,457.62676,458.523Z"
transform="translate(-160.68481 -208.5)" fill="#AEAFB0" />
<path id="a38c3c09-000b-42b7-8619-0229d8aff5e9-5149" data-name="Path 1421"
d="M754.67242,536.1831c-6.45068-2.76152-18.65315-1.06948-25.71553-1.27245-9.70666-.22892-19.96235.8024-27.928,6.3621-9.68351,6.7722-14.137,19.2008-14.0607,31.02182s4.04615,23.21839,8.29664,34.2533c2.36638,6.22174,4.86084,12.39318,5.68777,18.946,0,0-84.62988,10.0337-89.73865,14.14932s-7.39205,12.34819-3.474,17.43793,126.17305,10.19983,142.2691,6.794a5.08966,5.08966,0,0,0,5.21639-4.94937c1.62663-9.49139,2.93721-18.99642,3.81455-28.57778.46456-4.93706.80242-9.87421,1.14573-14.82359l3.65653-52.51275a45.04293,45.04293,0,0,0-.15258-11.10851C762.73613,546.90479,759.77712,538.431,754.67242,536.1831Z"
transform="translate(-160.68481 -208.5)" fill="#DFE0E2" />
<path id="bd3879bf-5d05-49be-b690-c4d97e29a2ab-5150" data-name="Path 1430"
d="M734.68691,454.346c-1.60348-1.09941-2.36638-2.91813-4.3009-3.54209-5.24092-1.67976-16.032,2.5067-21.45275,3.48622a23.55527,23.55527,0,0,0-5.66189,1.49858c-4.38946,1.98493-7.17544,6.43839-8.84294,10.96818-8.34705,22.63663,5.26817,48.2241-.19073,71.72579-1.23429,5.2927-3.41131,10.3184-4.92486,15.54841,21.45277.75068,42.3456-9.19987,63.73432-7.50784,4.46712.34325,9.49278,1.63474,11.59215,5.58556q.18253-.13482.35609-.28121a7.02422,7.02422,0,0,0,.84005-9.89817,15.53466,15.53466,0,0,1-1.87049-2.023,7.32926,7.32926,0,0,1-.82693-3.55028,213.58786,213.58786,0,0,0-17.94066-73.31562,13.16962,13.16962,0,0,0-2.82413-4.51753C740.35424,456.474,737.12278,455.90186,734.68691,454.346Z"
transform="translate(-160.68481 -208.5)" fill="#AEAFB0" />
<path
d="M741.57233,690.28819H479.54154a11.55237,11.55237,0,0,1-11.53931-11.53864V519.78292a11.55237,11.55237,0,0,1,11.53931-11.53864H741.57233a11.55237,11.55237,0,0,1,11.5393,11.53864V678.74955A11.55237,11.55237,0,0,1,741.57233,690.28819Z"
transform="translate(-160.68481 -208.5)" fill="#999A9C" />
<path
d="M537.55552,334.04923h0c-11.3546,0-20.55934-9.95244-20.55934-22.22945h0V300.705c0-12.277,9.20473-22.22945,20.55933-22.22945h0v55.57369Z"
transform="translate(-160.68481 -208.5)" fill="#AEAFB0" />
<path
d="M668.77923,278.47558h0c11.35461,0,20.55935,9.95245,20.55935,22.22943v11.11477c0,12.277-9.20472,22.22945-20.55935,22.22945h0V278.47558Z"
transform="translate(-160.68481 -208.5)" fill="#AEAFB0" />
<path
d="M679.55259,302.45164h-3.262c0-44.73-33.65638-81.12069-75.026-81.12069-41.36939,0-75.02605,36.3907-75.02605,81.12069h-3.262c0-46.6749,35.11988-84.64766,78.288-84.64766C644.433,217.804,679.55259,255.77677,679.55259,302.45164Z"
transform="translate(-160.68481 -208.5)" fill="#AEAFB0" />
</g>
</svg>
} @else {
<img [src]="url" #avatar alt="avatar" />
}
</div>
55 changes: 35 additions & 20 deletions src/app/components/avatar/avatar.component.scss
Original file line number Diff line number Diff line change
@@ -1,28 +1,43 @@
:host {
aspect-ratio: 1;
.avatar {
position: relative;
line-height: 1;
margin-right: 1rem;
margin-bottom: 1rem;
display: inline-flex;
width: 100%;
height: 100%;

&__circle {
img, svg, &::before {
border-radius: 100rem;
}
}

&::before {
content: '';
background: repeating-linear-gradient(
55deg,
var(--blog-palette-accent),
var(--blog-palette-accent) 5px,
transparent 5px,
transparent 10px
);
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
transform: translate(1rem, 1rem);
&__shadow {
&::before {
content: '';
background: repeating-linear-gradient(
55deg,
var(--blog-palette-accent),
var(--blog-palette-accent) 5px,
transparent 5px,
transparent 10px
);
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
transform: translate(8%, 8%);
}
}

img {
img, svg {
position: relative;
background: var(--blog-palette-neutral);
width: 100%;
height: 100%;
}

svg > * {
opacity: .5;
}
}
25 changes: 20 additions & 5 deletions src/app/components/avatar/avatar.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';
import { NgClass } from '@angular/common';

@Component({
selector: 'blog-avatar',
standalone: true,
imports: [CommonModule],
imports: [NgClass],
templateUrl: './avatar.component.html',
styleUrl: './avatar.component.scss',
})
export class AvatarComponent {
@Input() url: string | null = null;
export class AvatarComponent implements AfterViewInit {

@Input() url!: string | undefined;
@Input() format: 'circle' | 'square' = 'circle';
@Input() shadow = false;

@ViewChild('avatar')
image!: ElementRef;

placeholder: boolean = false;

ngAfterViewInit(): void {
this.image?.nativeElement?.addEventListener('error', () => {
this.placeholder = true
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
data-role="button"
[routerLink]="post | postUrl">
<div class="featured__image">
<blog-post-image [url]="post | postUrl: post.teaser"></blog-post-image>
<blog-post-image
[asset]="post.displayTeaser"
[postUrl]="post | postUrl"
></blog-post-image>
</div>

<div class="featured__content">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
position: relative;
}

@include responsive.up('sm') {
@include responsive.up('md') {
display: flex;
flex-direction: row-reverse;
background-color: transparent;
Expand All @@ -39,6 +39,7 @@
flex-grow: 1;
display: flex;
align-items: center;
max-width: 50%;

.post-content {
width: 100%;
Expand Down
18 changes: 10 additions & 8 deletions src/app/components/post-image/post-image.component.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
@if (isShown) {
@if (asset) {
<picture>
@for (image of images; track $index) {
<source
[srcset]="image.url"
[media]="'(min-width: ' + image.width + 'px)'" />
}
<source
[srcset]="postUrl + '/' + asset.md"
[media]="'(min-width: 800px)'" />

<source
[srcset]="postUrl + '/' + asset.lg"
[media]="'(min-width: 1200px)'" />

<img
mat-card-image
[src]="images[images.length - 1].url"
alt="${title || text}" />
[src]="postUrl + '/' + asset.md"
alt="" />
</picture>
}
21 changes: 3 additions & 18 deletions src/app/components/post-image/post-image.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ProcessedAsset } from '../../core/model/content.model';

@Component({
selector: 'blog-post-image',
Expand All @@ -10,22 +11,6 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PostImageComponent {
images = [
{ size: 'md', width: 800, url: '' },
{ size: 'lg', width: 1200, url: '' },
];

isShown = true;

@Input() set url(value: string) {
this.isShown = !!value;
if (!this.isShown) {
return;
}
const splittedHref = value.split('/');
const lastItem = splittedHref.pop();
this.images.forEach(element => {
element.url = [...splittedHref, 'dist', element.size, lastItem].join('/');
});
}
@Input() asset!: ProcessedAsset;
@Input() postUrl!: string;
}
4 changes: 3 additions & 1 deletion src/app/components/post-item/post-item.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
<mat-card-header class="item-card__header">
<blog-post-image
loading="lazy"
[url]="post | postUrl: post.teaser"></blog-post-image>
[asset]="post.displayTeaser"
[postUrl]="post | postUrl"
></blog-post-image>
</mat-card-header>

<mat-card-content>
Expand Down
Loading

0 comments on commit 0e545e2

Please sign in to comment.