diff --git a/apps/cory/docs.json b/apps/cory/docs.json
index 094c2a12..9c6a4e62 100644
--- a/apps/cory/docs.json
+++ b/apps/cory/docs.json
@@ -1 +1 @@
-{"type":"tildefriends-app","files":{"app.js":"&rLwYqurncmnUyGeWY+FLEGS2EIJmqw2cutl1gyGiVSk=.sha256","index.md":"&082vPjenwI6mL2vXwQDVEFquyl2jW9t767sGuCFvVNA=.sha256","todo.md":"&ehX+cfsiYWwe3Pjg2QW7Gqa5bsQTFBehJVxQnlxv+P4=.sha256","structure.md":"&T+CBfT9XP6ooKFvD1ZCI9hsutqsNIamfBxtAho0HtlU=.sha256","guide.md":"&SgnGL0+rjetY2o9A2+lVRbNvHIkqKwMnZr9gXWneIlc=.sha256","id_refactor.md":"&8yoYd14gX2Z3ppktVrPYf4qR78fuwAlvrtsWkSCkWUA=.sha256","ssb.md":"&WMvYIpp4CMZACwXJlX8HMDplJ+XeJB04BYf8zasrL4g=.sha256"}}
\ No newline at end of file
+{"type":"tildefriends-app","files":{"app.js":"&WEvJYebSMi5d2eXgUwJJmvR/Q4slFg3zHYB8Q2mXJII=.sha256","index.md":"&Pi0NTJn9/w76yIUKqRRuSvUPSpqkxdYynmjeOBbF3K8=.sha256","todo.md":"&ehX+cfsiYWwe3Pjg2QW7Gqa5bsQTFBehJVxQnlxv+P4=.sha256","structure.md":"&T+CBfT9XP6ooKFvD1ZCI9hsutqsNIamfBxtAho0HtlU=.sha256","guide.md":"&SgnGL0+rjetY2o9A2+lVRbNvHIkqKwMnZr9gXWneIlc=.sha256","ssb.md":"&ouqT3XzTGfBNpOP/uEdOw7K1F9BeLZgQCx24XTvhyXU=.sha256"}}
\ No newline at end of file
diff --git a/apps/cory/docs/app.js b/apps/cory/docs/app.js
index 28b7f6a0..fbbbd7e8 100644
--- a/apps/cory/docs/app.js
+++ b/apps/cory/docs/app.js
@@ -8,7 +8,7 @@ async function loadDocument(name) {
`;
var md = utf8Decode(await getFile(name + '.md'));
if (!md) {
- md = "File not found.";
+ md = `File not found: ${JSON.stringify(name)}.`;
}
var parsed = new commonmark.Parser().parse(md);
var html = new commonmark.HtmlRenderer().render(parsed);
@@ -22,7 +22,7 @@ async function main() {
core.register('message', function(message) {
if (message.event == 'hashChange') {
- loadDocument(message.hash.substring(1));
+ loadDocument((message.hash || '#index').substring(1));
}
});
diff --git a/apps/cory/docs/index.md b/apps/cory/docs/index.md
index 61a39084..703c6aeb 100644
--- a/apps/cory/docs/index.md
+++ b/apps/cory/docs/index.md
@@ -8,5 +8,4 @@ and run code.
- [Secure Scuttlebutt from Scratch](#ssb)
- [Structure](#structure)
- [Guide](#guide)
-- [TODO](#todo)
-- [ID Refactor](#id_refactor)
\ No newline at end of file
+- [TODO](#todo)
\ No newline at end of file
diff --git a/apps/cory/docs/ssb.md b/apps/cory/docs/ssb.md
index b81a74c7..a6371f3f 100644
--- a/apps/cory/docs/ssb.md
+++ b/apps/cory/docs/ssb.md
@@ -30,4 +30,8 @@ So now you're discovering other clients on the local network, connecting, perfor
a secret handshake, and making remote procedure calls over box streams. The next step
is to start synchronizing feeds over the network. The goal, after all, is to author
messages in your local append-only log and have them show up in distant clients, or
-vice versa.
\ No newline at end of file
+vice versa.
+
+## References
+* [https://ssbc.github.io/scuttlebutt-protocol-guide/](https://ssbc.github.io/scuttlebutt-protocol-guide/)
+* [https://dev.planetary.social/](https://dev.planetary.social/)
\ No newline at end of file
diff --git a/apps/cory/ssblit.json b/apps/cory/ssblit.json
index 10135e6a..0277eeec 100644
--- a/apps/cory/ssblit.json
+++ b/apps/cory/ssblit.json
@@ -1 +1 @@
-{"type":"tildefriends-app","files":{"app.js":"&jLRr14wP54BEkzBMIf1vCdeylqYExD8+jnHwgsqV9a4=.sha256","lit-all.min.js":"&N4A12AsifdQgwdpII0SFtG513BfoLpmPjdJ9VTDftpg=.sha256","index.html":"&4uvb7ESTRYeImX1lsIQOWRec6HmMBaYipGgYf0EFVPY=.sha256","script.js":"&G8puK9Q4MngHy3D4ppcKyT49WKbHD2OCeUcAw2ghTDE=.sha256","lit-all.min.js.map":"&oFY9wO4MnujgfGNGv4VggHc5V5JwX4C8csqKZ6KJYbE=.sha256","tf-id-picker.js":"&9BDffV4HY9FqhL7XI4it+UQJB4cYwbDNsY3S1cxy2vw=.sha256","tf-app.js":"&fEqRRoyD6C7oNGcveWy02XRdymmTgAVwFHvkTC1xOjU=.sha256","tf-message.js":"&6/9GXDUOB0KvKZMEgY8CEU2gqSUB0yZWEVWkRV9VSLM=.sha256","tf-user.js":"&bXTedgBudTQLXEBPY9R8OLfQ/ZLpo8YRU9Oq/wuGG3Y=.sha256","tf-utils.js":"&N2yKZwFnb2GbPeipgQtu6xFvezENNOgud9G7EhCQ/K0=.sha256","commonmark.min.js":"&bfBaMLU19d1p/vPBF9hlARqDX002KXG/UOfxOahZhe4=.sha256","tf-compose.js":"&ZGWHQZPTUl4QU5++WkGwGbyj+hxhQrTg9nLmZCrl/1g=.sha256","emojis.json":"&h3P4pez+AI4aYdsN0dJ3pbUEFR0276t9AM20caj/W/s=.sha256","emojis.js":"&pqYLDE/13PyEt2ceeFqvnwZ8NqWfPfpDBt4vP8SeHbs=.sha256","tf-styles.js":"&Zw90HptAvGwX/vBnEhRVfNrYjMSssFnnKpp8bzwXQH0=.sha256","tf-profile.js":"&vRKjsnYvOiHCQahzEfznCvP5YDwUPtltlpWf+pxwZ1Y=.sha256","commonmark-linkify.js":"&X+hNNkmSRvKY86khyAun+cXksquXbMakZdINbGbx30g=.sha256","tf-tab-search.js":"&ESt2vMG19sH5j6ungKua/ZuvIGslyuWyb3juXdOCecg=.sha256","tf-tab-news.js":"&SSHoFxBG2DiKUbfMNxiBjxqtAccQDSAEUTSN/IN/MlY=.sha256","tf-tab-connections.js":"&PjreVhTR/vxlGHVKQbY0P9BuD6udtPMHDUv9HPCHuKw=.sha256","tf-news.js":"&/Ij0SaBTohV2myuA1gQAPlgmyq/AmmvYIhSCm3wfmow=.sha256","tribute.css":"&9FogMzZHKXCfGb7mlh7z+/wiNZzBsOB/tKoh6MfYJno=.sha256","tribute.esm.js":"&P1wKqCfYULpR/ahSB98JP8xaxfikuZwwtT6I/SAo7/Y=.sha256"}}
\ No newline at end of file
+{"type":"tildefriends-app","files":{"app.js":"&jLRr14wP54BEkzBMIf1vCdeylqYExD8+jnHwgsqV9a4=.sha256","lit-all.min.js":"&N4A12AsifdQgwdpII0SFtG513BfoLpmPjdJ9VTDftpg=.sha256","index.html":"&TxhFekB9ov7tf/fmkAg7x5797i27oLidhgxEfDKC0T0=.sha256","script.js":"&G8puK9Q4MngHy3D4ppcKyT49WKbHD2OCeUcAw2ghTDE=.sha256","lit-all.min.js.map":"&oFY9wO4MnujgfGNGv4VggHc5V5JwX4C8csqKZ6KJYbE=.sha256","tf-id-picker.js":"&9BDffV4HY9FqhL7XI4it+UQJB4cYwbDNsY3S1cxy2vw=.sha256","tf-app.js":"&fEqRRoyD6C7oNGcveWy02XRdymmTgAVwFHvkTC1xOjU=.sha256","tf-message.js":"&6/9GXDUOB0KvKZMEgY8CEU2gqSUB0yZWEVWkRV9VSLM=.sha256","tf-user.js":"&bXTedgBudTQLXEBPY9R8OLfQ/ZLpo8YRU9Oq/wuGG3Y=.sha256","tf-utils.js":"&6RQUuxB3PkOhYEJr9+89Ptx7uijczjn0r035yCcQOQQ=.sha256","commonmark.min.js":"&bfBaMLU19d1p/vPBF9hlARqDX002KXG/UOfxOahZhe4=.sha256","tf-compose.js":"&ZGWHQZPTUl4QU5++WkGwGbyj+hxhQrTg9nLmZCrl/1g=.sha256","emojis.json":"&h3P4pez+AI4aYdsN0dJ3pbUEFR0276t9AM20caj/W/s=.sha256","emojis.js":"&pqYLDE/13PyEt2ceeFqvnwZ8NqWfPfpDBt4vP8SeHbs=.sha256","tf-styles.js":"&Zw90HptAvGwX/vBnEhRVfNrYjMSssFnnKpp8bzwXQH0=.sha256","tf-profile.js":"&vRKjsnYvOiHCQahzEfznCvP5YDwUPtltlpWf+pxwZ1Y=.sha256","commonmark-linkify.js":"&X+hNNkmSRvKY86khyAun+cXksquXbMakZdINbGbx30g=.sha256","tf-tab-search.js":"&ESt2vMG19sH5j6ungKua/ZuvIGslyuWyb3juXdOCecg=.sha256","tf-tab-news.js":"&SSHoFxBG2DiKUbfMNxiBjxqtAccQDSAEUTSN/IN/MlY=.sha256","tf-tab-connections.js":"&PjreVhTR/vxlGHVKQbY0P9BuD6udtPMHDUv9HPCHuKw=.sha256","tf-news.js":"&/Ij0SaBTohV2myuA1gQAPlgmyq/AmmvYIhSCm3wfmow=.sha256","tribute.css":"&9FogMzZHKXCfGb7mlh7z+/wiNZzBsOB/tKoh6MfYJno=.sha256","tribute.esm.js":"&P1wKqCfYULpR/ahSB98JP8xaxfikuZwwtT6I/SAo7/Y=.sha256","commonmark-hashtag.js":"&H+V1OLA9GDdzycKclz276zAtSZLpT3rlNVa4+qQmp4o=.sha256"}}
\ No newline at end of file
diff --git a/apps/cory/ssblit/commonmark-hashtag.js b/apps/cory/ssblit/commonmark-hashtag.js
new file mode 100644
index 00000000..76d0e8bc
--- /dev/null
+++ b/apps/cory/ssblit/commonmark-hashtag.js
@@ -0,0 +1,90 @@
+function textNode(text) {
+ const node = new commonmark.Node("text", undefined);
+ node.literal = text;
+ return node;
+}
+
+function linkNode(text, link) {
+ const linkNode = new commonmark.Node("link", undefined);
+ linkNode.destination = `#q=${encodeURIComponent(link)}`;
+ linkNode.appendChild(textNode(text));
+ return linkNode;
+}
+
+function splitMatches(text, regexp) {
+ // Regexp must be sticky.
+ regexp = new RegExp(regexp, "gm");
+
+ let i = 0;
+ const result = [];
+
+ let match = regexp.exec(text);
+ while (match) {
+ const matchText = match[0];
+
+ if (match.index > i) {
+ result.push([text.substring(i, match.index), false]);
+ }
+
+ result.push([matchText, true]);
+ i = match.index + matchText.length;
+
+ match = regexp.exec(text);
+ }
+
+ if (i < text.length) {
+ result.push([text.substring(i, text.length), false]);
+ }
+
+ return result;
+}
+
+const regex = new RegExp("#[\\w-]+");
+
+function split(textNodes) {
+ const text = textNodes.map(n => n.literal).join("");
+ const parts = splitMatches(text, regex);
+
+ return parts.map(part => {
+ if (part[1]) {
+ return linkNode(part[0], part[0]);
+ } else {
+ return textNode(part[0]);
+ }
+ });
+}
+
+export function transform(parsed) {
+ const walker = parsed.walker();
+ let event;
+
+ let nodes = [];
+ while ((event = walker.next())) {
+ const node = event.node;
+ if (event.entering && node.type === "text") {
+ nodes.push(node);
+ } else {
+ if (nodes.length > 0) {
+ split(nodes)
+ .reverse()
+ .forEach(newNode => {
+ nodes[0].insertAfter(newNode);
+ });
+
+ nodes.forEach(n => n.unlink());
+ nodes = [];
+ }
+ }
+ }
+
+ if (nodes.length > 0) {
+ split(nodes)
+ .reverse()
+ .forEach(newNode => {
+ nodes[0].insertAfter(newNode);
+ });
+ nodes.forEach(n => n.unlink());
+ }
+
+ return parsed;
+}
diff --git a/apps/cory/ssblit/index.html b/apps/cory/ssblit/index.html
index 60ed1b59..4aa22a60 100644
--- a/apps/cory/ssblit/index.html
+++ b/apps/cory/ssblit/index.html
@@ -15,6 +15,7 @@
+