update: add headings overview
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# blog.hareworks.net
|
||||
|
||||
<img src="https://blog.hareworks.net/img/logo.png" width="200">
|
||||
<img src="./static/img/logo.png" width="200">
|
||||
|
||||
## About
|
||||
|
||||
|
||||
-1
Submodule articles deleted from 1b15e59b0b
Generated
-4149
File diff suppressed because it is too large
Load Diff
+25
-23
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blog.hareworks.net",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -13,32 +13,34 @@
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.28.1",
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-node": "^5.2.2",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.0-next.6",
|
||||
"@types/eslint": "^9.6.0",
|
||||
"@types/pg": "^8.11.6",
|
||||
"eslint": "^9.0.0",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@sveltejs/adapter-auto": "^3.3.1",
|
||||
"@sveltejs/adapter-node": "^5.2.10",
|
||||
"@sveltejs/kit": "^2.12.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.2",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/pg": "^8.11.10",
|
||||
"eslint": "^9.17.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.36.0",
|
||||
"globals": "^15.0.0",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.1.2",
|
||||
"shiki": "^1.16.2",
|
||||
"svelte": "^5.0.0-next.1",
|
||||
"svelte-check": "^3.6.0",
|
||||
"typescript": "^5.0.0",
|
||||
"typescript-eslint": "^8.0.0",
|
||||
"vite": "^5.0.3"
|
||||
"eslint-plugin-svelte": "^2.46.1",
|
||||
"globals": "^15.13.0",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.2",
|
||||
"shiki": "^1.24.2",
|
||||
"svelte": "^5.14.1",
|
||||
"svelte-check": "4.1.1",
|
||||
"typescript": "^5.7.2",
|
||||
"typescript-eslint": "^8.18.1",
|
||||
"vite": "^6.0.3"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"dotenv": "^16.4.5",
|
||||
"dotenv": "^16.4.7",
|
||||
"mdsvex": "^0.12.3",
|
||||
"pg": "^8.12.0",
|
||||
"sass": "^1.77.8",
|
||||
"simple-git": "^3.26.0"
|
||||
"pg": "^8.13.1",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"sass": "^1.83.0",
|
||||
"simple-git": "^3.27.0"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+3127
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,5 +1,5 @@
|
||||
@import './ress.css';
|
||||
@import '../variables.scss';
|
||||
@forward './ress.css';
|
||||
@forward '../variables.scss';
|
||||
|
||||
@font-face {
|
||||
font-family: 'ZenKakuGothicNew-Regular';
|
||||
|
||||
@@ -71,6 +71,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
padding-left: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
&::before {
|
||||
content: '•';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
color: var(--color-concept);
|
||||
}
|
||||
}
|
||||
ul > li {
|
||||
&::before {
|
||||
content: '•';
|
||||
}
|
||||
}
|
||||
ol > li {
|
||||
counter-increment: item;
|
||||
&::before {
|
||||
content: counter(item) '.';
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
position: relative;
|
||||
font-size: 1.1rem;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<script lang="ts">
|
||||
export let html: string;
|
||||
|
||||
const headings: {
|
||||
level: number;
|
||||
id: string;
|
||||
text: string;
|
||||
}[] = [];
|
||||
html.match(/<h(\d) id="([^"]+)">([^<]+)<\/h\d>/g)?.forEach((match) => {
|
||||
console.log(match);
|
||||
const [, level, id, text] = match.match(/<h(\d) id="([^"]+)">([^<]+)<\/h\d>/)!;
|
||||
headings.push({ level: +level, id, text });
|
||||
});
|
||||
let output = '';
|
||||
let lastLevel = 1;
|
||||
headings.forEach(({ level, id, text }) => {
|
||||
console.log(level, id, text);
|
||||
if (level > lastLevel) {
|
||||
output += '<ul>';
|
||||
} else if (level < lastLevel) {
|
||||
output += '</li></ul>'.repeat(lastLevel - level);
|
||||
} else {
|
||||
if (output !== '') {
|
||||
}
|
||||
}
|
||||
output += `<li><a href="#${id}">${text}</a>`;
|
||||
lastLevel = level;
|
||||
});
|
||||
output += '</li>'.repeat(lastLevel);
|
||||
</script>
|
||||
|
||||
<div class="overview">
|
||||
<ul>
|
||||
{@html output}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.overview {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
:global(ul) {
|
||||
list-style-type: none;
|
||||
margin-left: 0.5em;
|
||||
padding-left: 0.25em;
|
||||
border-left: 1px solid var(--line-primary);
|
||||
}
|
||||
ul {
|
||||
border-left: none;
|
||||
}
|
||||
:global(li) {
|
||||
padding: 0.5em 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:global(a) {
|
||||
text-decoration: none;
|
||||
color: var(--text-primary);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 0.25em;
|
||||
text-wrap: nowrap;
|
||||
box-sizing: border-box;
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -5,6 +5,7 @@
|
||||
import Footer from '$lib/components/footer.svelte';
|
||||
import * as publish from '$lib/publish';
|
||||
import FormattedDate from '$lib/components/formatted_date.svelte';
|
||||
import Overview from '$lib/components/overview.svelte';
|
||||
|
||||
import type { Article } from '$lib/article';
|
||||
export let data: Article;
|
||||
@@ -32,39 +33,46 @@
|
||||
</div> -->
|
||||
<div class="container">
|
||||
<main>
|
||||
<div class="title">
|
||||
<h1>{data.title}</h1>
|
||||
<div class="meta">
|
||||
<div class="left">
|
||||
<span>
|
||||
released <FormattedDate date={data.released_at} />
|
||||
{#if isUpdated}<br />
|
||||
updated <FormattedDate date={data.updated_at} />
|
||||
{/if}
|
||||
</span>
|
||||
<span>
|
||||
<a href="/category/{data.category}"
|
||||
>{data.category[0].toUpperCase() + data.category.slice(1)}</a
|
||||
>
|
||||
{#each data.tags as tag}
|
||||
<a href={`/search?tag=${tag}`}>{tag}</a>
|
||||
{/each}
|
||||
</span>
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
<h1>{data.title}</h1>
|
||||
<div class="meta">
|
||||
<div class="left">
|
||||
<span>
|
||||
released <FormattedDate date={data.released_at} />
|
||||
{#if isUpdated}<br />
|
||||
updated <FormattedDate date={data.updated_at} />
|
||||
{/if}
|
||||
</span>
|
||||
<span>
|
||||
<a href="/category/{data.category}"
|
||||
>{data.category[0].toUpperCase() + data.category.slice(1)}</a
|
||||
>
|
||||
{#each data.tags as tag}
|
||||
<a href={`/search?tag=${tag}`}>{tag}</a>
|
||||
{/each}
|
||||
</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<img
|
||||
src="https://gitea.hareworks.net/avatars/e595ec10f8052671deab92caca78220fc838f63259bcd542a0d93f53e2371d52?size=512"
|
||||
alt="Author"
|
||||
/>
|
||||
<div>@{data.author}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<img
|
||||
src="https://gitea.hareworks.net/avatars/e595ec10f8052671deab92caca78220fc838f63259bcd542a0d93f53e2371d52?size=512"
|
||||
alt="Author"
|
||||
/>
|
||||
<div>@{data.author}</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="document">
|
||||
<slot />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="document">
|
||||
<slot />
|
||||
<div class="card-container">
|
||||
<div class="card">
|
||||
<Overview html={data.content} />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
@@ -100,25 +108,43 @@
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.card {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
border: 1px solid var(--line-primary);
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
box-sizing: border-box;
|
||||
color: white;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: start;
|
||||
.content {
|
||||
border: 1px solid var(--line-primary);
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
min-height: 100%;
|
||||
padding: 20px;
|
||||
padding-top: 100px;
|
||||
max-width: 800px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.card-container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
overflow-y: auto;
|
||||
background-color: var(--background-primary);
|
||||
box-sizing: border-box;
|
||||
padding: 20px;
|
||||
padding-top: 100px;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.card {
|
||||
width: 300px;
|
||||
padding: 0.5em 0;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import { compile, escapeSvelte } from "mdsvex";
|
||||
import { createHighlighter } from "shiki";
|
||||
import { kanagawa_dark as theme } from "$lib/kanagawa"
|
||||
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
|
||||
const highlighter = await createHighlighter({
|
||||
themes: [theme],
|
||||
@@ -19,5 +20,6 @@ export default async function compileArticle(code: string) {
|
||||
return html;
|
||||
},
|
||||
},
|
||||
rehypePlugins: [rehypeSlug],
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Postgres } from '$lib/server/database/postgres';
|
||||
import { type SimpleGit, CheckRepoActions } from 'simple-git';
|
||||
import fs from 'fs';
|
||||
import compile from '$lib/server/article_compiler';
|
||||
import compileArticle from '$lib/server/article_compiler';
|
||||
import type { TableSchema } from '$lib/server/database/table';
|
||||
import server_table from '$lib/server/database/table';
|
||||
import { format } from '$lib/scripts/formatted_date';
|
||||
@@ -33,7 +33,7 @@ const load = async (db: Postgres, git: SimpleGit) => {
|
||||
console.log(`Author: ${author} <${email}>\nReleased at: ${format(released_at)}\nUpdated at: ${format(updated_at)}`);
|
||||
|
||||
const category = path.split('/')[3];
|
||||
const compiled = await compile(fs.readFileSync(path, 'utf-8'));
|
||||
const compiled = await compileArticle(fs.readFileSync(path, 'utf-8'));
|
||||
const title = compiled.data.fm.title;
|
||||
const tags: string[] = compiled.data.fm.tags;
|
||||
const image = compiled.data.fm.image;
|
||||
|
||||
@@ -3,14 +3,9 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
const config = {
|
||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
||||
// for more information about preprocessors
|
||||
preprocess: vitePreprocess(),
|
||||
|
||||
kit: {
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
||||
adapter: adapter()
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user