add: wikibonsai changes.

This commit is contained in:
manunamz
2023-10-03 10:58:17 -04:00
parent 8e2152a560
commit f87f774b2a
26 changed files with 4811 additions and 54 deletions
+11 -7
View File
@@ -1,12 +1,10 @@
# Astro Starter Kit: Blog # Astro-WikiBonsai
```sh [![A WikiBonsai Project](https://img.shields.io/badge/%F0%9F%8E%8B-A%20WikiBonsai%20Project-brightgreen)](https://github.com/wikibonsai/wikibonsai)
npm create astro@latest -- --template blog
```
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog) An [Astro base blog](https://github.com/withastro/astro/tree/main/examples/blog) with [wikibonsai](https://github.com/wikibonsai/wikibonsai) support.
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/blog)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/blog/devcontainer.json) 💐 Display your [🎋 WikiBonsai](https://github.com/wikibonsai/wikibonsai) digital garden for others.
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! > 🧑‍🚀 **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 └── 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. 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. There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
+36 -4
View File
@@ -1,10 +1,42 @@
import { defineConfig } from 'astro/config'; import { base, defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap'; 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 // https://astro.build/config
export default defineConfig({ export default defineConfig({
site: 'https://example.com', site: 'https://astro-wikibonsai.netlify.app',
integrations: [mdx(), sitemap()], 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,
],
},
}); });
+19 -2
View File
@@ -2,6 +2,16 @@
"name": "astro-wikibonsai", "name": "astro-wikibonsai",
"type": "module", "type": "module",
"version": "0.0.1", "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": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"start": "astro dev", "start": "astro dev",
@@ -13,6 +23,13 @@
"@astrojs/mdx": "^1.1.0", "@astrojs/mdx": "^1.1.0",
"@astrojs/rss": "^3.0.0", "@astrojs/rss": "^3.0.0",
"@astrojs/sitemap": "^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"
} }
} }
+81
View File
@@ -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

+77
View File
@@ -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>
+25
View File
@@ -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>
+48
View File
@@ -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 -17
View File
@@ -3,23 +3,9 @@ const today = new Date();
--- ---
<footer> <footer>
&copy; {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"> <div class="social-links">
<a href="https://m.webtoo.ls/@astro" target="_blank"> <a href="https://twitter.com/wibomd" 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">
<span class="sr-only">Follow Astro on Twitter</span> <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" <svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/twitter"
><path ><path
@@ -28,7 +14,7 @@ const today = new Date();
></path></svg ></path></svg
> >
</a> </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> <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" <svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/github"
><path ><path
+3 -11
View File
@@ -8,20 +8,12 @@ import { SITE_TITLE } from '../consts';
<h2><a href="/">{SITE_TITLE}</a></h2> <h2><a href="/">{SITE_TITLE}</a></h2>
<div class="internal-links"> <div class="internal-links">
<HeaderLink href="/">Home</HeaderLink> <HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/map">Map</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink> <HeaderLink href="/blog">Blog</HeaderLink>
<HeaderLink href="/about">About</HeaderLink> <HeaderLink href="/about">About</HeaderLink>
</div> </div>
<div class="social-links"> <div class="social-links">
<a href="https://m.webtoo.ls/@astro" target="_blank"> <a href="https://twitter.com/wibomd" 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">
<span class="sr-only">Follow Astro on Twitter</span> <span class="sr-only">Follow Astro on Twitter</span>
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" <svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32"
><path ><path
@@ -30,7 +22,7 @@ import { SITE_TITLE } from '../consts';
></path></svg ></path></svg
> >
</a> </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> <span class="sr-only">Go to Astro's GitHub repo</span>
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" <svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32"
><path ><path
+2 -2
View File
@@ -1,5 +1,5 @@
// Place any global data in this file. // Place any global data in this file.
// You can import this data from anywhere in your site by using the `import` keyword. // You can import this data from anywhere in your site by using the `import` keyword.
export const SITE_TITLE = 'Astro Blog'; export const SITE_TITLE = 'Astro-WikiBonsai';
export const SITE_DESCRIPTION = 'Welcome to my website!'; export const SITE_DESCRIPTION = 'Welcome to my digital garden!';
+5
View File
@@ -5,6 +5,11 @@ pubDate: 'Jul 08 2022'
heroImage: '/blog-placeholder-3.jpg' 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. 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. 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
View File
@@ -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 };
+7
View File
@@ -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).
+5
View File
@@ -0,0 +1,5 @@
---
title: WikiBonsai
---
: components :: [[wikirefs]], [[semtree]]
+28
View File
@@ -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]].
+9
View File
@@ -0,0 +1,9 @@
---
title: Tag Map
layout: "../../layouts/Index.astro"
---
- [[wikibonsai]]
- [[entries]]
- [[semtree]]
- [[wikirefs]]
+62
View File
@@ -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>
+21
View File
@@ -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
View File
@@ -13,11 +13,11 @@ import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
<body> <body>
<Header title={SITE_TITLE} /> <Header title={SITE_TITLE} />
<main> <main>
<h1>🧑‍🚀 Hello, Astronaut!</h1> <h1>🧑‍🌾 Hello, Gardener!</h1>
<p> <p>
Welcome to the official <a href="https://astro.build/">Astro</a> blog starter template. This Welcome to <a href="https://github.com/wikibonsai/astro-wikibonsai/">astro-wikibonsai</a>, a digital garden starter template.
template serves as a lightweight, minimally-styled starting point for anyone looking to This template serves as a lightweight, minimally-styled starting point for anyone looking to
build a personal website, blog, or portfolio with Astro. build a personal website, blog, digital garden, or portfolio with Astro.
</p> </p>
<p> <p>
This template comes with a few integrations already configured in your 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>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>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>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> </ul>
<p> <p>
Have fun! If you get stuck, remember to <a href="https://docs.astro.build/" Have fun! If you get stuck, remember to <a href="https://docs.astro.build/"
>read the docs >read the docs
</a> or <a href="https://astro.build/chat">join us on Discord</a> to ask questions. </a> or <a href="https://astro.build/chat">join us on Discord</a> to ask questions.
</p> </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> </main>
<Footer /> <Footer />
</body> </body>
+28
View File
@@ -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>
+132
View File
@@ -14,6 +14,16 @@
--gray-gradient: rgba(var(--gray-light), 50%), #fff; --gray-gradient: rgba(var(--gray-light), 50%), #fff;
--box-shadow: 0 2px 6px rgba(var(--gray), 25%), 0 8px 24px rgba(var(--gray), 33%), --box-shadow: 0 2px 6px rgba(var(--gray), 25%), 0 8px 24px rgba(var(--gray), 33%),
0 16px 32px 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-face {
font-family: 'Atkinson'; 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 */ /* 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; 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%;
}
+114
View File
@@ -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,
}
}
+19
View File
@@ -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
// },
// },
// };
// }
+61
View File
@@ -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();
+121
View File
@@ -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;
}
}
+3869
View File
File diff suppressed because it is too large Load Diff