add: wikibonsai changes.
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
# Astro Starter Kit: Blog
|
||||
# Astro-WikiBonsai
|
||||
|
||||
```sh
|
||||
npm create astro@latest -- --template blog
|
||||
```
|
||||
[](https://github.com/wikibonsai/wikibonsai)
|
||||
|
||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog)
|
||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/blog)
|
||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/blog/devcontainer.json)
|
||||
An [Astro base blog](https://github.com/withastro/astro/tree/main/examples/blog) with [wikibonsai](https://github.com/wikibonsai/wikibonsai) support.
|
||||
|
||||
💐 Display your [🎋 WikiBonsai](https://github.com/wikibonsai/wikibonsai) digital garden for others.
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
@@ -38,6 +36,12 @@ Inside of your Astro project, you'll see the following folders and files:
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
#todo
|
||||
|
||||
- entries
|
||||
- index
|
||||
- when defining the tree in 'i.bonsai.md', be sure there is a single root node so that the entire tree is processed properly.
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
+36
-4
@@ -1,10 +1,42 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import mdx from '@astrojs/mdx';
|
||||
import { base, defineConfig } from 'astro/config';
|
||||
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
|
||||
import { remarkWikiRefs } from 'remark-wikirefs';
|
||||
import { remarkCaml } from 'remark-caml';
|
||||
|
||||
import {
|
||||
resolveHtmlHref,
|
||||
resolveHtmlText,
|
||||
resolveEmbedContent,
|
||||
generateForeRefsRemarkPlugin,
|
||||
} from './src/wikibonsai/wikirefs';
|
||||
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: 'https://example.com',
|
||||
integrations: [mdx(), sitemap()],
|
||||
site: 'https://astro-wikibonsai.netlify.app',
|
||||
integrations: [
|
||||
sitemap(),
|
||||
],
|
||||
assetsInclude: true,
|
||||
markdown: {
|
||||
// Preserve Astro's default plugins: GitHub-flavored Markdown and Smartypants
|
||||
extendDefaultPlugins: true,
|
||||
// Applied to .md and .mdx files
|
||||
remarkPlugins: [
|
||||
remarkCaml,
|
||||
[
|
||||
remarkWikiRefs,
|
||||
{
|
||||
baseUrl: base,
|
||||
resolveHtmlHref: resolveHtmlHref,
|
||||
resolveHtmlText: resolveHtmlText,
|
||||
resolveEmbedContent: resolveEmbedContent,
|
||||
},
|
||||
],
|
||||
// this plugin is necessary for backrefs to work
|
||||
generateForeRefsRemarkPlugin,
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
+18
-1
@@ -2,6 +2,16 @@
|
||||
"name": "astro-wikibonsai",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"description": "A starter project for a WikiBonsai digital garden using the Astro static site generator.",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "manunamz",
|
||||
"email": "manuanmz@pm.me"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wikibonsai/astro-wikibonsai"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
@@ -13,6 +23,13 @@
|
||||
"@astrojs/mdx": "^1.1.0",
|
||||
"@astrojs/rss": "^3.0.0",
|
||||
"@astrojs/sitemap": "^3.0.0",
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.1.4",
|
||||
"fast-glob": "^3.3.1",
|
||||
"gray-matter": "^4.0.3",
|
||||
"remark-caml": "^0.0.5-rm",
|
||||
"remark-wikirefs": "^0.0.6-rm",
|
||||
"semtree": "^0.0.2",
|
||||
"unist-util-select": "^5.0.0",
|
||||
"wikirefs": "^0.0.4"
|
||||
}
|
||||
}
|
||||
Executable
+81
@@ -0,0 +1,81 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 583.03 399.59">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #8c6239;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: none;
|
||||
stroke: #8c6239;
|
||||
stroke-miterlimit: 10;
|
||||
stroke-width: 10px;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #31af31;
|
||||
}
|
||||
|
||||
.cls-4 {
|
||||
fill: #5c5962;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_2" data-name="Layer 2">
|
||||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path class="cls-1" d="M155.05,219.83a41.35,41.35,0,0,0,1,6.4,47.68,47.68,0,0,0,2.16,6.47,56.53,56.53,0,0,0,6.91,12.22,71.84,71.84,0,0,0,9.63,10.67l2.76,2.38c.94.78,1.94,1.49,2.9,2.25,2,1.48,4,2.89,6.09,4.21a105.38,105.38,0,0,0,13.25,7.05,117.12,117.12,0,0,0,14.31,5.34c4.92,1.46,10,2.67,15.08,3.66,2.57.42,5.14.93,7.74,1.21l3.9.5,3.93.36c2.6.27,5.27.34,7.91.52l4.18.25c.72.07,1.43.06,2.15.18l2.15.34a51.45,51.45,0,0,1,16.25,5.64,53.43,53.43,0,0,1,13.41,10.41A50.61,50.61,0,0,1,300,314a43.63,43.63,0,0,1,3.66,16.26,53.33,53.33,0,0,1-1.87,16.33,60.27,60.27,0,0,1-6.42,14.95,62.45,62.45,0,0,1-9.93,12.73l-.06-.06a61.81,61.81,0,0,0,9.1-13.16,57.91,57.91,0,0,0,5.41-14.92,51.19,51.19,0,0,0,.79-15.65,40.32,40.32,0,0,0-4.33-14.75,46.28,46.28,0,0,0-21.84-20.57,44.53,44.53,0,0,0-14.37-3.87l-1.84-.16c-.61-.07-1.25,0-1.87,0-1.28,0-2.43,0-3.89.06-2.72,0-5.43.19-8.19.13-5.49.07-11-.24-16.54-.61a165.09,165.09,0,0,1-16.59-2.24,131,131,0,0,1-16.4-4.37,101,101,0,0,1-15.74-7,90.35,90.35,0,0,1-14.43-9.87,77.76,77.76,0,0,1-12.19-13c-.91-1.19-1.7-2.48-2.55-3.71s-1.56-2.59-2.33-3.88-1.41-2.69-2.05-4.06-1.27-2.77-1.76-4.23l-.78-2.17c-.24-.73-.44-1.48-.66-2.22-.47-1.46-.76-3-1.11-4.53a46.53,46.53,0,0,1-.78-9.59Z" />
|
||||
<line class="cls-2" x1="112.41" y1="78.94" x2="143.58" y2="23.49" />
|
||||
<line class="cls-2" x1="143.58" y1="23.49" x2="173.76" y2="78.94" />
|
||||
<line class="cls-2" x1="173.76" y1="78.94" x2="205.22" y2="23.49" />
|
||||
<line class="cls-2" x1="205.22" y1="23.49" x2="235.11" y2="78.94" />
|
||||
<line class="cls-2" x1="235.11" y1="78.94" x2="266.85" y2="23.49" />
|
||||
<line class="cls-2" x1="266.85" y1="23.49" x2="298.44" y2="78.94" />
|
||||
<line class="cls-2" x1="298.44" y1="78.94" x2="329.3" y2="23.49" />
|
||||
<line class="cls-2" x1="329.3" y1="23.49" x2="362.49" y2="78.94" />
|
||||
<line class="cls-2" x1="309.46" y1="196.33" x2="340.64" y2="140.89" />
|
||||
<line class="cls-2" x1="340.64" y1="140.89" x2="370.81" y2="196.33" />
|
||||
<line class="cls-2" x1="370.81" y1="196.33" x2="402.27" y2="140.89" />
|
||||
<line class="cls-2" x1="402.27" y1="140.89" x2="432.16" y2="196.33" />
|
||||
<line class="cls-2" x1="432.16" y1="196.33" x2="463.9" y2="140.89" />
|
||||
<line class="cls-2" x1="463.9" y1="140.89" x2="495.49" y2="196.33" />
|
||||
<line class="cls-2" x1="495.49" y1="196.33" x2="526.35" y2="140.89" />
|
||||
<line class="cls-2" x1="526.35" y1="140.89" x2="559.54" y2="196.33" />
|
||||
<line class="cls-2" x1="54.67" y1="145.12" x2="84.84" y2="200.56" />
|
||||
<line class="cls-2" x1="146.19" y1="200.56" x2="176.63" y2="145.12" />
|
||||
<line class="cls-2" x1="176.63" y1="145.12" x2="209.2" y2="200.56" />
|
||||
<line class="cls-2" x1="146.19" y1="200.56" x2="116.3" y2="145.12" />
|
||||
<line class="cls-2" x1="84.84" y1="200.56" x2="116.3" y2="145.12" />
|
||||
<line class="cls-2" x1="23.49" y1="200.56" x2="54.67" y2="145.12" />
|
||||
<circle class="cls-3" cx="146.19" cy="200.56" r="23.49" />
|
||||
<circle class="cls-3" cx="209.52" cy="200.56" r="23.49" transform="translate(-58.76 90.34) rotate(-21.41)" />
|
||||
<circle class="cls-3" cx="116.3" cy="145.12" r="23.49" />
|
||||
<circle class="cls-3" cx="177.93" cy="145.12" r="23.49" />
|
||||
<circle class="cls-3" cx="84.84" cy="200.56" r="23.49" />
|
||||
<circle class="cls-3" cx="54.67" cy="145.12" r="23.49" />
|
||||
<circle class="cls-3" cx="23.49" cy="200.56" r="23.49" />
|
||||
<circle class="cls-3" cx="235.11" cy="78.94" r="23.49" />
|
||||
<circle class="cls-3" cx="298.44" cy="78.94" r="23.49" />
|
||||
<circle class="cls-3" cx="205.22" cy="23.49" r="23.49" />
|
||||
<circle class="cls-3" cx="266.85" cy="23.49" r="23.49" />
|
||||
<circle class="cls-3" cx="173.76" cy="78.94" r="23.49" />
|
||||
<circle class="cls-3" cx="143.58" cy="23.49" r="23.49" />
|
||||
<circle class="cls-3" cx="112.41" cy="78.94" r="23.49" />
|
||||
<circle class="cls-3" cx="362.49" cy="78.94" r="23.49" />
|
||||
<circle class="cls-3" cx="329.3" cy="23.49" r="23.49" />
|
||||
<circle class="cls-3" cx="432.16" cy="196.33" r="23.49" />
|
||||
<circle class="cls-3" cx="495.49" cy="196.33" r="23.49" />
|
||||
<circle class="cls-3" cx="402.27" cy="140.89" r="23.49" />
|
||||
<circle class="cls-3" cx="463.9" cy="140.89" r="23.49" />
|
||||
<circle class="cls-3" cx="370.81" cy="196.33" r="23.49" />
|
||||
<circle class="cls-3" cx="340.64" cy="140.89" r="23.49" />
|
||||
<circle class="cls-3" cx="309.46" cy="196.33" r="23.49" />
|
||||
<circle class="cls-3" cx="559.54" cy="196.33" r="23.49" />
|
||||
<circle class="cls-3" cx="526.35" cy="140.89" r="23.49" />
|
||||
<path class="cls-4" d="M190.1,399.59H142.9q0-2.29.16-16.32t.16-40.78q0-10.33,0-26.85t-.28-32.48h47.2v7.72H154.62q-.17,16.1-.21,28.75t0,22.2q0,20.28.16,32t.17,18h35.4Z" />
|
||||
<path class="cls-4" d="M259.28,399.59H212.07q0-2.29.17-16.32t.16-40.78q0-10.33,0-26.85t-.29-32.48h47.21v7.72H223.79q-.16,16.1-.2,28.75t0,22.2q0,20.28.16,32t.16,18h35.41Z" />
|
||||
<path class="cls-4" d="M272.12,373.41c0-8.14,5.5-13.87,13.21-13.87s13,5.73,13,13.87c0,7.93-5.06,13.88-13.21,13.88C277.4,387.29,272.12,381.34,272.12,373.41Z" />
|
||||
<path class="cls-4" d="M359.86,399.59h-47.2v-7.72h35.4q0-6.93.17-19.95t.16-30.09q0-8.62,0-23.09t-.2-27.86H312.66v-7.72h47.2q-.24,15.9-.28,32.7t0,26.63q0,18.31.16,36.56T359.86,399.59Z" />
|
||||
<path class="cls-4" d="M429,399.59h-47.2v-7.72h35.4q0-6.93.16-19.95t.17-30.09q0-8.62-.05-23.09t-.2-27.86H381.84v-7.72H429q-.24,15.9-.28,32.7t0,26.63q0,18.31.16,36.56T429,399.59Z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,77 @@
|
||||
---
|
||||
// import { getCollection } from 'astro:content';
|
||||
import { generateBackRefs } from '../wikibonsai/backrefs';
|
||||
|
||||
const { frontmatter } = Astro.props;
|
||||
|
||||
const res = await generateBackRefs(frontmatter.fname);
|
||||
const backattrs = res.backattrs;
|
||||
const backlinks = res.backlinks;
|
||||
---
|
||||
<style>
|
||||
li {
|
||||
list-style: '';
|
||||
}
|
||||
.back-refs {
|
||||
padding: 2em 1em 6em 1em;
|
||||
margin: 2em;
|
||||
border: 1px solid #ccc!important;
|
||||
border-radius: 25px;
|
||||
}
|
||||
.title {
|
||||
color: #4F534F;
|
||||
text-align: center;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.sections {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.section-title {
|
||||
color: #4F534F;
|
||||
text-align: center;
|
||||
}
|
||||
.attrtype {
|
||||
padding-left: 0px;
|
||||
}
|
||||
</style>
|
||||
<div class="back-refs">
|
||||
<h5 class="title">Links To This Page</h5>
|
||||
<div class="sections">
|
||||
<div>
|
||||
<span class="section-title">Attributes</span>
|
||||
<ul class="attrtype">
|
||||
{Object.entries(backattrs).map(([type, attrs]) =>
|
||||
<li>
|
||||
{type} :
|
||||
<ul>
|
||||
{attrs.map((attr: any) =>
|
||||
<li>
|
||||
{attr.htmlHref ?
|
||||
<a class="wiki" href={attr.htmlHref}>{attr.htmlText}</a>
|
||||
:
|
||||
<a class="invalid">{attr.htmlText}</a>
|
||||
}
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<span class="section-title">Links</span>
|
||||
<ul>
|
||||
{backlinks.map((link: any) =>
|
||||
<li>
|
||||
{link.htmlHref ?
|
||||
<a class="wiki" href={link.htmlHref}>{link.htmlText}{link.type ? ` (${link.type})` : ''}</a>
|
||||
:
|
||||
<a class="invalid">{link.htmlText}{link.linktype ? ` (${link.linktype})` : ''}</a>
|
||||
}
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
import { SITE_TITLE } from '../consts';
|
||||
import { bonsai } from '../wikibonsai/semtree';
|
||||
|
||||
const { nodes } = Astro.props;
|
||||
|
||||
const root = bonsai ? bonsai.root : '';
|
||||
const tree = bonsai ? bonsai.tree : [];
|
||||
---
|
||||
<!-- from: https://stackoverflow.com/questions/74126716/how-to-self-reference-astro-component -->
|
||||
<ul class="branch">
|
||||
{nodes.map(node =>
|
||||
<li>
|
||||
{node.url ?
|
||||
<a class="wiki" href={node.url}>{node.text}</a>
|
||||
:
|
||||
<a class="invalid">{node.text}</a>
|
||||
}
|
||||
<Astro.self nodes={node.children.map(child =>
|
||||
tree.find(treeNode => treeNode.text == child)
|
||||
)} />
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
import { SITE_TITLE } from '../consts';
|
||||
import { bonsai } from '../wikibonsai/semtree';
|
||||
|
||||
const { current } = Astro.props;
|
||||
|
||||
const root = bonsai ? bonsai.root : '';
|
||||
const tree = bonsai ? bonsai.tree : [];
|
||||
|
||||
const curNode = tree.find(node => node.text == current);
|
||||
const ancestors = curNode ? curNode.ancestors : [];
|
||||
const ancestorNodes = ancestors.map(n => tree.find(tn => tn.text == n));
|
||||
---
|
||||
<style>
|
||||
ol {
|
||||
list-style: '> ';
|
||||
display: flex;
|
||||
align-self: center;
|
||||
overflow-x: scroll;
|
||||
white-space: nowrap;
|
||||
padding-left: 0em;
|
||||
}
|
||||
li {
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
.site-item {
|
||||
list-style: none;
|
||||
}
|
||||
</style>
|
||||
<nav calss="bread-crumbs">
|
||||
<ol>
|
||||
<li class="site-item">
|
||||
<a href="/">{SITE_TITLE}</a>
|
||||
</li>
|
||||
{ancestorNodes.map(node =>
|
||||
<li>
|
||||
{node.url ?
|
||||
<a class="wiki" href={node.url}>{node.text}</a>
|
||||
:
|
||||
<a class="invalid">{node.text}</a>
|
||||
}
|
||||
</li>
|
||||
)}
|
||||
<li>
|
||||
{current}
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
@@ -3,23 +3,9 @@ const today = new Date();
|
||||
---
|
||||
|
||||
<footer>
|
||||
© {today.getFullYear()} Your name here. All rights reserved.
|
||||
<p>🪴 Grown with 💚 from an <a href="https://github.com/wikibonsai/astro-wikibonsai">astro-wikibonsai</a></p>
|
||||
<div class="social-links">
|
||||
<a href="https://m.webtoo.ls/@astro" target="_blank">
|
||||
<span class="sr-only">Follow Astro on Mastodon</span>
|
||||
<svg
|
||||
viewBox="0 0 16 16"
|
||||
aria-hidden="true"
|
||||
width="32"
|
||||
height="32"
|
||||
astro-icon="social/mastodon"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765c0 0-2.285 1.017-2.285 4.488l-.002.662c-.004.64-.007 1.35.011 2.091.083 3.394.626 6.74 3.78 7.57 1.454.383 2.703.463 3.709.408 1.823-.1 2.847-.647 2.847-.647l-.06-1.317s-1.303.41-2.767.36c-1.45-.05-2.98-.156-3.215-1.928a3.614 3.614 0 0 1-.033-.496s1.424.346 3.228.428c1.103.05 2.137-.064 3.188-.189zm1.613-2.47H11.13v-4.08c0-.859-.364-1.295-1.091-1.295-.804 0-1.207.517-1.207 1.541v2.233H7.168V5.89c0-1.024-.403-1.541-1.207-1.541-.727 0-1.091.436-1.091 1.296v4.079H3.197V5.522c0-.859.22-1.541.66-2.046.456-.505 1.052-.764 1.793-.764.856 0 1.504.328 1.933.983L8 4.39l.417-.695c.429-.655 1.077-.983 1.934-.983.74 0 1.336.259 1.791.764.442.505.661 1.187.661 2.046v4.203z"
|
||||
></path></svg
|
||||
>
|
||||
</a>
|
||||
<a href="https://twitter.com/astrodotbuild" target="_blank">
|
||||
<a href="https://twitter.com/wibomd" target="_blank">
|
||||
<span class="sr-only">Follow Astro on Twitter</span>
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/twitter"
|
||||
><path
|
||||
@@ -28,7 +14,7 @@ const today = new Date();
|
||||
></path></svg
|
||||
>
|
||||
</a>
|
||||
<a href="https://github.com/withastro/astro" target="_blank">
|
||||
<a href="https://github.com/wikibonsai/wikibonsai" target="_blank">
|
||||
<span class="sr-only">Go to Astro's GitHub repo</span>
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/github"
|
||||
><path
|
||||
|
||||
@@ -8,20 +8,12 @@ import { SITE_TITLE } from '../consts';
|
||||
<h2><a href="/">{SITE_TITLE}</a></h2>
|
||||
<div class="internal-links">
|
||||
<HeaderLink href="/">Home</HeaderLink>
|
||||
<HeaderLink href="/map">Map</HeaderLink>
|
||||
<HeaderLink href="/blog">Blog</HeaderLink>
|
||||
<HeaderLink href="/about">About</HeaderLink>
|
||||
</div>
|
||||
<div class="social-links">
|
||||
<a href="https://m.webtoo.ls/@astro" target="_blank">
|
||||
<span class="sr-only">Follow Astro on Mastodon</span>
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32"
|
||||
><path
|
||||
fill="currentColor"
|
||||
d="M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765c0 0-2.285 1.017-2.285 4.488l-.002.662c-.004.64-.007 1.35.011 2.091.083 3.394.626 6.74 3.78 7.57 1.454.383 2.703.463 3.709.408 1.823-.1 2.847-.647 2.847-.647l-.06-1.317s-1.303.41-2.767.36c-1.45-.05-2.98-.156-3.215-1.928a3.614 3.614 0 0 1-.033-.496s1.424.346 3.228.428c1.103.05 2.137-.064 3.188-.189zm1.613-2.47H11.13v-4.08c0-.859-.364-1.295-1.091-1.295-.804 0-1.207.517-1.207 1.541v2.233H7.168V5.89c0-1.024-.403-1.541-1.207-1.541-.727 0-1.091.436-1.091 1.296v4.079H3.197V5.522c0-.859.22-1.541.66-2.046.456-.505 1.052-.764 1.793-.764.856 0 1.504.328 1.933.983L8 4.39l.417-.695c.429-.655 1.077-.983 1.934-.983.74 0 1.336.259 1.791.764.442.505.661 1.187.661 2.046v4.203z"
|
||||
></path></svg
|
||||
>
|
||||
</a>
|
||||
<a href="https://twitter.com/astrodotbuild" target="_blank">
|
||||
<a href="https://twitter.com/wibomd" target="_blank">
|
||||
<span class="sr-only">Follow Astro on Twitter</span>
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32"
|
||||
><path
|
||||
@@ -30,7 +22,7 @@ import { SITE_TITLE } from '../consts';
|
||||
></path></svg
|
||||
>
|
||||
</a>
|
||||
<a href="https://github.com/withastro/astro" target="_blank">
|
||||
<a href="https://github.com/wikibonsai/wikibonsai" target="_blank">
|
||||
<span class="sr-only">Go to Astro's GitHub repo</span>
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32"
|
||||
><path
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
// Place any global data in this file.
|
||||
// You can import this data from anywhere in your site by using the `import` keyword.
|
||||
|
||||
export const SITE_TITLE = 'Astro Blog';
|
||||
export const SITE_DESCRIPTION = 'Welcome to my website!';
|
||||
export const SITE_TITLE = 'Astro-WikiBonsai';
|
||||
export const SITE_DESCRIPTION = 'Welcome to my digital garden!';
|
||||
|
||||
@@ -5,6 +5,11 @@ pubDate: 'Jul 08 2022'
|
||||
heroImage: '/blog-placeholder-3.jpg'
|
||||
---
|
||||
|
||||
:attrtype::string
|
||||
:attr::[[wikirefs]]
|
||||
|
||||
👉 [[wikirefs]]
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
|
||||
|
||||
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi.
|
||||
|
||||
+18
-1
@@ -12,4 +12,21 @@ const blog = defineCollection({
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog };
|
||||
const entries = defineCollection({
|
||||
// Type-check frontmatter using a schema
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
// Transform string to Date object
|
||||
pubDate: z.coerce.date().optional(),
|
||||
updatedDate: z.coerce.date().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
const index = defineCollection({
|
||||
// Type-check frontmatter using a schema
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog, entries, index };
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Semantic Tree
|
||||
---
|
||||
|
||||
This is an entry that describes the semantic tree -- also known as the "knowledge bonsai".
|
||||
|
||||
An example of such a tree can be viewed [here](/map).
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: WikiBonsai
|
||||
---
|
||||
|
||||
: components :: [[wikirefs]], [[semtree]]
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: WikiRefs
|
||||
---
|
||||
|
||||
:attr::[[wikirefs]]
|
||||
:primitive::string
|
||||
:post-1::[[first-post]]
|
||||
|
||||
This is an entry that describes [[wikirefs]].
|
||||
|
||||
:post-2::[[second-post]]
|
||||
|
||||
![[wikibonsai.svg]]
|
||||
|
||||
This is a `[[wikilink]]` to the [[second-post]]...
|
||||
|
||||
:something-a-bit-longer::
|
||||
- [[third-post]]
|
||||
- [[fourth-post]]
|
||||
- [[zombielink]]
|
||||
|
||||
[[another-zombielink]]
|
||||
|
||||
[[third-post|with a label]]
|
||||
|
||||
![[second-post]]
|
||||
|
||||
Now for the entries: [[wikirefs]] and [[semtree]].
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Tag Map
|
||||
layout: "../../layouts/Index.astro"
|
||||
---
|
||||
|
||||
- [[wikibonsai]]
|
||||
- [[entries]]
|
||||
- [[semtree]]
|
||||
- [[wikirefs]]
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import BreadCrumbs from '../components/BreadCrumbs.astro';
|
||||
import BackRefs from '../components/BackRefs.astro';
|
||||
|
||||
type Props = CollectionEntry<'entries'>['data'];
|
||||
|
||||
const { title, frontmatter } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<BaseHead title={title} />
|
||||
<style>
|
||||
main {
|
||||
width: calc(100% - 2em);
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
.prose {
|
||||
width: 720px;
|
||||
max-width: calc(100% - 2em);
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
color: rgb(var(--gray-dark));
|
||||
}
|
||||
.title {
|
||||
margin-bottom: 1em;
|
||||
padding: 1em 0;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
}
|
||||
.title h1 {
|
||||
margin: 0 0 0.5em 0;
|
||||
}
|
||||
.date {
|
||||
margin-bottom: 0.5em;
|
||||
color: rgb(var(--gray));
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<Header />
|
||||
<main>
|
||||
<article>
|
||||
<div class="prose">
|
||||
<div class="title">
|
||||
<h1>{title}</h1>
|
||||
<BreadCrumbs current={frontmatter.fname}/>
|
||||
<hr />
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
<BackRefs frontmatter={frontmatter}/>
|
||||
</article>
|
||||
</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import { type CollectionEntry, getCollection } from 'astro:content';
|
||||
import Entry from '../../layouts/Entry.astro';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const entries = await getCollection('entries');
|
||||
return entries.map((entry) => ({
|
||||
params: { slug: entry.slug },
|
||||
props: entry,
|
||||
}));
|
||||
}
|
||||
type Props = CollectionEntry<'entries'>;
|
||||
|
||||
const entry = Astro.props;
|
||||
const { Content, remarkPluginFrontmatter } = await entry.render();
|
||||
entry.data.frontmatter = remarkPluginFrontmatter;
|
||||
---
|
||||
|
||||
<Entry {...entry.data}>
|
||||
<Content />
|
||||
</Entry>
|
||||
+7
-10
@@ -13,11 +13,11 @@ import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
|
||||
<body>
|
||||
<Header title={SITE_TITLE} />
|
||||
<main>
|
||||
<h1>🧑🚀 Hello, Astronaut!</h1>
|
||||
<h1>🧑🌾 Hello, Gardener!</h1>
|
||||
<p>
|
||||
Welcome to the official <a href="https://astro.build/">Astro</a> blog starter template. This
|
||||
template serves as a lightweight, minimally-styled starting point for anyone looking to
|
||||
build a personal website, blog, or portfolio with Astro.
|
||||
Welcome to <a href="https://github.com/wikibonsai/astro-wikibonsai/">astro-wikibonsai</a>, a digital garden starter template.
|
||||
This template serves as a lightweight, minimally-styled starting point for anyone looking to
|
||||
build a personal website, blog, digital garden, or portfolio with Astro.
|
||||
</p>
|
||||
<p>
|
||||
This template comes with a few integrations already configured in your
|
||||
@@ -32,18 +32,15 @@ import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
|
||||
<li>Add your name to the footer in <code>src/components/Footer.astro</code></li>
|
||||
<li>Check out the included blog posts in <code>src/pages/blog/</code></li>
|
||||
<li>Customize the blog post page layout in <code>src/layouts/BlogPost.astro</code></li>
|
||||
<li>Check out the included entries in <code>src/pages/entries/</code></li>
|
||||
<li>Customize the entry page layout in <code>src/layouts/Entry.astro</code></li>
|
||||
<li>Check out the included topic index in <code>src/pages/index/</code></li>
|
||||
</ul>
|
||||
<p>
|
||||
Have fun! If you get stuck, remember to <a href="https://docs.astro.build/"
|
||||
>read the docs
|
||||
</a> or <a href="https://astro.build/chat">join us on Discord</a> to ask questions.
|
||||
</p>
|
||||
<p>
|
||||
Looking for a blog template with a bit more personality? Check out <a
|
||||
href="https://github.com/Charca/astro-blog-template"
|
||||
>astro-blog-template
|
||||
</a> by <a href="https://twitter.com/Charca">Maxi Ferreira</a>.
|
||||
</p>
|
||||
</main>
|
||||
<Footer />
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
import Branch from '../components/Branch.astro';
|
||||
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
|
||||
import { bonsai } from '../wikibonsai/semtree';
|
||||
|
||||
const root = bonsai ? bonsai.root : '';
|
||||
const tree = bonsai ? bonsai.tree : [];
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
|
||||
</head>
|
||||
<body>
|
||||
<Header title={SITE_TITLE} />
|
||||
<main>
|
||||
<h1>Tag Map</h1>
|
||||
<p><a href="/">{SITE_TITLE}</a></p>
|
||||
<Branch nodes={tree.filter(node => node.text === root)} />
|
||||
</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
@@ -14,6 +14,16 @@
|
||||
--gray-gradient: rgba(var(--gray-light), 50%), #fff;
|
||||
--box-shadow: 0 2px 6px rgba(var(--gray), 25%), 0 8px 24px rgba(var(--gray), 33%),
|
||||
0 16px 32px rgba(var(--gray), 33%);
|
||||
/* wiki colors */
|
||||
--text-color-wiki: #009c7b;
|
||||
--text-color-wiki-visited: #008064;
|
||||
--text-color-invalid-wikilink: #8c8c8c;
|
||||
/* for dark themes */
|
||||
/* --text-color-wiki: #a0e4a0;
|
||||
--text-color-wiki-visited: #90f390;
|
||||
--text-color-invalid-wikilink: #8c8c8c;
|
||||
|
||||
--background-color: #27262b; */
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Atkinson';
|
||||
@@ -152,3 +162,125 @@ hr {
|
||||
/* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* tag map / semantic tree */
|
||||
|
||||
.branch {
|
||||
color: var(--text-color-wiki);
|
||||
list-style: "#";
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* wikiref styles */
|
||||
/******************/
|
||||
|
||||
/* wikiattr */
|
||||
|
||||
/* attrbox */
|
||||
aside.attrbox {
|
||||
text-align: center;
|
||||
border: 1px double #ccc;
|
||||
color: #4F534F;
|
||||
border-radius: 25px;
|
||||
border-spacing: 1em;
|
||||
/* @noflip */
|
||||
margin: 0.5em;
|
||||
padding: 0.2em;
|
||||
/* @noflip */
|
||||
float: right;
|
||||
}
|
||||
span.attrbox-title {
|
||||
margin: 0.5em;
|
||||
color: #4F534F;
|
||||
}
|
||||
/* from: https://www.the-art-of-web.com/css/format-dl/ */
|
||||
dl {
|
||||
margin: 0.5em;
|
||||
}
|
||||
dt {
|
||||
width: 100px;
|
||||
float: left;
|
||||
clear: left;
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
}
|
||||
dt::after {
|
||||
content: ":";
|
||||
}
|
||||
dd {
|
||||
margin: 0 0 0 110px;
|
||||
padding: 0 0 0.5em 0;
|
||||
}
|
||||
|
||||
/* (internal) wiki links */
|
||||
a.wiki[href] {
|
||||
color: var(--text-color-wiki);
|
||||
}
|
||||
a.wiki[href]:visited {
|
||||
color: var(--text-color-wiki-visited);
|
||||
}
|
||||
a.invalid {
|
||||
color: var(--text-color-invalid-wikilink);
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* !wikiembed */
|
||||
|
||||
.embed-wrapper {
|
||||
border: 1px solid #535353;
|
||||
border-radius: 6px;
|
||||
padding: 5px 20px 15px 20px;
|
||||
margin: 0 20px;
|
||||
position: relative;
|
||||
}
|
||||
.embed-title {
|
||||
height: 36px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 26px;
|
||||
line-height: 42px;
|
||||
top: 5px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-weight: 900;
|
||||
}
|
||||
.embed-link {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.embed-link-icon {
|
||||
text-decoration: none;
|
||||
}
|
||||
.link-icon {
|
||||
font-size: 18px;
|
||||
color: #535353;
|
||||
}
|
||||
.link-icon::before{
|
||||
content: "🔗";
|
||||
}
|
||||
.embed-content {
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
padding-right: 10px;
|
||||
}
|
||||
/* embed media */
|
||||
.embed-media {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.embed-audio {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.embed-image {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
}
|
||||
.embed-video {
|
||||
height: 75%;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
import path from 'path';
|
||||
import * as wikirefs from 'wikirefs';
|
||||
|
||||
|
||||
export async function generateBackRefs(thisFileName: string) {
|
||||
const blogrefs = generateBlogBackRefs(thisFileName);
|
||||
const entryrefs = generateEntryBackRefs(thisFileName);
|
||||
return {
|
||||
backattrs: { ...(await blogrefs).backattrs, ...(await entryrefs).backattrs },
|
||||
backlinks: [...(await blogrefs).backlinks, ...(await entryrefs).backlinks],
|
||||
}
|
||||
}
|
||||
|
||||
// note: the following functions perform identical
|
||||
// tasks, but operate on different collections
|
||||
|
||||
export async function generateBlogBackRefs(thisFileName: string) {
|
||||
const backattrs: any = {};
|
||||
const backlinks: any = [];
|
||||
const allBlogPosts = await getCollection('blog');
|
||||
for (const thatDoc of allBlogPosts) {
|
||||
const thatFName: string = path.basename(thatDoc.id, '.md');
|
||||
if (thatFName === thisFileName) { continue; }
|
||||
const wiki = wikirefs.scan(thatDoc.body);
|
||||
for (const w of wiki) {
|
||||
if (w.kind === wikirefs.CONST.WIKI.ATTR) {
|
||||
// @ts-expect-error
|
||||
for (const fname of w.filenames) {
|
||||
const fnameStr: string = fname[0];
|
||||
// @ts-expect-error
|
||||
const typeStr: string = w.type[0];
|
||||
if (fnameStr === thisFileName) {
|
||||
if (!Object.keys(backattrs).includes(typeStr)) {
|
||||
backattrs[typeStr] = [];
|
||||
}
|
||||
backattrs[typeStr].push({
|
||||
filenames: thatFName,
|
||||
htmlHref: '/blog/' + thatDoc.slug,
|
||||
htmlText: thatFName,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (w.kind === wikirefs.CONST.WIKI.LINK) {
|
||||
// @ts-expect-error
|
||||
const fnameStr: string = w.filename[0];
|
||||
// @ts-expect-error
|
||||
const typeStr: string = w.type[0];
|
||||
if (fnameStr === thisFileName) {
|
||||
backlinks.push({
|
||||
linktype: typeStr,
|
||||
htmlHref: '/blog/' + thatDoc.slug,
|
||||
htmlText: thatFName,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
backattrs,
|
||||
backlinks,
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateEntryBackRefs(thisFileName: string) {
|
||||
const backattrs: any = {};
|
||||
const backlinks: any = [];
|
||||
const allEntryDocs = await getCollection('entries');
|
||||
for (const thatDoc of allEntryDocs) {
|
||||
const thatFName: string = path.basename(thatDoc.id, '.md');
|
||||
if (thatFName === thisFileName) { continue; }
|
||||
const wiki = wikirefs.scan(thatDoc.body);
|
||||
for (const w of wiki) {
|
||||
if (w.kind === wikirefs.CONST.WIKI.ATTR) {
|
||||
// @ts-expect-error
|
||||
for (const fname of w.filenames) {
|
||||
const fnameStr: string = fname[0];
|
||||
// @ts-expect-error
|
||||
const typeStr: string = w.type[0];
|
||||
if (fnameStr === thisFileName) {
|
||||
if (!Object.keys(backattrs).includes(typeStr)) {
|
||||
backattrs[typeStr] = [];
|
||||
}
|
||||
backattrs[typeStr].push({
|
||||
filenames: thatFName,
|
||||
htmlHref: '/entries/' + thatDoc.slug,
|
||||
htmlText: thatFName,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (w.kind === wikirefs.CONST.WIKI.LINK) {
|
||||
// @ts-expect-error
|
||||
const fnameStr: string = w.filename[0];
|
||||
// @ts-expect-error
|
||||
const typeStr: string = w.type[0];
|
||||
if (fnameStr === thisFileName) {
|
||||
backlinks.push({
|
||||
linktype: typeStr,
|
||||
htmlHref: '/entries/' + thatDoc.slug,
|
||||
htmlText: thatFName,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
backattrs,
|
||||
backlinks,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// todo
|
||||
|
||||
// import type { AstroIntegration } from 'astro';
|
||||
|
||||
// // from: https://stackblitz.com/github/withastro/astro/tree/latest/examples/integration?file=index.ts&on=stackblitz
|
||||
// export default function backrefs(): AstroIntegration {
|
||||
// // See the Integration API docs for full details
|
||||
// // https://docs.astro.build/en/reference/integrations-reference/
|
||||
// return {
|
||||
// name: '@wikibonsai/metadata',
|
||||
// hooks: {
|
||||
// 'astro:build:done': ({ dir, routes, pages }) => {
|
||||
// console.log('wikibonsai metadata integration: ', dir, routes, pages);
|
||||
// // See the @astrojs/partytown integration for an example
|
||||
// // https://github.com/withastro/astro/blob/main/packages/integrations/partytown/src/index.ts
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
@@ -0,0 +1,61 @@
|
||||
import { getCollection } from 'astro:content';
|
||||
import path from 'path';
|
||||
import { SemTree } from 'semtree';
|
||||
|
||||
|
||||
export async function buildBonsai() {
|
||||
// init vars
|
||||
const bonsai = new SemTree({
|
||||
// if set to 'false', make sure to extract urls of index docs below
|
||||
virtualTrunk: true,
|
||||
});
|
||||
const bonsaiText: any = {}; // { filename: content } hash
|
||||
const rootFilename: string = 'i.bonsai';
|
||||
// build 'bonsaiText' hash
|
||||
const allIndexDocs = await getCollection('index');
|
||||
allIndexDocs.forEach((doc: any) => { // remove preceding/trailing newlines/whitespace
|
||||
bonsaiText[path.basename(doc.id, '.md')] = doc.body.replace(/^\s+|\s+$/g, '');
|
||||
});
|
||||
let res;
|
||||
try {
|
||||
// build bonsai tree data struct
|
||||
res = bonsai.parse(bonsaiText, rootFilename);
|
||||
// append url for template rendering and init fam metadata
|
||||
const allEntryDocs = await getCollection('entries');
|
||||
for (const node of bonsai.tree) {
|
||||
const doc: any = allEntryDocs.find((doc) => path.basename(doc.id, '.md') == node.text);
|
||||
if (doc !== undefined) {
|
||||
node.url = '/entries/' + doc.slug;
|
||||
}
|
||||
}
|
||||
// uncomment if 'virtualTrunk' is set to 'false'
|
||||
// for (const node of bonsai.tree) {
|
||||
// const doc: any = allIndexDocs.find((doc) => path.basename(doc.id, '.md') == node.text);
|
||||
// if (doc !== undefined) {
|
||||
// node.url = '/index/' + doc.slug;
|
||||
// }
|
||||
// }
|
||||
// uncomment in case blog posts are desired on the #tag map
|
||||
// const allBlogDocs = await getCollection('blog');
|
||||
// for (const node of bonsai.tree) {
|
||||
// const doc: any = allBlogDocs.find((doc) => path.basename(doc.id, '.md') == node.text);
|
||||
// if (doc !== undefined) {
|
||||
// node.url = '/blog/' + doc.slug;
|
||||
// }
|
||||
// }
|
||||
return bonsai;
|
||||
} catch (e) {
|
||||
console.error(e, res);
|
||||
}
|
||||
if (bonsai.duplicates.length > 0) {
|
||||
console.log('bonsai duplicates: ' + bonsai.duplicates);
|
||||
} else {
|
||||
console.log('bonsai: \n'
|
||||
+ 'res: ' + JSON.stringify(res) + '\n'
|
||||
+ 'root: ' + bonsai.root + '\n'
|
||||
+ 'duplicates: ' + bonsai.duplicates
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const bonsai = await buildBonsai();
|
||||
@@ -0,0 +1,121 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import fg from 'fast-glob';
|
||||
import matter from 'gray-matter';
|
||||
import { selectAll } from 'unist-util-select';
|
||||
import * as wikirefs from 'wikirefs';
|
||||
|
||||
|
||||
const CONTENT_GLOB: string = './src/content/**/*.md';
|
||||
|
||||
export function resolveHtmlHref(fname: string): string | undefined {
|
||||
// #todo revisit: https://docs.astro.build/en/reference/api-reference/#importmeta
|
||||
// 'import.meta.glob' docs:
|
||||
// - astro docs: https://docs.astro.build/en/reference/api-reference/
|
||||
// - vite docs: https://vitejs.dev/guide/features.html#glob-import
|
||||
// see:
|
||||
// - https://github.com/withastro/astro/issues/5265
|
||||
// - https://github.com/withastro/docs/pull/1967
|
||||
// const posts = import.meta.glob(CONTENT_GLOB, { as: 'raw', eager: true });
|
||||
if (!wikirefs.isMedia(fname)) {
|
||||
const docPaths: string[] = fg.sync(CONTENT_GLOB);
|
||||
const docPath: string | undefined = docPaths.find((p) => {
|
||||
return path.basename(p, '.md') === fname;
|
||||
});
|
||||
if (docPath === undefined) {
|
||||
return undefined;
|
||||
} else {
|
||||
// todo: support dynamic routes (https://docs.astro.build/en/core-concepts/routing/#dynamic-routes)
|
||||
return docPath.replace('./src/content', '').replace('.md', '');
|
||||
}
|
||||
// media
|
||||
} else {
|
||||
return '/' + fname;
|
||||
// note: in case media is stored in separate locations,
|
||||
// uncomment and customize the following:
|
||||
// audio
|
||||
// if (wikirefs.CONST.EXTS.AUD.has(path.extname(fname))) {
|
||||
// return '/' + fname;
|
||||
// }
|
||||
// images
|
||||
// if (wikirefs.CONST.EXTS.IMG.has(path.extname(fname))) {
|
||||
// return '/' + fname;
|
||||
// }
|
||||
// video
|
||||
// if (wikirefs.CONST.EXTS.VID.has(path.extname(fname))) {
|
||||
// return '/' + fname;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveHtmlText(fname: string): string | undefined {
|
||||
const docPaths: string[] = fg.sync(CONTENT_GLOB);
|
||||
const docPath: string | undefined = docPaths.find((p) => {
|
||||
return path.basename(p, '.md') === fname;
|
||||
});
|
||||
if (docPath === undefined) {
|
||||
return undefined;
|
||||
} else {
|
||||
const content: string | undefined = fs.readFileSync(docPath, { encoding: 'utf8', flag: 'r' });
|
||||
const data: any = matter(content).data;
|
||||
if (!data || !data.title) {
|
||||
return undefined;
|
||||
} else {
|
||||
return data.title.toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveEmbedContent(filename: string): any {
|
||||
// markdown-only
|
||||
if (wikirefs.isMedia(filename)) { return; }
|
||||
const docPaths: string[] = fg.sync(CONTENT_GLOB);
|
||||
const docPath: string | undefined = docPaths.find((p) => {
|
||||
return path.basename(p, '.md') === filename;
|
||||
});
|
||||
let content: string = '';
|
||||
if (docPath === undefined) {
|
||||
content = 'embed content not found for ' + filename;
|
||||
} else {
|
||||
const text: string | undefined = fs.readFileSync(docPath, { encoding: 'utf8', flag: 'r' });
|
||||
content = matter(text).content;
|
||||
}
|
||||
// return mdast node
|
||||
return {
|
||||
type: 'text',
|
||||
// todo: render
|
||||
value: content,
|
||||
};
|
||||
}
|
||||
|
||||
// forerfs
|
||||
|
||||
// todo: don't include index documents when calculating metadata -- and skip index docs too
|
||||
export function generateForeRefsRemarkPlugin() {
|
||||
return function (tree: any, file: any) {
|
||||
// from: https://observablehq.com/@tmcw/extracting-links-from-markdown-using-remark-and-unist-util
|
||||
// access the first item of the wikiattrs matches since they should already be consolidated in the attrbox data already
|
||||
const attrs = selectAll("attrbox", tree).map((node: any) => node.data.items)[0];
|
||||
const wikiattrs = {} as any;
|
||||
// strip out primitive caml attrs
|
||||
if (attrs) {
|
||||
for (const [type, vals] of Object.entries(attrs)) {
|
||||
// @ts-expect-error
|
||||
for (const val of vals) {
|
||||
if (val.type === 'wiki') {
|
||||
if (!Object.keys(wikiattrs).includes(type)) {
|
||||
wikiattrs[type] = [];
|
||||
}
|
||||
wikiattrs[type].push(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const wikilinks = selectAll("wikilink", tree).map((node: any) => node.data.item);
|
||||
const thisFname: string = path.basename(file.history[0], '.md');
|
||||
// refs
|
||||
file.data.astro.frontmatter.fname = thisFname;
|
||||
file.data.astro.frontmatter.foreattrs = wikiattrs;
|
||||
file.data.astro.frontmatter.forelinks = wikilinks;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user