6 Commits

Author SHA1 Message Date
6ad2e97e2e Kubernetes tips 2025-10-20 12:16:46 +02:00
a61c44b085 playground post 2025-10-05 17:23:35 +02:00
52089dd9dc Added preconnect link 2025-10-04 18:31:01 +02:00
9bb67f04c2 Style description 2025-10-04 18:12:13 +02:00
11298411bd Added document title and fixed viewport size 2025-10-04 18:00:27 +02:00
2ef2f5d974 Add playground 2025-10-04 16:08:11 +02:00
12 changed files with 282 additions and 108 deletions

View File

@@ -19,23 +19,24 @@ export class FileLoader implements IPluginBuilder {
const { menuManifest } = builderContext;
const { files } = this.options;
files.forEach((file) => {
const fileName =
file.nameOverride ?? file.path.split("/").pop() ?? file.path;
const filePath = file.path.split("/").pop() ?? file.path;
const fileName = file.nameOverride ?? filePath;
const isImage = fileName.match(/\.(png|jpe?g|gif|webp)$/);
if (isImage) {
console.log("Processing image", file.path);
ffmpeg(file.path)
.output(`${builderContext.outputDirectory}/${fileName}`)
.output(`${builderContext.outputDirectory}/${filePath}`)
.size(`${this.options.imageWidth ?? 200}x?`)
.run();
} else {
console.log("Copying file", file.path);
copyFile(file.path, `${builderContext.outputDirectory}/${fileName}`);
const destination = `${builderContext.outputDirectory}/${filePath}`;
console.log("Copying file", file.path, "to", destination);
copyFile(file.path, destination);
}
if (file.menuEntry) {
menuManifest.push({
name: fileName,
link: file.path,
link: filePath,
});
}
});

View File

@@ -44,9 +44,9 @@ const createMarkdownLoaderManifest = ({
publicAssetDirectoryPath: `/${noteDirectory}_`,
assetFiles: fs.existsSync(assetDirectoryPath)
? fs.readdirSync(assetDirectoryPath).map((name) => ({
path: `${assetDirectoryPath}/${name}`,
name,
}))
path: `${assetDirectoryPath}/${name}`,
name,
}))
: [],
};
});
@@ -85,10 +85,12 @@ const writeMarkdownAsHtmlToOutputDirectory = (
) => {
markdownManifest.forEach((m) => {
const markdownAsHtml = toHtml(m.markdown, m.publicAssetDirectoryPath);
const titleWithoutDashesOrNumbers = (m.name.slice(m.name.indexOf('-') + 1) ?? "").replaceAll('-', ' ');
const noteHtmlDocument = noteHtmlTemplate.replace(
markdownHtmlReplacementTag,
markdownAsHtml
);
).replace("{{title}}", titleWithoutDashesOrNumbers);
writeTextAsFile(
`${outputDirectory}/${m.directoryName}.html`,
noteHtmlDocument

53
src/assets/base.css Normal file
View File

@@ -0,0 +1,53 @@
:root {
--color-background: #1c1b28;
--color-accent: #00FFFF;
--color-text: #FFF;
--content-width: 800px;
--font-size-base: 18px;
--line-height-base: 26px;
--font-family: monospace;
--space-base: 1rem;
}
.banner {
margin-top: 1rem;
width: 100%;
height: 40px;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
align-items: center;
flex: 1;
font-family: monospace;
}
.banner {
.title {
display: flex;
flex-direction: row;
flex: 1;
.name {
color: #1c1b28;
background-color: #00FFFF;
white-space: nowrap;
padding: 5px;
a {
color: unset;
text-decoration: none;
}
}
}
.title::after {
background: repeating-linear-gradient(90deg, #00FFFF, #00FFFF 2px, transparent 0, transparent 10px);
content: "";
display: block;
width: 100%;
margin-left: 10px;
}
}

View File

@@ -24,7 +24,6 @@ new ToolchainBuilder(paths)
files: [
{
path: "src/templates/404.html",
nameOverride: "Not Found Page",
menuEntry: false,
},
{
@@ -32,6 +31,13 @@ new ToolchainBuilder(paths)
},
{
path: "src/assets/favicon.ico",
},
{
path: "src/assets/base.css"
},
{
path: "src/playground/playground.html",
nameOverride: "CSS/HTML playground"
}
],
}),

View File

Before

Width:  |  Height:  |  Size: 8.2 MiB

After

Width:  |  Height:  |  Size: 8.2 MiB

View File

@@ -1,4 +1,4 @@
# Second hand MTB
# Second hand MTB - part 1
_2025-08-17 - 2 minute read_

View File

@@ -0,0 +1,17 @@
# Live demos and experiments
I recently attended a Swedish frontend development conference called nordicjs. Something that I noticed was that some of the speakers had made tools and demos that they were using live in their keynotes which I thought was pretty neat!
It got me thinking about being able to host tools like that along with my [static site generator](https://git.zacke.dev/wholteza/blog). As long as they're not too heavy and dependent on JS libraries.
My SSG project is built up around a plugin chain where one of the plugins available is a [file loader](https://git.zacke.dev/wholteza/blog/src/branch/main/packages/@zblog/toolchain/src/file-loader.ts). So to start off i just added a new directory for what I call playgrounds and added a new HTML file into the [files array of the plugin](https://git.zacke.dev/wholteza/blog/src/commit/52089dd9dc163ddbf1dbbc56af31e39bb7a0254f/src/index.ts) which makes sure that it is available in the built site.
The result? The very first [playground](/playground.html) of this site. It's a very simple HTML + CSS playground with a preview pane that will show you the result. To start off it shows the CSS logotype, but change any parameter and it will update immediately. [Source BTW](https://git.zacke.dev/wholteza/blog/src/commit/52089dd9dc163ddbf1dbbc56af31e39bb7a0254f/src/playground/playground.html).
This initial playground is meant to be part of something bigger. I have thoughts about building a presentation framework and I want these kinds of interactive and editable examples to be part of it. But we will see when I get the urge to build it.
Until then I will have a way to make different demos and experiments available.
Right now they will show up as menu alternatives on the home page. I also noticed that since files loaded by the file loader plugin wasn't designed to end up on the home page post flow they always end up at the top which isn't ideal. I'll have to do something about that in the future or just simply have a blog post that link to each playground. I probably want to write something about it anyways. _Edit: I updated the file loading so that is isn't present on the home page._
Until next time.

View File

@@ -0,0 +1,18 @@
# Kubernetes tricks
A collection of nice to haves while managing applications in kubernetes.
## Kubectl proxy
Running `kubectl proxy` will open a tunnel to the selected cluster. You can then access the webapi on the port that was displayed.
Using that webapi you can browse the resources and even access the application hosted within your cluster.
### Explore a namespace
Enter the following address and replace the namespace name and the resource type (pods|services) to get a list of the available resources.
`http://localhost:8001/api/v1/namespaces/<namespace-name>/<resource-type>`
### Make a request to a service or pod
The url pattern looks like this: `http://localhost:8001/api/v1/namespaces/<namespace-name>/<pods|services>/<protocol>:<name>:<port>/proxy/<url-path>`
Example: `http://localhost:8001/api/v1/namespaces/hangfire-services/services/http:hangfire-services:80/proxy/hangfire` will make a request to my hangfire dashboard.

View File

@@ -0,0 +1,146 @@
<!DOCTYPE html>
<meta>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>zacke.dev - playground</title>
<link href="https://blog.zacke.dev" rel="preconnect" />
<link href="base.css" rel="stylesheet" />
<style>
html {
line-height: var(--line-height-base);
font-size: 18px;
display: flex;
justify-content: center;
align-items: center;
font-family: var(--font-family);
}
body {
max-width: var(--content-width);
background-color: var(--color-background);
color: var(--color-text);
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
#description {
box-sizing: border-box;
margin: var(--space-base);
padding: var(--space-base);
a {
color: var(--color-accent);
}
}
#style-editor {
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
background-color: var(--color-background);
color: var(--color-text);
font-size: 18px;
display: flex;
flex: 1;
outline: none;
border: 1px solid var(--color-accent);
box-sizing: border-box;
}
#html-editor {
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
background-color: var(--color-background);
color: var(--color-text);
font-size: 18px;
display: flex;
flex: 1;
outline: none;
border: 1px solid var(--color-accent);
box-sizing: border-box;
}
#preview {
width: 100%;
box-sizing: border-box;
padding: 1rem;
margin-bottom: 1rem;
background-color: var(--color-background);
color: var(--color-text);
font-size: 18px;
display: flex;
flex: 1;
outline: none;
border: 1px solid var(--color-accent);
justify-content: center;
align-items: center;
}
}
</style>
<style id="style">
.square {
height: 150px;
width: 150px;
background-color: #553FF3;
color: white;
font-weight: bold;
font-size: 3rem;
position: ;
border-radius: 30px;
border-top-left-radius: 5px;
}
span {
display: block;
position: relative;
top: 100px;
left: 45px;
}
</style>
<div id="markup" aria-hidden="true" hidden="true" style="display: none;">
<div class="square"><span>CSS</span></div>
</div>
<script type="text/javascript">
window.onload = function () {
const style = document.getElementById('style').innerHTML;
const formattedStyle = style.split("\n").reduce((agg, curr) => {
console.log(curr)
if (curr === "") return agg;
const line = curr.replace('\t', '').replaceAll('\t', ' ');
if (agg.length === 0) return line;
return agg + "\n" + line;;
}, "");
console.log(formattedStyle)
document.getElementById('style-editor').value = formattedStyle;
document.getElementById('style').innerHTML = formattedStyle;
const markup = document.getElementById('markup').innerHTML;
const formattedMarkup = markup.replace('\t', '').replaceAll('\t', ' ').split('\n').filter(line => line !== '').join('\n');
document.getElementById('html-editor').value = formattedMarkup;
document.getElementById('preview').innerHTML = formattedMarkup;
}
</script>
</meta>
<body>
<div class="banner">
<div class="title">
<div class="name"><a href="/">Zackarias Montell</a></div>
</div>
</div>
<p id="description">This is an interactive HTML and CSS playground built with minimal JS. Alter the HTML and CSS below
to preview the changes. <a
href="https://git.zacke.dev/wholteza/blog/src/branch/main/src/playground/playground.html">Source here!</a></p>
<textarea id="html-editor" oninput="document.getElementById('preview').innerHTML=this.value" rows="15"
autocomplete="false" autocorrect="false" id="style-editor">
</textarea>
<textarea rows="15" autocomplete="false" autocorrect="false" id="style-editor"
oninput="document.getElementById('style').innerHTML = this.value">
</textarea>
<div id="preview"></div>
</body>
</html>

View File

@@ -1,15 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Not Found</title>
</head>
<body>
<div id="message">
<h2>404</h2>
<h1>Page Not Found</h1>
<p>The specified file was not found on this website. Please check the URL for mistakes and try again.</p>
</div>
</body>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page Not Found</title>
</head>
<body>
<div id="message">
<h2>404</h2>
<h1>Page Not Found</h1>
<p>The specified file was not found on this website. Please check the URL for mistakes and try again.</p>
</div>
</body>
</html>

View File

@@ -4,7 +4,9 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<title>zacke.dev</title>
<link href="https://blog.zacke.dev" rel="preconnect" />
<link href="base.css" rel="stylesheet" />
<style>
html {
font-size: 18px;
@@ -17,13 +19,13 @@
}
a {
color: #FFF;
color: var(--color-accent);
}
body {
max-width: 800px;
color: #fbfbfe;
background-color: #1c1b28;
background-color: var(--color-background);
display: flex;
flex-direction: column;
align-items: center;
@@ -84,46 +86,6 @@
}
.profile li {}
.banner {
margin-top: 1rem;
width: 100%;
height: 40px;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
align-items: center;
flex: 1;
font-family: monospace;
}
.banner {
.title {
display: flex;
flex-direction: row;
flex: 1;
.name {
color: #1c1b28;
background-color: #00FFFF;
white-space: nowrap;
padding: 5px;
a {
color: unset;
text-decoration: none;
}
}
}
.title::after {
background: repeating-linear-gradient(90deg, #00FFFF, #00FFFF 2px, transparent 0, transparent 10px);
content: "";
display: block;
width: 100%;
margin-left: 10px;
}
}
</style>
</head>
@@ -156,6 +118,10 @@
for
my first name.)</p>
<p>Live demos and experiments:</p>
<ul>
<li><a href="/playground.html">CSS + HTML Playground</a></li>
</ul>
</div>
<div class="content">

View File

@@ -4,7 +4,9 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<title>zacke.dev - {{title}}</title>
<link href="https://blog.zacke.dev" rel="preconnect" />
<link href="base.css" rel="stylesheet" />
<style>
html {
font-family: monospace;
@@ -82,46 +84,6 @@
margin-top: 0px;
}
.banner {
margin-top: 1rem;
width: 100%;
height: 40px;
display: flex;
flex-direction: row;
margin-bottom: 1rem;
align-items: center;
flex: 1;
font-family: monospace;
}
.banner {
.title {
display: flex;
flex-direction: row;
flex: 1;
.name {
color: #1c1b28;
background-color: #00FFFF;
white-space: nowrap;
padding: 5px;
a {
color: unset;
text-decoration: none;
}
}
}
.title::after {
background: repeating-linear-gradient(90deg, #00FFFF, #00FFFF 2px, transparent 0, transparent 10px);
content: "";
display: block;
width: 100%;
margin-left: 10px;
}
}
a {
color: #00FFFF;
}