First commit

This commit is contained in:
Mario Romero 2023-05-16 14:08:46 -04:00
commit d3a534ab64
35 changed files with 823 additions and 0 deletions

7
src/.fleek.json Normal file
View File

@ -0,0 +1,7 @@
{
"build": {
"image": "denoland/deno",
"command": "deno task build --location=https://lume-blog.on.fleek.co",
"publicDir": "_site"
}
}

2
src/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
_site
_bin

8
src/404.md Normal file
View File

@ -0,0 +1,8 @@
---
layout: layouts/home.njk
url: /404.html
---
# Content not found.
Go [home](/).

46
src/_config.ts Normal file
View File

@ -0,0 +1,46 @@
import lume from "lume/mod.ts";
import date from "lume/plugins/date.ts";
import postcss from "lume/plugins/postcss.ts";
import codeHighlight from "lume/plugins/code_highlight.ts";
import basePath from "lume/plugins/base_path.ts";
import slugifyUrls from "lume/plugins/slugify_urls.ts";
import resolveUrls from "lume/plugins/resolve_urls.ts";
import netlifyCMS from "lume/plugins/netlify_cms.ts";
import pageFind from "lume/plugins/pagefind.ts";
import sitemap from "lume/plugins/sitemap.ts";
import feed from "lume/plugins/feed.ts";
const site = lume({
location: new URL("https://example.com/"),
});
site
.ignore("README.md")
.copy("img")
.use(postcss())
.use(date())
.use(codeHighlight())
.use(basePath())
.use(sitemap())
.use(pageFind({
ui: {
resetStyles: false,
},
}))
.use(slugifyUrls({ alphanumeric: false }))
.use(feed({
output: ["/feed.json", "/feed.xml"],
query: "type=posts",
info: {
title: "=site.title",
description: "=site.description",
},
items: {
title: "=title",
content: "$.post-body",
}
}))
.use(resolveUrls())
.use(netlifyCMS({ netlifyIdentity: true }));
export default site;

54
src/_data/netlify_cms.js Normal file
View File

@ -0,0 +1,54 @@
import f from "https://deno.land/x/netlify_cms_config@v0.2.0/mod.ts";
f.defaultRequired = false;
const config = {
backend: {
name: "git-gateway",
branch: "master",
},
media_folder: "img",
collections: [],
};
// Posts
config.collections.push(
f.folder("Posts", "posts")
.description("Here you can create or edit your posts")
.preview(false)
.create(true)
.viewFilter("Draft", "draft", true)
.fields([
f.string("Title"),
f.string("Description"),
f.datetime("Date"),
f.list("Tags"),
f.boolean("Draft").required(false),
f.markdown("Body"),
])
.toJSON(),
);
const pageFields = [
f.string("Title"),
f.string("Url"),
f.markdown("Body"),
f.object("Menu", [
f.boolean("Visible"),
f.number("Order"),
]),
f.hidden("templateClass"),
f.hidden("layout"),
];
// Individual pages
config.collections.push(
f.files("Pages")
.description("Here you can edit your individual pages")
.preview(false)
.file("About", "about.md", pageFields)
.file("404", "404.md", pageFields)
.toJSON(),
);
export default config;

6
src/_data/site.yml Executable file
View File

@ -0,0 +1,6 @@
title: 1159
description: Mario Romero personal site.
author:
name: Mario Romero,
email: mario@1159.cl,
url: https://1159.cl/home/

View File

@ -0,0 +1,66 @@
.navbar {
display: flex;
flex-wrap: wrap;
align-items: center;
padding: 1rem 1rem 1rem 2rem;
column-gap: 2rem;
row-gap: 1rem;
background-color: var(--bg-secondary);
& a {
display: block;
color: var(--fg-secondary);
&:not(:hover) {
text-decoration: none;
}
}
}
.navbar-links {
padding: 0;
margin: 0;
list-style: none;
display: flex;
flex-wrap: wrap;
column-gap: 2rem;
& [aria-current="page"] {
font-weight: bold;
text-decoration: underline;
}
}
.navbar-search {
flex-grow: 1;
max-width: 800px;
margin-left: auto;
}
#search {
& .pagefind-ui__drawer {
margin-top: 2px;
position: absolute;
background: var(--bg-secondary);
padding: 0 2rem 1rem;
max-height: calc(100vh - 200px);
overflow-y: auto;
box-shadow: 0 10px 10px -5px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
border-bottom-right-radius: var(--pagefind-ui-border-radius);
border-bottom-left-radius: var(--pagefind-ui-border-radius);
width: 100%;
box-sizing: border-box;
}
& .pagefind-ui__message {
margin: 0;
padding: 0;
}
& .pagefind-ui__result-link {
color: var(--accent-primary);
}
& .pagefind-ui__result-excerpt {
color: var(--fg-primary);
}
& .pagefind-ui__search-input {
color: var(--fg-primary);
}
}

View File

@ -0,0 +1,19 @@
.postList {
list-style: none;
padding: 0;
}
.postList-date {
font-size: 0.8rem;
color: var(--fg-primary);
}
.postList-title {
display: inline-block;
padding: 0.5em 0.2em;
font-size: 1.2rem;
&[aria-current="page"] {
font-weight: bold;
}
}

View File

@ -0,0 +1,45 @@
.post-header {
padding: 5vh 0;
}
.post-title {
font-size: 4rem;
font-size: clamp(2rem, 10vw, 4rem);
line-height: 1;
letter-spacing: -0.02em;
margin: 0 0 0.25em;
}
.post-tags {
display: inline;
}
.post-body {
font-size: 1.2em;
line-height: 1.4;
& p,
& ul,
& ol {
max-width: 45em;
}
& h2,
& h3,
& h4,
& h5,
& h6 {
max-width: 20em;
margin-bottom: 0;
}
}
.post-navigation {
& ul {
list-style: none;
padding: 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
& li {
padding: 1em;
}
}

View File

@ -0,0 +1,73 @@
:root {
--bg-primary: #0a0a0a; /* Black */
--bg-secondary: #171717; /* Dark gray */
--accent-primary: #26a269; /* Teal */
--accent-primary-pale: #26a269; /* Teal */
--accent-secondary: #613583; /* Purple */
--accent-secondary-pale: #c061cb; /* Light purple */
--fg-primary: #ffffff; /* White */
--fg-secondary: #f2f2f2; /* Light gray */
--font-family: -apple-system, system-ui, sans-serif;
}
html,
body {
padding: 0;
margin: 0;
font-family: var(--font-family);
color: var(--fg-primary);
background-color: var(--bg-primary);
/** Pagefind variables */
--pagefind-ui-scale: .8;
--pagefind-ui-primary: var(--accent-primary);
--pagefind-ui-text: var(--fg-primary);
--pagefind-ui-background: var(--bg-primary);
--pagefind-ui-border: var(--bg-secondary);
--pagefind-ui-tag: var(--bg-secondary);
--pagefind-ui-border-width: 1px;
--pagefind-ui-border-radius: 6px;
--pagefind-ui-image-border-radius: 6px;
--pagefind-ui-image-box-ratio: 3 / 2;
--pagefind-ui-font: var(--font-family);
}
main {
padding: 5vh 5vw;
& > :first-child {
margin-top: 0;
}
}
a {
color: var(--accent-secondary-pale);
}
/* Warning */
.warning {
background-color: var(--bg-secondary);
padding: 1em 0.5em;
}
table {
margin: 1em 0;
& td,
& th {
padding-right: 1em;
}
}
pre,
code {
font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace;
line-height: 1.5;
font-size: 1rem;
}
hr {
border: 0;
border-top: solid 2px var(--bg-secondary);
margin: 5vh 0;
}

View File

@ -0,0 +1,34 @@
search-form {
}
oom-search::part(input) {
border: solid 2px var(--accent-primary);
border-radius: 4px;
padding: .5em;
background: none;
}
oom-search::part(label) {
font-weight: bold;
}
oom-search::part(input) {
border: solid 2px var(--accent-primary);
border-radius: 4px;
padding: .5em;
background: none;
}
oom-search::part(items) {
padding: .5em;
margin: .5em 0;
box-shadow: 0 2px 3px #0003;
background: var(--bg-primary);
width: auto;
min-width: 100%;
right: 0;
}
oom-search::part(item) {
background: none;
font: inherit;
padding: .5em 1em;
}
oom-search::part(active) {
background-color: var(--bg-primary);
}

16
src/_includes/css/tag.css Normal file
View File

@ -0,0 +1,16 @@
.tag {
display: inline-block;
text-transform: uppercase;
font-size: 0.7rem;
line-height: 1;
padding: 0.2em 0.5em;
margin-right: 0.8em;
background-color: var(--accent-primary);
color: var(--bg-primary);
border-radius: 0.25em;
text-decoration: none;
&.is-big {
font-size: 1rem;
}
}

View File

@ -0,0 +1,30 @@
---
layout: layouts/base.njk
bodyClass: body-tag
---
<h1>{{ title }}</h1>
{% set postslist = results %}
{% include "templates/postslist.njk" %}
<hr>
<nav class="post-navigation">
<ul>
{%- if pagination.previous %}
<li>
<a href="{{ pagination.previous }}" rel="prev">← Previous</a>
</li>
{% endif %}
<li>
Page {{ pagination.page }}
</li>
{%- if pagination.next %}
<li>
<a href="{{ pagination.next }}" rel="next">Next →</a>
</li>
{% endif %}
</ul>
</nav>

View File

@ -0,0 +1,42 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title or site.title }}</title>
<meta name="description" content="{{ description or site.description }}">
<link rel="stylesheet" href="/styles.css">
<link rel="alternate" href="/feed.xml" type="application/atom+xml" title="{{ site.title }}">
<link rel="alternate" href="/feed.json" type="application/json" title="{{ site.title }}">
</head>
<body>
<nav class="navbar">
<a href="/" class="navbar-home">
<strong>{{ site.title }}</strong>
</a>
<ul class="navbar-links">
{%- for entry in search.pages("menu.visible=true", "menu.order") %}
<li>
<a href="{{ entry.data.url }}"{% if entry.data.url == url %} aria-current="page"{% endif %}>
{{ entry.data.menu.title or entry.data.title }}
</a>
</li>
{%- endfor %}
</ul>
<div class="navbar-search">
<div id="search"></div>
</div>
</nav>
<main class="{{ bodyClass }}">
{{ content | safe }}
</main>
<footer></footer>
<!-- Current page: {{ url }} -->
</body>
</html>

View File

@ -0,0 +1,6 @@
---
layout: layouts/base.njk
bodyClass: body-home
---
aaa
{{ content | safe }}

View File

@ -0,0 +1,43 @@
---
layout: layouts/base.njk
bodyClass: body-post
---
<article class="post" data-pagefind-body>
<div class="post-header">
<h1 class="post-title">{{ title }}</h1>
<nav class="post-tags">
{% for tag in tags %}
<a href="/tags/{{ tag }}/" class="tag">{{ tag }}</a>
{% endfor %}
</nav>
<time class="post-date" datetime="{{ date | date('DATETIME') }}">
{{ date | date('HUMAN_DATE') }}
</time>
</div>
<div class="post-body">
{{ content | safe }}
</div>
</article>
<hr>
<nav class="post-navigation">
<ul>
{%- set previousPost = search.previousPage(url, "type=posts") %}
{%- if previousPost %}
<li>
← Previous: <a href="{{ previousPost.data.url }}" rel="prev">{{ previousPost.data.title }}</a>
</li>
{% endif %}
{%- set nextPost = search.nextPage(url, "type=posts") %}
{%- if nextPost %}
<li>
<strong>Next: <a href="{{ nextPost.data.url }}" rel="next">{{ nextPost.data.title }}</a> →</strong>
</li>
{% endif %}
</ul>
</nav>

View File

@ -0,0 +1,14 @@
---
layout: layouts/base.njk
bodyClass: body-tag
---
<div data-pagefind-body>
<h1>Tagged “{{ tag }}”</h1>
{% set postslist = search.pages("'" + tag + "'") %}
{% include "templates/postslist.njk" %}
<hr>
<p>See <a href="/tags/">all tags</a>.</p>
</div>

View File

@ -0,0 +1,24 @@
<ul class="postList">
{% for post in postslist %}
<li class="postList-post">
<a href="{{ post.data.url }}" class="postList-title"{% if entry.data.url == url %} aria-current="page"{% endif %}>
{% if post.data.title %}
<strong>{{ post.data.title }}</strong>
{% else %}
<code>{{ post.url }}</code>
{% endif %}
</a>
<time class="postList-date" datetime="{{ post.data.date | date('DATETIME') }}">
{{ post.data.date | date('HUMAN_DATE') }}
</time>
{% for tag in post.data.tags %}
{% set page = search.page("type=tag tag='" + tag + "'") %}
{% if page %}
<a href="{{ page.data.url }}" class="tag">{{ tag }}</a>
{% endif %}
{% endfor %}
</li>
{% endfor %}
</ul>

10
src/about.md Normal file
View File

@ -0,0 +1,10 @@
---
layout: layouts/post.njk
title: About Me
templateClass: tmpl-post
menu:
visible: true
order: 2
---
I am a person that writes stuff.

28
src/archive.tmpl.js Normal file
View File

@ -0,0 +1,28 @@
export const layout = "layouts/archive.njk";
export const title = "Archive";
export default function* ({ search, paginate }) {
const posts = search.pages("type=posts", "date=desc");
for (
const data of paginate(posts, { url, size: 10 })
) {
// Show the first page in the menu
if (data.pagination.page === 1) {
data.menu = {
visible: true,
order: 1,
};
}
yield data;
}
}
function url(n) {
if (n === 1) {
return "/posts/";
}
return `/posts/${n}/`;
}

11
src/deno.json Normal file
View File

@ -0,0 +1,11 @@
{
"imports": {
"lume/": "https://deno.land/x/lume@v1.17.3/"
},
"lock": false,
"tasks": {
"build": "deno task lume",
"serve": "deno task lume -s",
"lume": "echo \"import 'lume/cli.ts'\" | deno run --unstable -A -"
}
}

0
src/img/.gitkeep Normal file
View File

25
src/index.njk Normal file
View File

@ -0,0 +1,25 @@
---
layout: layouts/home.njk
menu:
visible: true
title: Home
order: 0
---
{% set postslist = search.pages("type=posts", "date=desc", 3) %}
<h1>Latest {% if postslist.length == 1 %}Post{% else %}{{ postslist.length }} Posts{% endif %}</h1>
{% include "templates/postslist.njk" %}
<hr>
{% set postslist = search.pages("pinned=true") %}
{%if postslist.length %}
<h2>Pinned Post:</h1>
{% include "templates/postslist.njk" %}
<hr>
{% endif %}
<p>More posts can be found in <a href="/posts/">the archive</a>.</p>

6
src/netlify.toml Normal file
View File

@ -0,0 +1,6 @@
[build]
publish = "_site"
command = """
curl -fsSL https://deno.land/x/install/install.sh | sh && \
/opt/buildhome/.deno/bin/deno task build --location=https://deno-blog.netlify.app/ \
"""

2
src/posts/_data.yml Normal file
View File

@ -0,0 +1,2 @@
type: posts
layout: layouts/post.njk

10
src/posts/fifthpost.md Normal file
View File

@ -0,0 +1,10 @@
---
title: This is the fifth post (in draft).
description: This post shouldn't be visible in production
date: 2021-01-01
tags:
- second-tag
draft: true
---
To see this post, run `lume --dev`

35
src/posts/firstpost.md Normal file
View File

@ -0,0 +1,35 @@
---
title: This is my first post.
description: This is a post on My Blog about agile frameworks.
date: 2018-05-01
tags:
- another-tag
---
Leverage agile frameworks to provide a robust synopsis for high level overviews.
Iterative approaches to corporate strategy foster collaborative thinking to
further the overall value proposition. Organically grow the holistic world view
of disruptive innovation via workplace diversity and empowerment.
Bring to the table win-win survival strategies to ensure proactive domination.
At the end of the day, going forward, a new normal that has evolved from
generation X is on the runway heading towards a streamlined cloud solution. User
generated content in real-time will have multiple touchpoints for offshoring.
## Section Header
Capitalize on low hanging fruit to identify a ballpark value added activity to
beta test. Override the digital divide with additional clickthroughs from
DevOps. Nanotechnology immersion along the information highway will close the
loop on focusing solely on the bottom line.
```js
// this is a command
function myCommand() {
let counter = 0;
counter++;
}
// Test with a line break above this line.
console.log("Test");
```

24
src/posts/fourthpost.md Normal file
View File

@ -0,0 +1,24 @@
---
title: This is my fourth post.
description: This is a post on My Blog about touchpoints and circling wagons.
date: 2018-09-30
tags:
- second-tag
---
Leverage agile frameworks to provide a robust synopsis for high level overviews.
Iterative approaches to corporate strategy foster collaborative thinking to
further the overall value proposition. Organically grow the holistic world view
of disruptive innovation via workplace diversity and empowerment.
Bring to the table win-win survival strategies to ensure proactive domination.
At the end of the day, going forward, a new normal that has evolved from
generation X is on the runway heading towards a streamlined cloud solution. User
generated content in real-time will have multiple touchpoints for offshoring.
## Section Header
Capitalize on low hanging fruit to identify a ballpark value added activity to
beta test. Override the digital divide with additional clickthroughs from
DevOps. Nanotechnology immersion along the information highway will close the
loop on focusing solely on the bottom line.

28
src/posts/secondpost.md Normal file
View File

@ -0,0 +1,28 @@
---
title: This is my second post.
description: This is a post on My Blog about leveraging agile frameworks.
date: 2018-07-04
tags:
- number-2
- second-tag
---
Leverage agile frameworks to provide a robust synopsis for high level overviews.
Iterative approaches to corporate strategy foster collaborative thinking to
further the overall value proposition. Organically grow the holistic world view
of disruptive innovation via workplace diversity and empowerment.
## Section Header
[First post](firstpost.md) [Third post](thirdpost.md)
Bring to the table win-win survival strategies to ensure proactive domination.
At the end of the day, going forward, a new normal that has evolved from
generation X is on the runway heading towards a streamlined cloud solution. User
generated content in real-time will have multiple touchpoints for offshoring.
Capitalize on low hanging fruit to identify a ballpark value added activity to
beta test. Override the digital divide with additional clickthroughs from
DevOps. Nanotechnology immersion along the information highway will close the
loop on focusing solely on the bottom line.

37
src/posts/thirdpost.md Normal file
View File

@ -0,0 +1,37 @@
---
title: This is my third post.
description: This is a post on My Blog about win-win survival strategies.
date: 2018-08-24
pinned: true
tags:
- second-tag
---
Leverage agile frameworks to provide a robust synopsis for high level overviews.
Iterative approaches to corporate strategy foster collaborative thinking to
further the overall value proposition. Organically grow the holistic world view
of disruptive innovation via workplace diversity and empowerment.
```js
// this is a command
function myCommand() {
let counter = 0;
counter++;
}
// Test with a line break above this line.
console.log("Test");
```
Bring to the table win-win survival strategies to ensure proactive domination.
At the end of the day, going forward, a new normal that has evolved from
generation X is on the runway heading towards a streamlined cloud solution. User
generated content in real-time will have multiple touchpoints for offshoring.
## Section Header
Capitalize on low hanging fruit to identify a ballpark value added activity to
beta test. Override the digital divide with additional clickthroughs from
DevOps. Nanotechnology immersion along the information highway will close the
loop on focusing solely on the bottom line.

25
src/search.tmpl.js Normal file
View File

@ -0,0 +1,25 @@
export const url = "/search.json";
export default function ({ search }, { url }) {
const result = [];
// Search tags
for (const tag of search.tags("type=posts")) {
result.push({
label: `Tag: ${tag}`,
search: tag,
value: url(`/tags/${tag}/`),
});
}
// Search posts
for (const post of search.pages("type=posts")) {
result.push({
label: post.data.title,
search: `${post.data.title} ${post.data.tags.join(" ")}`,
value: url(post.data.url),
});
}
return JSON.stringify(result);
}

18
src/server.ts Normal file
View File

@ -0,0 +1,18 @@
import Server from "lume/core/server.ts";
import expires from "lume/middlewares/expires.ts";
import notFound from "lume/middlewares/not_found.ts";
const server = new Server({
port: 8000,
root: `${Deno.cwd()}/_site`,
});
server.use(expires());
server.use(notFound({
root: `${Deno.cwd()}/_site`,
page404: "/404.html",
}));
server.start();
console.log("Listening on http://localhost:8000");

9
src/styles.css Normal file
View File

@ -0,0 +1,9 @@
/* Code syntax highlight */
@import "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.0.0/build/styles/github-dark.min.css";
@import "css/reset.css";
@import "css/navbar.css";
@import "css/search.css";
@import "css/post-list.css";
@import "css/post.css";
@import "css/tag.css";

12
src/tag.tmpl.js Normal file
View File

@ -0,0 +1,12 @@
export const layout = "layouts/tag.njk";
export default function* ({ search }) {
for (const tag of search.tags()) {
yield {
url: `/tags/${tag}/`,
title: `Tagged “${tag}`,
type: "tag",
tag,
};
}
}

8
src/tags.njk Normal file
View File

@ -0,0 +1,8 @@
---
layout: layouts/base.njk
---
<h1>Tags</h1>
{% for page in search.pages("type=tag", "tag") %}
<a href="{{ page.data.url }}" class="tag is-big">{{ page.data.tag }}</a>
{% endfor %}