init
This commit is contained in:
88
routes/index.server.ts
Normal file
88
routes/index.server.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { html, htmlToResponse } from "@mastrojs/mastro";
|
||||
import { Layout } from "../components/Layout.ts";
|
||||
|
||||
export const GET = () =>
|
||||
htmlToResponse(
|
||||
Layout({
|
||||
title: "Home",
|
||||
children: html`
|
||||
<nav>
|
||||
<p>👉 <a href="/news/">News</a></p>
|
||||
</nav>
|
||||
|
||||
<h1>Common HTML elements</h1>
|
||||
<p>
|
||||
Let's go through the most important HTML elements to
|
||||
structure your content:
|
||||
</p>
|
||||
|
||||
<h2>Paragraphs</h2>
|
||||
<p>The p element marks a paragraph of text.</p>
|
||||
|
||||
<h2>Headings</h2>
|
||||
<p>
|
||||
At the very top of the body, we have the heading of this page
|
||||
in an h1 element. This is what search engines (like Google)
|
||||
and screen readers (used by visually impaired readers) look for
|
||||
when they want to know what the page's title is. Therefore, you
|
||||
should only ever have one h1 element on any given page.
|
||||
</p>
|
||||
<p>
|
||||
The h2 element is a sub-heading. HTML has h1 up to h6 elements,
|
||||
to mark progressively deeper nested sub-headings. You should
|
||||
use those to mark the structure of your page. All headings
|
||||
together should act like a table of contents for your page.
|
||||
</p>
|
||||
|
||||
<h2>Lists</h2>
|
||||
<p>
|
||||
Let's add an ordered list
|
||||
(meaning the list markers will be numbers):
|
||||
</p>
|
||||
<ol>
|
||||
<li>list item one</li>
|
||||
<li>list item two</li>
|
||||
<li>list item three</li>
|
||||
</ol>
|
||||
<p>
|
||||
and an unordered list
|
||||
(the list markers will be bullet points):
|
||||
</p>
|
||||
<ul>
|
||||
<li>list item one</li>
|
||||
<li>list item two</li>
|
||||
<li>list item three</li>
|
||||
</ul>
|
||||
|
||||
<h2>Formatting</h2>
|
||||
<p>
|
||||
Note how all elements introduced so far cause a line-break
|
||||
before and after them? That's because they are so-called
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Glossary/Block-level_content">block elements</a>.
|
||||
</p>
|
||||
<p>
|
||||
However, links (like the a element we just saw),
|
||||
<em>emphasis</em> (rendered as italics), and
|
||||
<strong>strong emphasis</strong> (rendered bold),
|
||||
are all inline elements. That means they don't cause
|
||||
any line-breaks by default.
|
||||
</p>
|
||||
|
||||
<h2>An image</h2>
|
||||
<img src="chair.jpg" alt="A chair" height="300">
|
||||
<p>
|
||||
We will add an image file <code>chair.jpg</code> later.
|
||||
</p>
|
||||
<p>
|
||||
For now, note the alt attribute on the image. It is required
|
||||
and contains "alternative text" that is read to visually
|
||||
impaired readers, or shown if the image fails to load.
|
||||
</p>
|
||||
<p>
|
||||
If the image is relevant content, the alt text should
|
||||
therefore be a brief description of what's in the image.
|
||||
If the image is just decoration, you should use alt="".
|
||||
</p>
|
||||
`,
|
||||
}),
|
||||
);
|
||||
19
routes/news/[slug]/index.server.ts
Normal file
19
routes/news/[slug]/index.server.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { getParams, htmlToResponse, readDir } from "@mastrojs/mastro";
|
||||
import { readMarkdownFile } from "@mastrojs/markdown";
|
||||
import { Layout } from "../../../components/Layout.ts";
|
||||
|
||||
export const GET = async (req: Request) => {
|
||||
const { slug } = getParams(req);
|
||||
const post = await readMarkdownFile(`data/posts/${slug}.md`);
|
||||
return htmlToResponse(
|
||||
Layout({
|
||||
title: post.meta.title,
|
||||
children: post.content,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
export const getStaticPaths = async () => {
|
||||
const posts = await readDir("data/posts/");
|
||||
return posts.map((p) => "/news/" + p.slice(0, -3) + "/");
|
||||
};
|
||||
21
routes/news/index.server.ts
Normal file
21
routes/news/index.server.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { html, htmlToResponse } from "@mastrojs/mastro";
|
||||
import { readMarkdownFiles } from "@mastrojs/markdown";
|
||||
import { Layout } from "../../components/Layout.ts";
|
||||
|
||||
export const GET = async () => {
|
||||
const posts = await readMarkdownFiles("data/posts/*.md");
|
||||
return htmlToResponse(
|
||||
Layout({
|
||||
title: "News",
|
||||
children: posts.map((post) =>
|
||||
html`
|
||||
<p>
|
||||
<a href="${post.path.slice(12, -3) + "/"}">
|
||||
${post.meta.title}
|
||||
</a>
|
||||
</p>
|
||||
`
|
||||
),
|
||||
}),
|
||||
);
|
||||
};
|
||||
129
routes/styles.css
Normal file
129
routes/styles.css
Normal file
@@ -0,0 +1,129 @@
|
||||
/* 1. Use a more-intuitive box-sizing model */
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 2. Remove default margin */
|
||||
*:not(dialog) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 3. Enable keyword animations */
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
html {
|
||||
interpolate-size: allow-keywords;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
/* 4. Add accessible line-height */
|
||||
line-height: 1.5;
|
||||
/* 5. Improve text rendering */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* 6. Improve media defaults */
|
||||
img,
|
||||
picture,
|
||||
video,
|
||||
canvas,
|
||||
svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* 7. Inherit fonts for form controls */
|
||||
input,
|
||||
button,
|
||||
textarea,
|
||||
select {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
/* 8. Avoid text overflows */
|
||||
p,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* 9. Improve line wrapping */
|
||||
p {
|
||||
text-wrap: pretty;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
/*
|
||||
10. Create a root stacking context
|
||||
*/
|
||||
#root,
|
||||
#__next {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
/*
|
||||
real css
|
||||
*/
|
||||
|
||||
body {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
min-height: 100vh;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
margin: 0 auto;
|
||||
--brand-color: rebeccapurple;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: var(--brand-color);
|
||||
color: whitesmoke;
|
||||
font-weight: bold;
|
||||
font-size: 50px;
|
||||
padding: 1.5em 1em 1em 1em;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: var(--brand-color);
|
||||
color: whitesmoke;
|
||||
padding: 2em 1em;
|
||||
margin-top: 3em;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
header > div,
|
||||
main,
|
||||
footer > div {
|
||||
width: 100%;
|
||||
max-width: 30rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
header > a,
|
||||
a:visited {
|
||||
color: white;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration-line: none;
|
||||
}
|
||||
Reference in New Issue
Block a user