Links in markdown headings, corrected date

This commit is contained in:
DarkCat09 2023-06-18 18:55:51 +04:00
parent 8849d70735
commit 70b0893df8
5 changed files with 188 additions and 39 deletions

View file

@ -2,6 +2,9 @@ import { defineConfig } from 'astro/config';
import compress from "astro-compress"; import compress from "astro-compress";
import remarkUnwrapImages from 'remark-unwrap-images'; import remarkUnwrapImages from 'remark-unwrap-images';
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
@ -12,5 +15,13 @@ export default defineConfig({
markdown: { markdown: {
syntaxHighlight: "shiki", syntaxHighlight: "shiki",
remarkPlugins: [remarkUnwrapImages], remarkPlugins: [remarkUnwrapImages],
rehypePlugins: [
rehypeSlug,
rehypeHeadingIds,
[
rehypeAutolinkHeadings,
{ behavior: "append" },
],
],
}, },
}); });

174
package-lock.json generated
View file

@ -10,6 +10,8 @@
"astro": "^2.3.0", "astro": "^2.3.0",
"astro-compress": "^1.1.42", "astro-compress": "^1.1.42",
"less": "^4.1.3", "less": "^4.1.3",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-unwrap-images": "^3.0.1" "remark-unwrap-images": "^3.0.1"
} }
}, },
@ -2508,6 +2510,40 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/hast-util-has-property": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz",
"integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-heading-rank": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-2.1.1.tgz",
"integrity": "sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==",
"dependencies": {
"@types/hast": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-is-element": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz",
"integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/unist": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-parse-selector": { "node_modules/hast-util-parse-selector": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz",
@ -2581,6 +2617,18 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/hast-util-to-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz",
"integrity": "sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==",
"dependencies": {
"@types/hast": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-whitespace": { "node_modules/hast-util-whitespace": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz",
@ -4605,6 +4653,24 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/rehype-autolink-headings": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-6.1.1.tgz",
"integrity": "sha512-NMYzZIsHM3sA14nC5rAFuUPIOfg+DFmf9EY1YMhaNlB7+3kK/ZlE6kqPfuxr1tsJ1XWkTrMtMoyHosU70d35mA==",
"dependencies": {
"@types/hast": "^2.0.0",
"extend": "^3.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-heading-rank": "^2.0.0",
"hast-util-is-element": "^2.0.0",
"unified": "^10.0.0",
"unist-util-visit": "^4.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-parse": { "node_modules/rehype-parse": {
"version": "8.0.4", "version": "8.0.4",
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz",
@ -4634,6 +4700,24 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/rehype-slug": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-5.1.0.tgz",
"integrity": "sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==",
"dependencies": {
"@types/hast": "^2.0.0",
"github-slugger": "^2.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-heading-rank": "^2.0.0",
"hast-util-to-string": "^2.0.0",
"unified": "^10.0.0",
"unist-util-visit": "^4.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-stringify": { "node_modules/rehype-stringify": {
"version": "9.0.3", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-9.0.3.tgz", "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-9.0.3.tgz",
@ -4850,9 +4934,9 @@
} }
}, },
"node_modules/rollup": { "node_modules/rollup": {
"version": "3.20.6", "version": "3.25.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.6.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz",
"integrity": "sha512-2yEB3nQXp/tBQDN0hJScJQheXdvU2wFhh6ld7K/aiZ1vYcak6N/BKjY1QrU6BvO2JWYS8bEs14FRaxXosxy2zw==", "integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==",
"bin": { "bin": {
"rollup": "dist/bin/rollup" "rollup": "dist/bin/rollup"
}, },
@ -5778,13 +5862,13 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "4.3.0", "version": "4.3.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.0.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
"integrity": "sha512-JTGFgDh3dVxeGBpuQX04Up+JZmuG6wu9414Ei36vQzaEruY/M4K0AgwtuB2b4HaBgB7R8l+LHxjB0jcgz4d2qQ==", "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==",
"dependencies": { "dependencies": {
"esbuild": "^0.17.5", "esbuild": "^0.17.5",
"postcss": "^8.4.21", "postcss": "^8.4.23",
"rollup": "^3.20.2" "rollup": "^3.21.0"
}, },
"bin": { "bin": {
"vite": "bin/vite.js" "vite": "bin/vite.js"
@ -7808,6 +7892,28 @@
"web-namespaces": "^2.0.0" "web-namespaces": "^2.0.0"
} }
}, },
"hast-util-has-property": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz",
"integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg=="
},
"hast-util-heading-rank": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-2.1.1.tgz",
"integrity": "sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==",
"requires": {
"@types/hast": "^2.0.0"
}
},
"hast-util-is-element": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz",
"integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==",
"requires": {
"@types/hast": "^2.0.0",
"@types/unist": "^2.0.0"
}
},
"hast-util-parse-selector": { "hast-util-parse-selector": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz",
@ -7865,6 +7971,14 @@
"zwitch": "^2.0.0" "zwitch": "^2.0.0"
} }
}, },
"hast-util-to-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz",
"integrity": "sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==",
"requires": {
"@types/hast": "^2.0.0"
}
},
"hast-util-whitespace": { "hast-util-whitespace": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz",
@ -9169,6 +9283,20 @@
"unified": "^10.0.0" "unified": "^10.0.0"
} }
}, },
"rehype-autolink-headings": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-6.1.1.tgz",
"integrity": "sha512-NMYzZIsHM3sA14nC5rAFuUPIOfg+DFmf9EY1YMhaNlB7+3kK/ZlE6kqPfuxr1tsJ1XWkTrMtMoyHosU70d35mA==",
"requires": {
"@types/hast": "^2.0.0",
"extend": "^3.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-heading-rank": "^2.0.0",
"hast-util-is-element": "^2.0.0",
"unified": "^10.0.0",
"unist-util-visit": "^4.0.0"
}
},
"rehype-parse": { "rehype-parse": {
"version": "8.0.4", "version": "8.0.4",
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz",
@ -9190,6 +9318,20 @@
"unified": "^10.0.0" "unified": "^10.0.0"
} }
}, },
"rehype-slug": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-5.1.0.tgz",
"integrity": "sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==",
"requires": {
"@types/hast": "^2.0.0",
"github-slugger": "^2.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-heading-rank": "^2.0.0",
"hast-util-to-string": "^2.0.0",
"unified": "^10.0.0",
"unist-util-visit": "^4.0.0"
}
},
"rehype-stringify": { "rehype-stringify": {
"version": "9.0.3", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-9.0.3.tgz", "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-9.0.3.tgz",
@ -9341,9 +9483,9 @@
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
}, },
"rollup": { "rollup": {
"version": "3.20.6", "version": "3.25.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.6.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz",
"integrity": "sha512-2yEB3nQXp/tBQDN0hJScJQheXdvU2wFhh6ld7K/aiZ1vYcak6N/BKjY1QrU6BvO2JWYS8bEs14FRaxXosxy2zw==", "integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==",
"requires": { "requires": {
"fsevents": "~2.3.2" "fsevents": "~2.3.2"
} }
@ -9962,14 +10104,14 @@
} }
}, },
"vite": { "vite": {
"version": "4.3.0", "version": "4.3.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.3.0.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz",
"integrity": "sha512-JTGFgDh3dVxeGBpuQX04Up+JZmuG6wu9414Ei36vQzaEruY/M4K0AgwtuB2b4HaBgB7R8l+LHxjB0jcgz4d2qQ==", "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==",
"requires": { "requires": {
"esbuild": "^0.17.5", "esbuild": "^0.17.5",
"fsevents": "~2.3.2", "fsevents": "~2.3.2",
"postcss": "^8.4.21", "postcss": "^8.4.23",
"rollup": "^3.20.2" "rollup": "^3.21.0"
} }
}, },
"vitefu": { "vitefu": {

View file

@ -13,6 +13,8 @@
"astro": "^2.3.0", "astro": "^2.3.0",
"astro-compress": "^1.1.42", "astro-compress": "^1.1.42",
"less": "^4.1.3", "less": "^4.1.3",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-unwrap-images": "^3.0.1" "remark-unwrap-images": "^3.0.1"
} }
} }

View file

@ -10,7 +10,7 @@ const { code } = Astro.props;
<span class="icon">{code}</span> <span class="icon">{code}</span>
<style lang="less"> <style lang="less" is:global>
@font-face { @font-face {
font-family: 'Line Awesome Regular'; font-family: 'Line Awesome Regular';
font-style: normal; font-style: normal;

View file

@ -1,6 +1,5 @@
--- ---
import BlogLayout from "../../layouts/BlogLayout.astro"; import BlogLayout from "../../layouts/BlogLayout.astro";
import Icon from "../../components/Icon.astro";
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
@ -44,15 +43,16 @@ const description = post.body
.trim() + '\u2026'; // 2026 = ellipsis .trim() + '\u2026'; // 2026 = ellipsis
let dateStr = slug.split("-", 1)[0]; let dateStr = slug.split("-", 1)[0];
let date: string | undefined; let date: Date | undefined;
if (isNaN(Number(dateStr))) { if (isNaN(Number(dateStr))) {
dateStr = undefined; dateStr = undefined;
} }
else { else {
date = date = new Date(
`${dateStr.slice(0,4)}-` + `${dateStr.slice(0,4)}-` +
`${dateStr.slice(4,6)}-` + `${dateStr.slice(4,6)}-` +
`${dateStr.slice(6,8)}`; `${dateStr.slice(6,8)}`
)
} }
const image = (post.body.match(/(?:\s|^)!\[.*\]\((.*?)\)/) || [])[1]; const image = (post.body.match(/(?:\s|^)!\[.*\]\((.*?)\)/) || [])[1];
@ -64,20 +64,17 @@ const image = (post.body.match(/(?:\s|^)!\[.*\]\((.*?)\)/) || [])[1];
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:description" content={description} /> <meta property="og:description" content={description} />
<meta property="og:image" content={image} /> <meta property="og:image" content={image} />
<meta property="article:published_time" content={date} /> <meta property="article:published_time" content={date.toISOString()} />
<meta property="article:author" content="DarkCat09" /> <meta property="article:author" content="DarkCat09" />
<meta property="twitter:card" content="summary" /> <meta property="twitter:card" content="summary" />
<meta property="twitter:title" content={title} /> <meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content={image} /> <meta property="twitter:image" content={image} />
</Fragment> </Fragment>
<span id="link-icon" style="display: none;">
<Icon code="&#xf0c1;" />
</span>
<header> <header>
<h1>{title}</h1> <h1>{title}</h1>
<address> <address>
<time datetime={date}>{date}</time>, <time datetime={date.toISOString()}>{date.toLocaleDateString()}</time>,
<a href="https://t.me/dcat09" rel="author">DarkCat09</a> <a href="https://t.me/dcat09" rel="author">DarkCat09</a>
</address> </address>
</header> </header>
@ -97,6 +94,16 @@ const image = (post.body.match(/(?:\s|^)!\[.*\]\((.*?)\)/) || [])[1];
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
margin: 0; margin: 0;
span.icon::before {
content: "\f0c1";
font-size: 1.1rem;
display: none;
}
&:hover span.icon::before {
display: inline-block;
}
} }
.heading-link { .heading-link {
@ -156,16 +163,3 @@ const image = (post.body.match(/(?:\s|^)!\[.*\]\((.*?)\)/) || [])[1];
} }
} }
</style> </style>
<script>
const linkIcon = document.getElementById("link-icon").innerHTML || "";
const hs = document.querySelectorAll("article h1,h2,h3");
for (let h of hs) {
const link = document.createElement("a");
link.classList.add("heading-link");
link.innerHTML = linkIcon;
link.href = "#" + h.id;
h.append(link);
}
</script>