Compare commits
73 Commits
1a1c1217e9
...
master
Author | SHA1 | Date | |
---|---|---|---|
1a9df45e55
|
|||
d5d7f74fd0
|
|||
934c4f4de3
|
|||
1ff611b3ed
|
|||
e2372b378a
|
|||
c4d3194a7f
|
|||
252f5143d1
|
|||
9a0cf62882
|
|||
c267ec35a4
|
|||
fd867c7262
|
|||
3bdc78303d
|
|||
4aafc98be9
|
|||
84bae3759d
|
|||
98ff90f460
|
|||
ab55d75296
|
|||
f69df643f7
|
|||
2e328133cc
|
|||
ac1744869d
|
|||
68e1e77843
|
|||
675f56d9c5
|
|||
7bf40c1263
|
|||
3586eeb6bf
|
|||
ee9a16865e
|
|||
a1533640cf
|
|||
d48d4dcb14
|
|||
bdd2e8c79a
|
|||
b36d394308
|
|||
a8295a7321
|
|||
a3f0a74535
|
|||
0e5cce4a52
|
|||
2007c280c8
|
|||
03aadb59fe
|
|||
0f90c7c0d0 | |||
fbf3657b77
|
|||
21f1d9216c
|
|||
0bd69bd3f3
|
|||
de146693aa
|
|||
57bd0f0fcc
|
|||
41e4d4dab0
|
|||
176a5855de
|
|||
1b2e0d7501
|
|||
db94ace86e | |||
60babf9451
|
|||
b5d6232b59
|
|||
3a123ab8ee
|
|||
652cee0e2e
|
|||
080912401b
|
|||
8acfafab45
|
|||
0e97c82aa1
|
|||
6307509542 | |||
118c8f89c0
|
|||
1a4c18cce0
|
|||
0aaf47909f
|
|||
186bdde093
|
|||
f99cd77e20
|
|||
c4dc1d26d2
|
|||
2bf4389d37 | |||
f1a7bd7dff | |||
8d1aec32f6 | |||
|
b631a8e782 | ||
|
cc792b244b | ||
0b0c028954 | |||
d01a3f227c | |||
36a58be0f1 | |||
c8f30073d9 | |||
b0e84f281d | |||
c10c858988 | |||
eeebcd3472 | |||
04e9e1fd14 | |||
fb419d0bea | |||
193625958a | |||
d7ccad274c | |||
de320346e3 |
@@ -1 +0,0 @@
|
||||
nodejs 12.22.4
|
11
Dockerfile
@@ -1,9 +1,14 @@
|
||||
FROM node:12-alpine
|
||||
FROM node:16.17-alpine
|
||||
|
||||
RUN apk update && apk add python3 make gcc g++
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ADD package.json .
|
||||
RUN npm install
|
||||
|
||||
ADD . .
|
||||
|
||||
RUN npm install
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["npm", "start"]
|
||||
|
8
Makefile
@@ -1,6 +1,6 @@
|
||||
.DEFAULT_GOAL := default
|
||||
|
||||
IMAGE ?= docker.cloud.cluster.fun/averagemarcus/blog:latest
|
||||
IMAGE ?= rg.fr-par.scw.cloud/averagemarcus/blog:latest
|
||||
|
||||
.PHONY: test # Run all tests, linting and format checks
|
||||
test: lint check-format run-tests
|
||||
@@ -38,8 +38,8 @@ docker-publish:
|
||||
@docker push $(IMAGE)
|
||||
|
||||
.PHONY: run # Run the application
|
||||
run:
|
||||
@npm start
|
||||
run: docker-build
|
||||
@docker run --rm -it -p 8000:8000 $(IMAGE)
|
||||
|
||||
.PHONY: ci # Perform CI specific tasks to perform on a pull request
|
||||
ci:
|
||||
@@ -47,7 +47,7 @@ ci:
|
||||
|
||||
.PHONY: release # Release the latest version of the application
|
||||
release:
|
||||
@kubectl --namespace blog set image deployment blog web=docker.cluster.fun/averagemarcus/blog:$(SHA)
|
||||
@kubectl --namespace blog set image deployment blog web=rg.fr-par.scw.cloud/averagemarcus/blog:$(SHA)
|
||||
|
||||
.PHONY: help # Show this list of commands
|
||||
help:
|
||||
|
41
app.js
@@ -23,26 +23,54 @@ const striptags = require('striptags');
|
||||
|
||||
const port = process.env.PORT || 8000;
|
||||
|
||||
app.disable('x-powered-by');
|
||||
app.use(compress());
|
||||
app.use(express.static(__dirname + '/build'));
|
||||
|
||||
// Lets try and slow down some of those exploit crawlers
|
||||
app.use("/", require('./filterRoutes'));
|
||||
|
||||
// Redirects
|
||||
app.use("/", require('./redirects'));
|
||||
|
||||
// Handle some iOS icon 404s
|
||||
app.get("/apple-touch-icon*", function(req, res) {
|
||||
res.sendFile(__dirname + '/build/images/favico/' + req.url, () => {
|
||||
res.sendFile(__dirname + '/build/images/favico/apple-touch-icon.png');
|
||||
});
|
||||
});
|
||||
app.get("/images/favico/*.png", function(req, res) {
|
||||
res.sendFile(__dirname + '/build/images/favico/apple-touch-icon.png');
|
||||
});
|
||||
|
||||
app.get("/favicon.png", function(req, res) {
|
||||
res.sendFile(__dirname + '/build/images/favico/apple-touch-icon.png');
|
||||
});
|
||||
|
||||
app.get("/robots.txt", function(req, res) {
|
||||
res.send("User-agent: * Disallow: ");
|
||||
})
|
||||
|
||||
app.get(/\/(feed|rss)\/?$/, function(req, res) {
|
||||
res.redirect('/feed.xml');
|
||||
})
|
||||
app.get(/(\/(feeds?|rss|atom)\/?|feed.xml|rss.xml|index.rss|feed.rss)$/, function(req, res) {
|
||||
res.redirect(301, '/feed.xml');
|
||||
});
|
||||
|
||||
app.get(/.+\/manifest.json$/, function(req, res) {
|
||||
res.redirect(301, '/manifest.json');
|
||||
});
|
||||
|
||||
app.get("/healthz", function(req, res) {
|
||||
res.sendStatus(200);
|
||||
})
|
||||
});
|
||||
|
||||
var md = markdown({html: true});
|
||||
md.parser.use(emoji);
|
||||
const proxy = (tokens, idx, options, env, self) => self.renderToken(tokens, idx, options);
|
||||
const defaultTableOpenRenderer = md.parser.renderer.rules.table_open || proxy;
|
||||
md.parser.renderer.rules.table_open = function(tokens, idx, options, env, self) {
|
||||
tokens[idx].attrJoin("role", "grid");
|
||||
return defaultTableOpenRenderer(tokens, idx, options, env, self)
|
||||
};
|
||||
|
||||
Handlebars.registerHelper('markdown', function(text) {
|
||||
if(!text) return;
|
||||
@@ -63,12 +91,15 @@ Handlebars.registerHelper("buildTitle", function(title, siteTitle){
|
||||
Handlebars.registerHelper("jointags", function(tags){
|
||||
return (tags || '').split(' ').join(',');
|
||||
});
|
||||
Handlebars.registerHelper("encodetitle", function(str){
|
||||
return (str || '').replaceAll(' ', '%2B');
|
||||
});
|
||||
|
||||
Metalsmith(__dirname)
|
||||
.use(define({
|
||||
site: {
|
||||
title: 'Marcus Noble',
|
||||
description: 'Awesomeness with a side of geek',
|
||||
description: 'The blog of Marcus Noble, self-described tinkerer, platform engineer and all round average guy!',
|
||||
url: 'https://marcusnoble.co.uk'
|
||||
}
|
||||
}))
|
||||
|
@@ -4,29 +4,82 @@ const blackHole = function (req, res) {
|
||||
res.redirect("https://crawler-test.com/redirects/infinite_redirect");
|
||||
};
|
||||
|
||||
router.all('(/*)?/wp-admin/', blackHole);
|
||||
// Specifically allow, but mark as not-found, any `/.well-known/` paths
|
||||
router.all(/^\/\.well-known\//, function(req, res) {
|
||||
res.sendStatus(404);
|
||||
});
|
||||
|
||||
// Block access to any root-level dot files
|
||||
router.all(/^\/\./, blackHole);
|
||||
// Block access to file types I don't use
|
||||
router.all(/.*\.php$/, blackHole);
|
||||
router.all(/.*\.asp$/, blackHole);
|
||||
router.all(/.*\.aspx$/, blackHole);
|
||||
router.all(/.*\.gz$/, blackHole);
|
||||
router.all(/.*\.bz2$/, blackHole);
|
||||
router.all(/.*\.tar$/, blackHole);
|
||||
router.all(/.*\.sql$/, blackHole);
|
||||
router.all('(/*)?/wp-includes/(*)?', blackHole);
|
||||
router.all('/.git/*?', blackHole);
|
||||
router.all('/.env', blackHole);
|
||||
router.all('/autodiscover/autodiscover.xml', blackHole)
|
||||
router.all('/.well-known/autoconfig(/.*)?', blackHole)
|
||||
router.all('/admin(/.*)?', blackHole)
|
||||
router.all(/.*\.env$/, blackHole);
|
||||
router.all(/.*\.ini$/, blackHole);
|
||||
router.all(/.*\.pem$/, blackHole);
|
||||
router.all(/.*\.key$/, blackHole);
|
||||
router.all(/.*\.crt$/, blackHole);
|
||||
router.all(/.*\.properties$/, blackHole);
|
||||
// Block access to any .git folders
|
||||
router.all(/.*\/\.git\/.*/, blackHole);
|
||||
// Block attempts to navigate up directories
|
||||
router.all(/.*\.\.\/.*/, blackHole);
|
||||
// Block access to special Mac folder
|
||||
router.all('/__MACOSX/*?', blackHole);
|
||||
// Block access to Workdpress files
|
||||
router.all('(/*)?/wp-admin/', blackHole);
|
||||
router.all('(/*)?/wp-includes/?(*)?', blackHole);
|
||||
router.all('(/*)?/wp-content/?(*)?', blackHole);
|
||||
router.all('/wordpress/', blackHole);
|
||||
router.all('/wp(2)?/', blackHole);
|
||||
router.all('/backup/', blackHole);
|
||||
// Block access to possible databases
|
||||
router.all('/database/', blackHole);
|
||||
router.all('/db/', blackHole);
|
||||
router.all('/db-backup/', blackHole);
|
||||
router.all('/db_backup/', blackHole);
|
||||
router.all('/sql-backup/', blackHole);
|
||||
router.all('/sql/', blackHole);
|
||||
router.all('/pma/', blackHole);
|
||||
router.all('/phpmyadmin/', blackHole);
|
||||
router.all('/mysqladmin/', blackHole);
|
||||
router.all('/mysql/', blackHole);
|
||||
router.all('/myadmin/', blackHole);
|
||||
// Block access to possible backups and uploads
|
||||
router.all('/backup/', blackHole);
|
||||
router.all('/uploads/', blackHole);
|
||||
router.all('/test/', blackHole);
|
||||
router.all('/temp/', blackHole);
|
||||
router.all(/.*\/dbbackup\/.*/, blackHole);
|
||||
router.all('/bak/', blackHole);
|
||||
router.all('archive.zip', blackHole);
|
||||
// Block access to possible credentials
|
||||
router.all('/env.test', blackHole);
|
||||
router.all('/admin(/.*)?', blackHole)
|
||||
router.all('/credentials(/*)?', blackHole);
|
||||
router.all(/.*credentials\.json$/, blackHole);
|
||||
router.all(/.*keys\.json$/, blackHole);
|
||||
router.all(/.*secrets\.json$/, blackHole);
|
||||
// Block system paths
|
||||
router.all('/etc/*', blackHole);
|
||||
router.all('/var/*', blackHole);
|
||||
router.all('/usr/*', blackHole);
|
||||
router.all('/user/*', blackHole);
|
||||
|
||||
// Block misc stuff
|
||||
router.all('/data/owncloud.log', blackHole);
|
||||
router.all('/autodiscover/autodiscover.xml', blackHole)
|
||||
router.all('/.well-known/autoconfig(/*)?', blackHole)
|
||||
router.all('/sites/default/files/', blackHole);
|
||||
router.all(/.*\/mail\/config-.+\.xml/, blackHole);
|
||||
router.all(/archive\.zip/, blackHole);
|
||||
router.all('/bitnami/*', blackHole)
|
||||
router.all('/aws/*', blackHole)
|
||||
|
||||
// Block methods I don't support
|
||||
router.post('*', blackHole);
|
||||
router.put('*', blackHole);
|
||||
router.delete('*', blackHole);
|
||||
|
@@ -20,15 +20,16 @@
|
||||
"metalsmith-markdownit": "^0.3.0",
|
||||
"metalsmith-pagination": "^1.4.0",
|
||||
"metalsmith-permalinks": "^0.5.0",
|
||||
"metalsmith-sass": "^1.7.0",
|
||||
"metalsmith-sass": "^2.0.0",
|
||||
"metalsmith-sitemap": "^1.2.2",
|
||||
"moment": "^2.13.0",
|
||||
"node-sass": "^6.0.0",
|
||||
"striptags": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^1.12.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "12"
|
||||
"node": "16"
|
||||
}
|
||||
}
|
||||
|
8
redirects.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/2022-07-04-managing-kubernetes-without-loosing-your-cool(/)?', function(req, res) {
|
||||
return res.redirect("/2022-07-04-managing-kubernetes-without-losing-your-cool/")
|
||||
});
|
||||
|
||||
module.exports = router
|
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig><msapplication><tile><square70x70logo src="/images/favico/ms-icon-70x70.png"/><square150x150logo src="/images/favico/ms-icon-150x150.png"/><square310x310logo src="/images/favico/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
|
101
src/css/_glitch.scss
Normal file
@@ -0,0 +1,101 @@
|
||||
.glitch-image:hover, .glitch:hover, a:hover {
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.glitch-image {
|
||||
animation: shift 3s ease-in-out .2s alternate 5;
|
||||
}
|
||||
|
||||
.glitch, a:hover {
|
||||
position: relative;
|
||||
text-shadow: 0.05em 0 0 var(--primary-hover), -0.03em -0.04em 0 var(--primary), 0.025em 0.04em 0 var(--primary-inverse);
|
||||
animation: glitch 2s ease alternate 5, shift 2s ease alternate 5;
|
||||
|
||||
&::before, &::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&::before {
|
||||
animation: glitch 1s infinite;
|
||||
clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%);
|
||||
transform: translate(-0.04em, -0.03em);
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
&::after {
|
||||
animation: glitch .5s infinite;
|
||||
clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%);
|
||||
transform: translate(0.04em, 0.03em);
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes glitch {
|
||||
0% {
|
||||
text-shadow: 0.05em 0 0 var(--primary-hover), -0.03em -0.04em 0 var(--primary),
|
||||
0.025em 0.04em 0 var(--primary-inverse);
|
||||
}
|
||||
15% {
|
||||
text-shadow: 0.05em 0 0 var(--primary-hover), -0.03em -0.04em 0 var(--primary),
|
||||
0.025em 0.04em 0 var(--primary-inverse);
|
||||
}
|
||||
16% {
|
||||
text-shadow: -0.05em -0.025em 0 var(--primary-hover), 0.025em 0.035em 0 var(--primary),
|
||||
-0.05em -0.05em 0 var(--primary-inverse);
|
||||
}
|
||||
49% {
|
||||
text-shadow: -0.05em -0.025em 0 var(--primary-hover), 0.025em 0.035em 0 var(--primary),
|
||||
-0.05em -0.05em 0 var(--primary-inverse);
|
||||
}
|
||||
50% {
|
||||
text-shadow: 0.05em 0.035em 0 var(--primary-hover), 0.03em 0 0 var(--primary),
|
||||
0 -0.04em 0 var(--primary-inverse);
|
||||
}
|
||||
99% {
|
||||
text-shadow: 0.05em 0.035em 0 var(--primary-hover), 0.03em 0 0 var(--primary),
|
||||
0 -0.04em 0 var(--primary-inverse);
|
||||
}
|
||||
100% {
|
||||
text-shadow: -0.05em 0 0 var(--primary-hover), -0.025em -0.04em 0 var(--primary),
|
||||
-0.04em -0.025em 0 var(--primary-inverse);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shift {
|
||||
0%,40%, 44%, 58%, 61%, 65%,69%,73%,100% {
|
||||
transform: skewX(0deg);
|
||||
filter: invert(0%);
|
||||
fill: var(--text-color);
|
||||
}
|
||||
41% {
|
||||
transform: skewX(50deg);
|
||||
fill: var(--primary);
|
||||
}
|
||||
42% {
|
||||
transform: skewX(-20deg);
|
||||
filter: invert(40%);
|
||||
}
|
||||
59% {
|
||||
transform: skewX(50deg);
|
||||
fill: var(--primary-hover);
|
||||
}
|
||||
60% {
|
||||
transform: skewX(-40deg);
|
||||
filter: invert(10%);
|
||||
}
|
||||
63% {
|
||||
transform: skewX(10deg);
|
||||
filter: invert(30%);
|
||||
fill: var(--primary-hover);
|
||||
}
|
||||
70% {
|
||||
transform: skewX(-30deg);
|
||||
fill: var(--primary);
|
||||
}
|
||||
71% {
|
||||
transform: skewX(15deg);
|
||||
filter: invert(100%);
|
||||
}
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
@mixin textShadowToCropUnderline($color) {
|
||||
text-shadow:
|
||||
.01em 0 $color,
|
||||
-.01em 0 $color,
|
||||
0 .01em $color,
|
||||
0 -.01em $color,
|
||||
|
||||
.06em 0 $color,
|
||||
-.06em 0 $color,
|
||||
.09em 0 $color,
|
||||
-.09em 0 $color,
|
||||
|
||||
.12em 0 $color,
|
||||
-.12em 0 $color,
|
||||
.15em 0 $color,
|
||||
-.15em 0 $color;
|
||||
}
|
||||
|
||||
@mixin linkUnderlines($background, $color, $hoverColor) {
|
||||
color: $color;
|
||||
text-decoration: none;
|
||||
@include textShadowToCropUnderline($background);
|
||||
|
||||
background-image:
|
||||
linear-gradient($background, $background),
|
||||
linear-gradient($background, $background),
|
||||
linear-gradient($color, $color);
|
||||
background-size:
|
||||
.05em 2px,
|
||||
.05em 2px,
|
||||
2px 2px;
|
||||
background-repeat:
|
||||
no-repeat,
|
||||
no-repeat,
|
||||
repeat-x;
|
||||
background-position: 0% 1.02em, 100% 1.02em, 0% 1.04em;
|
||||
|
||||
&::selection {
|
||||
@include textShadowToCropUnderline($selectionColor);
|
||||
background-color: $selectionColor;
|
||||
}
|
||||
&::-moz-selection {
|
||||
@include textShadowToCropUnderline($selectionColor);
|
||||
background-color: $selectionColor;
|
||||
}
|
||||
&:before,
|
||||
&:after,
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
text-shadow: none;
|
||||
}
|
||||
&:visited {
|
||||
color: $color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $hoverColor;
|
||||
background-image:
|
||||
linear-gradient($background, $background),
|
||||
linear-gradient($background, $background),
|
||||
linear-gradient($hoverColor, $hoverColor);
|
||||
}
|
||||
}
|
7
src/css/_utils.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
@@ -1,265 +0,0 @@
|
||||
$link-color: #AD4E4E;
|
||||
$selectionColor: #D2D2D2;
|
||||
$background-color: #FFF;
|
||||
|
||||
@import "_underlines.scss";
|
||||
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: none;
|
||||
}
|
||||
|
||||
* {
|
||||
&::selection {
|
||||
background-color: $selectionColor;
|
||||
}
|
||||
&::-moz-selection {
|
||||
background-color: $selectionColor;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $link-color;
|
||||
transition: color ease .3s;
|
||||
|
||||
&:hover {
|
||||
color: $link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&+img {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
header {
|
||||
font-family: 'Lucida Grande', Arial, sans-serif;
|
||||
font-size: .8em;
|
||||
|
||||
a:not(.social) {
|
||||
@include linkUnderlines($background-color, #4a4a4a, $link-color);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: normal;
|
||||
margin: .8em 0 .8em 8px;
|
||||
|
||||
img {
|
||||
height: 1.2em;
|
||||
float: left;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #000 !important;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.social {
|
||||
text-decoration: none;
|
||||
|
||||
svg {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&:hover svg path,
|
||||
&:hover svg rect {
|
||||
fill: $link-color !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 0 auto;
|
||||
width: 95%;
|
||||
height: 1px;
|
||||
background-color: rgba(0, 0, 0, .2);
|
||||
}
|
||||
}
|
||||
|
||||
pre code {
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 15px;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
p > code {
|
||||
background-color: #3f3f3f;
|
||||
color: #dcdcdc;
|
||||
font-size: 0.9em;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 8px solid rgba(121, 130, 139, 0.52);
|
||||
margin-left: 0;
|
||||
padding-left: 1em;
|
||||
color: #79828B;
|
||||
}
|
||||
|
||||
figure {
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
border: 1px solid rgba(100,100,100,.2);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
iframe {
|
||||
max-width: 100%;
|
||||
border: 0;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 2px;
|
||||
background: rgba(121, 130, 139, 0.52);
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
details {
|
||||
font-size: 0.8em;
|
||||
border: 1px dashed #79828B;
|
||||
padding: 2px 8px;
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji {
|
||||
display: inline !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1020px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.post-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.post-preview {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
text-align: center;
|
||||
}
|
||||
.pagination a {
|
||||
font-size: 1.4mem;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.post {
|
||||
font-family: 'Lucida Grande', Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
line-height: 28px;
|
||||
padding: 2px 8px;
|
||||
|
||||
a {
|
||||
@include linkUnderlines($background-color, #4a4a4a, $link-color);
|
||||
}
|
||||
|
||||
.post-title {
|
||||
color: #000;
|
||||
font-size: 32px;
|
||||
line-height: 34px;
|
||||
margin: 21px 0 0;
|
||||
font-weight: 700;
|
||||
|
||||
a {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.full-post-link {
|
||||
font-style: italic;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.post-meta {
|
||||
color: #3d4145;
|
||||
font-size: 15px;
|
||||
line-height: 17px;
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
margin: 20px 0 10px;
|
||||
color: #79828B;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.social-icons {
|
||||
a {
|
||||
text-decoration: none !important;
|
||||
background: none !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
a svg {
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.share {
|
||||
background: transparent;
|
||||
border: none;
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
|
||||
&.show {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
&:hover, &:active {
|
||||
fill: $link-color;
|
||||
color: $link-color;
|
||||
}
|
||||
|
||||
svg {
|
||||
height: 20px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
|
||||
&, tr, td, th, tbody, thead {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 5px;
|
||||
border: 1px solid #3d4145;
|
||||
}
|
||||
}
|
5
src/css/pico.min.css
vendored
Normal file
228
src/css/style.scss
Normal file
@@ -0,0 +1,228 @@
|
||||
/* Light Theme */
|
||||
[data-theme="light"],
|
||||
:root:not([data-theme="dark"]) {
|
||||
--primary: #fd7e0b;
|
||||
--primary-hover: #326ce5;
|
||||
--primary-focus: #fefefe;
|
||||
--primary-inverse: #d6efff;
|
||||
--color: #131b23;
|
||||
--text-color: #131b23;
|
||||
}
|
||||
|
||||
/* Dark Theme */
|
||||
@media only screen and (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme="light"]) {
|
||||
--primary: #fd7e0b;
|
||||
--primary-hover: #326ce5;
|
||||
--primary-focus: #131b23;
|
||||
--primary-inverse: #d6efff;
|
||||
--color: #fefefe;
|
||||
--text-color: #fefefe;
|
||||
}
|
||||
}
|
||||
[data-theme="dark"] {
|
||||
--primary: #fd7e0b;
|
||||
--primary-hover: #326ce5;
|
||||
--primary-focus: #131b23;
|
||||
--primary-inverse: #d6efff;
|
||||
--color: #fefefe;
|
||||
--text-color: #fefefe;
|
||||
}
|
||||
|
||||
:root:not([data-theme="dark"]),
|
||||
:root:not([data-theme="light"]){
|
||||
--form-element-active-border-color: var(--primary);
|
||||
--form-element-focus-color: var(--primary-focus);
|
||||
--switch-color: var(--primary-inverse);
|
||||
--switch-checked-background-color: var(--primary);
|
||||
--blockquote-border-color: var(--primary-hover);
|
||||
|
||||
--font-family: 'Orkney', system-ui, -apple-system, "Segoe UI", "Roboto", "Ubuntu",
|
||||
"Cantarell", "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol", "Noto Color Emoji";
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
// Links
|
||||
|
||||
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
|
||||
color: var(--text-color)
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
@media only screen and (prefers-color-scheme: light) {
|
||||
a.social {
|
||||
svg {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
[data-theme="light"] {
|
||||
a.social {
|
||||
svg {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
a.social {
|
||||
svg {
|
||||
margin: 4px;
|
||||
fill: #fff !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
|
||||
svg {
|
||||
animation: shift 1.5s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Layout
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2em 0 !important;
|
||||
|
||||
& + main {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 1em 0 !important;
|
||||
}
|
||||
|
||||
article {
|
||||
margin-top: 0;
|
||||
padding-top: 1.5em;
|
||||
|
||||
blockquote, dl, figure, form, ol, p, pre, table, ul {
|
||||
font-size: calc(var(--font-size) + 2px) !important;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
figure p,
|
||||
blockquote p,
|
||||
blockquote ul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
figure a:hover {
|
||||
text-shadow: initial;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
details {
|
||||
font-size: 0.8em;
|
||||
border: 1px dashed #79828B;
|
||||
padding: 2px 8px;
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
|
||||
&::after {
|
||||
float: unset;
|
||||
display: inline-block;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
code, kbd, pre {
|
||||
color: #dcdcdc;
|
||||
background-color: #3f3f3f;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1em auto;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-top: solid 3px #57688d;
|
||||
text-align: center;
|
||||
width: 60%;
|
||||
position: relative;
|
||||
|
||||
|
||||
&::after {
|
||||
content: "✨";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: -0.7em;
|
||||
padding: 0 5px;
|
||||
font-size: 2rem;
|
||||
filter: grayscale(70%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: ' ';
|
||||
background-color: var(--background-color);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: -1.2em;
|
||||
padding: 0;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 23px;
|
||||
transform: translateX(-50%);
|
||||
|
||||
article & {
|
||||
background-color: var(--card-background-color) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section:last-of-type hr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Custom Classes
|
||||
|
||||
.site-logo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.post-meta {
|
||||
font-size: 0.7em;
|
||||
font-family: 'OrkneyLight';
|
||||
vertical-align: text-bottom;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
&::before {
|
||||
content: "📆 ";
|
||||
filter: grayscale(70%);
|
||||
}
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
|
||||
@import "_utils.scss";
|
||||
@import "_glitch.scss";
|
BIN
src/favicon.ico
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 34 KiB |
BIN
src/images/Cloud_Native_Now_-_Square.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
src/images/emf-airfryer.jpg
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
src/images/emf-blacksmith.jpg
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
src/images/emf-evening-unnecessary.jpg
Normal file
After Width: | Height: | Size: 179 KiB |
BIN
src/images/emf-food.jpg
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
src/images/emf-jo.jpg
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
src/images/emf-jsoxford.jpg
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
src/images/emf-laser-duck-hunt.jpg
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
src/images/emf-lasers.jpg
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
src/images/emf-terence.jpg
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
src/images/emf-tesla-coil.jpg
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
src/images/emf-van.jpg
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
src/images/favico/android-chrome-144x144.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
src/images/favico/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
src/images/favico/android-chrome-256x256.png
Normal file
After Width: | Height: | Size: 85 KiB |
BIN
src/images/favico/android-chrome-36x36.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
src/images/favico/android-chrome-384x384.png
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
src/images/favico/android-chrome-48x48.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
src/images/favico/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 307 KiB |
BIN
src/images/favico/android-chrome-72x72.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
src/images/favico/android-chrome-96x96.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 56 KiB |
BIN
src/images/favico/apple-touch-icon-1024x1024.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
src/images/favico/apple-touch-icon-114x114.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src/images/favico/apple-touch-icon-120x120.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
src/images/favico/apple-touch-icon-144x144.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
src/images/favico/apple-touch-icon-152x152.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
src/images/favico/apple-touch-icon-167x167.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
src/images/favico/apple-touch-icon-180x180.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
src/images/favico/apple-touch-icon-57x57.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
src/images/favico/apple-touch-icon-60x60.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
src/images/favico/apple-touch-icon-72x72.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
src/images/favico/apple-touch-icon-76x76.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
src/images/favico/apple-touch-icon-precomposed.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
src/images/favico/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 780 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.2 KiB |
BIN
src/images/favico/favicon-48x48.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
src/images/favico/favicon-96.png
Normal file
After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 9.1 KiB |
BIN
src/images/favico/mstile-144x144.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
src/images/favico/mstile-150x150.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
src/images/favico/mstile-310x150.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
src/images/favico/mstile-310x310.png
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
src/images/favico/mstile-70x70.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
26
src/images/favico/safari-pinned-tab.svg
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="192.000000pt" height="192.000000pt" viewBox="0 0 192.000000 192.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,192.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M1055 1592 c-45 -10 -154 -99 -169 -137 -4 -11 -10 -45 -12 -75 -5
|
||||
-64 -7 -76 -22 -112 -11 -26 -9 -51 8 -118 5 -19 11 -47 14 -63 3 -15 11 -40
|
||||
18 -55 29 -60 4 -115 -57 -125 -11 -2 -35 -11 -52 -20 -18 -10 -33 -15 -33
|
||||
-11 0 4 -6 2 -12 -4 -7 -5 -29 -13 -48 -17 -45 -10 -121 -48 -140 -72 -41 -49
|
||||
-72 -93 -65 -93 4 0 2 -7 -5 -15 -7 -8 -9 -15 -6 -15 4 0 2 -9 -4 -20 -6 -11
|
||||
-13 -38 -15 -60 -2 -22 -9 -58 -15 -80 -6 -23 -13 -58 -16 -78 -2 -20 -7 -50
|
||||
-10 -67 -12 -57 -15 -90 -17 -223 l-2 -132 706 0 706 0 -3 58 c-4 90 -12 149
|
||||
-28 201 -8 27 -12 52 -9 55 3 3 2 13 -2 23 -5 10 -9 24 -11 30 -1 7 -9 32 -17
|
||||
55 -19 54 -41 128 -58 196 -7 28 -17 52 -21 52 -5 0 -7 4 -3 9 3 5 1 12 -5 16
|
||||
-5 3 -17 22 -26 41 -15 30 -89 94 -110 94 -4 0 -26 9 -48 20 -23 11 -50 21
|
||||
-61 23 -11 2 -33 9 -48 15 -16 7 -31 12 -34 12 -16 0 -93 45 -93 54 0 13 52
|
||||
166 73 215 9 21 12 44 7 60 -4 14 -6 64 -4 111 3 101 -8 130 -68 187 -60 57
|
||||
-123 79 -183 65z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/images/k9s.gif
Normal file
After Width: | Height: | Size: 3.8 MiB |
BIN
src/images/kubernetes_operators_diagram.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
src/images/linkedin-scopes.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
src/images/marcus-transparent.png
Normal file
After Width: | Height: | Size: 3.1 MiB |
BIN
src/images/marcus.jpg
Normal file → Executable file
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 7.9 MiB |
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 15 MiB |
BIN
src/images/node-red-blog-flow.png
Normal file
After Width: | Height: | Size: 166 KiB |
BIN
src/images/node-red-bluesky-format-post-setup.png
Normal file
After Width: | Height: | Size: 114 KiB |
BIN
src/images/node-red-dropout-bot.png
Normal file
After Width: | Height: | Size: 226 KiB |
BIN
src/images/node-red-kubernetes-releases-bot.png
Normal file
After Width: | Height: | Size: 109 KiB |
BIN
src/images/node-red-post-to-bluesky.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
src/images/node-red-post-to-linkedin.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
src/images/node-red-post-to-mastodon.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
src/images/node-red-wayback-machine.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
src/images/podman-macos.png
Normal file
After Width: | Height: | Size: 403 KiB |
BIN
src/images/renovate-kubernetes-bump.png
Normal file
After Width: | Height: | Size: 131 KiB |
42
src/images/tweets/1432720164169076755.svg
Normal file
@@ -0,0 +1,42 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="499px" height="348px">
|
||||
<foreignObject x="0" y="0" width="499px" height="100%" fill="#eade52">
|
||||
<style>
|
||||
.tweetsvg{clear:none;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;}
|
||||
.tweetsvg.text{font-size: 23px;}
|
||||
a.tweetsvg{color: rgb(27, 149, 224); text-decoration:none;}
|
||||
.tweetsvg a { color: #1da1f2; }
|
||||
blockquote.tweetsvg{margin:1px; background-color:#fefefe; border-radius:2%; border-style:solid; border-width:.1em; border-color:#ddd; padding:1em; font-family:sans; width:29rem}
|
||||
blockquote.subtweet{width:26rem; padding:0.8em;}
|
||||
.avatar-tweetsvg{float:left; width:4rem; height:4rem; border-radius:50%;margin-right:.5rem;;margin-bottom:.5rem;border-style: solid; border-width:.1em; border-color:#ddd;}
|
||||
h1.tweetsvg{margin:0;font-size:15px;text-decoration:none;color:#000;}
|
||||
h2.tweetsvg{margin:0;font-size:15px;font-weight:normal;text-decoration:none;color:rgb(101, 119, 134);}
|
||||
p.tweetsvg{font-size:1rem; clear:both;}
|
||||
hr.tweetsvg{color:#ddd;}
|
||||
.media-tweetsvg{border-radius:2%; max-width:100%;border-radius: 2%; border-style: solid; border-width: .1em; border-color: #ddd;}
|
||||
time.tweetsvg{font-size:15px;margin:0;margin-left: 2px;padding-bottom:1rem;color:rgb(101, 119, 134);text-decoration:none;}
|
||||
.tweetsvg.reply{font-size:15px;color:rgb(110, 118, 125);}
|
||||
.tweetsvg.footer{display:block;}
|
||||
</style>
|
||||
<blockquote class="tweetsvg" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a rel="noopener" target="_blank" class="tweetsvg" href="https://twitter.com/QuinnyPig/"><img class="avatar-tweetsvg" alt="" src="data:image/jpeg;base64,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" /></a>
|
||||
|
||||
<a rel="noopener" target="_blank" class="tweetsvg" href="https://twitter.com/QuinnyPig/"><h1 class="tweetsvg">Corey Quinn / @quinnypig@awscommunity.social</h1></a>
|
||||
|
||||
<a rel="noopener" target="_blank" class="tweetsvg" href="https://twitter.com/QuinnyPig/"><h2 class="tweetsvg">@QuinnyPig</h2></a>
|
||||
|
||||
|
||||
|
||||
<p class="tweetsvg text">So @docker has a new monetization strategy that's definitely innovative. "Docker Desktop requires you pay them if you're at a large company," which they define as over $10 million in revenue or 250 employees.<br /><br /><a rel="noopener" target="_blank" href="https://www.docker.com/blog/updating-product-subscriptions/">docker.com/blog/updating-…</a></p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a rel="noopener" target="_blank" class="tweetsvg footer" href="https://twitter.com/QuinnyPig/status/1432720164169076755">
|
||||
<time class="tweetsvg" datetime="2021-08-31T15:01:20Z">3:01 PM · Aug 31, 2021</time>
|
||||
</a>
|
||||
</blockquote>
|
||||
</foreignObject>
|
||||
</svg>
|
After Width: | Height: | Size: 5.4 KiB |