diff --git a/.gitignore b/.gitignore
index fd3dbb5..e4d6f72 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
+
+# vscode
+.vscode
diff --git a/app/layout.tsx b/app/layout.tsx
index b73eff4..5e4f48f 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -7,6 +7,7 @@ import {
Cog8ToothIcon,
PuzzlePieceIcon,
} from "@heroicons/react/24/solid";
+import Link from "next/link";
const inter = Inter({ subsets: ["latin"] });
@@ -20,6 +21,29 @@ export default function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
+ const navItems = [
+ {
+ to: "/schemas",
+ icon: CircleStackIcon,
+ text: "Schemas",
+ },
+ {
+ to: "/game-systems",
+ icon: PuzzlePieceIcon,
+ text: "Game Systems",
+ },
+ {
+ to: "/publications",
+ icon: BookOpenIcon,
+ text: "Publications",
+ },
+ {
+ to: "/settings",
+ icon: Cog8ToothIcon,
+ text: "Settings",
+ },
+ ];
+
return (
@@ -28,18 +52,17 @@ export default function RootLayout({
Tabletop Commander
- -
- Schemas
-
- -
- Game Systems
-
- -
- Publications
-
- -
- Settings
-
+ {navItems.map((n) => (
+ -
+
+
+ {n.text}
+
+
+ ))}
diff --git a/components/tcmd/index.tsx b/components/tcmd/index.tsx
index 5f5413e..00b370b 100644
--- a/components/tcmd/index.tsx
+++ b/components/tcmd/index.tsx
@@ -3,6 +3,7 @@
import { Accordion, AccordionContent } from "@/lib/accordion";
import { Poppable } from "@/lib/poppables/components/poppable";
import { createElements } from "@/lib/tcmd";
+import { tokenizeInline } from "@/lib/tcmd/tokenizeInline";
import Link from "next/link";
import React, { FC, Fragment, ReactNode, use, useMemo } from "react";
@@ -192,7 +193,7 @@ const renderInlineToken = (l: Line) => {
case "popover":
return (
{
@@ -11,6 +11,8 @@ export const createElements = (body: string) => {
};
const tokenize = (body: string) => {
+ body = body.replace(/\n?\n?/gs, "");
+
const paragraphs = body.split("\n\n");
const blockTokens: BlockToken[] = [];
@@ -97,129 +99,3 @@ const tokenize = (body: string) => {
return blockTokens.filter((b) => !b.parent);
};
-
-// const __tokenize = (md: string) => {
-// const tokens: (Token)[] = [];
-// // md = md.replace(/(?<=[a-z])\n(?=[a-z])/g, " ");
-// const lines = md.split("\n");
-// let preserveEmpty = false;
-// let multilineLines;
-// let tokenSettings;
-
-// for (let line of lines) {
-// if (!line && !preserveEmpty) continue;
-// let foundLine = false;
-
-// if (!multilineLines) {
-// token:
-// for (const token of multilineTokens) {
-// if (!token.rx.test(line)) continue token;
-// tokenSettings = token;
-// multilineLines = token.create(tokens);
-// preserveEmpty = true;
-// foundLine = true;
-// multilineLines.push({
-// type: "text",
-// line: token.replace(line),
-// });
-// }
-// } else {
-// foundLine = true;
-// if (tokenSettings?.closeRx?.test(line) || tokenSettings?.rx.test(line)) {
-// tokenSettings = undefined;
-// multilineLines = undefined;
-// preserveEmpty = false;
-// } else {
-// multilineLines.push({
-// type: "text",
-// line,
-// });
-// }
-// }
-
-// if (!multilineLines) {
-// token:
-// for (const token of singleLineTokens) {
-// if (!token.rx.test(line)) continue token;
-// foundLine = true;
-// line = line.replace(token.replaceRx, "").trim();
-
-// const lineContent = tokenizeInline(line);
-// token.create(lineContent, tokens);
-// }
-// }
-
-// if (foundLine) continue;
-
-// tokens.push({
-// type: "text",
-// line: tokenizeInline(line),
-// });
-// }
-
-// return tokens;
-// };
-
-const tokenizeLine = (
- line: string,
- previous?: SingleLineToken,
-): SingleLineToken => {
- for (const token of singleLineTokens) {
- if (!token.rx.test(line)) continue;
-
- const t = token.create(line);
-
- if (t.type === "h2") {
- }
-
- t.line = tokenizeInline(line.replace(token.replaceRx, ""));
- return t;
- }
-
- if (previous?.mends) {
- previous.raw += " " + line;
- previous.line = tokenizeInline(previous.raw.replace(previous.cfg!.rx, ""));
- return previous;
- }
-
- return {
- line: tokenizeInline(line),
- type: "text",
- raw: line,
- };
-};
-
-const tokenizeInline = (line: string) => {
- line = line.trim();
- const originalLine = line;
- const insertMarker = "\u{03A9}";
- const tokens: InlineTokenInsert[] = [];
-
- for (const token of inlineTokens) {
- token.rx.lastIndex = 0;
- let match;
- while ((match = token.rx.exec(line)) !== null) {
- const tokenStart = match.index;
- const tokenEnd = match.index + match[0].length;
-
- token.create(match, tokenStart, tokenEnd, tokens);
- }
- }
-
- if (tokens.length) {
- for (const insert of tokens) {
- line = line.slice(0, insert.start) +
- "".padStart(insert.end - insert.start, insertMarker) +
- line.slice(insert.end, line.length);
- }
-
- return zipArrays(
- line.split(new RegExp(insertMarker + "{2,}")).map((t): InlineToken => ({
- content: t,
- type: "text",
- })),
- tokens,
- ).filter((t) => t.content);
- }
- return originalLine;
-};
diff --git a/lib/tcmd/inlineTokens.ts b/lib/tcmd/tokenizeInline.ts
similarity index 50%
rename from lib/tcmd/inlineTokens.ts
rename to lib/tcmd/tokenizeInline.ts
index 9f9c2e2..a55e0c8 100644
--- a/lib/tcmd/inlineTokens.ts
+++ b/lib/tcmd/tokenizeInline.ts
@@ -1,3 +1,55 @@
+import { zipArrays } from "../zip";
+
+export const tokenizeInline = (line: string, recursive?: boolean) => {
+ if (recursive) console.log("recursive call");
+ line = line.trim();
+ const originalLine = line;
+ const insertMarker = "\u{03A9}";
+ const tokens: InlineTokenInsert[] = [];
+
+ for (const token of inlineTokens) {
+ const rx = new RegExp(token.rx);
+ let match;
+ while ((match = rx.exec(line)) !== null) {
+ const tokenStart = match.index;
+ const tokenEnd = match.index + match[0].length;
+
+ const wrappingToken = tokens.find((t) =>
+ t.start < tokenStart && t.end > tokenStart
+ );
+ if (wrappingToken) continue;
+
+ let wrappedToken;
+ while (
+ (wrappedToken = tokens.findIndex((t) =>
+ t.start > tokenStart && t.start < tokenEnd
+ )) !== -1
+ ) {
+ tokens.splice(wrappedToken, 1);
+ }
+
+ token.create(match, tokenStart, tokenEnd, tokens);
+ }
+ }
+
+ if (tokens.length) {
+ for (const insert of tokens) {
+ line = line.slice(0, insert.start) +
+ "".padStart(insert.end - insert.start, insertMarker) +
+ line.slice(insert.end, line.length);
+ }
+
+ return zipArrays(
+ line.split(new RegExp(insertMarker + "{2,}")).map((t): InlineToken => ({
+ content: t,
+ type: "text",
+ })),
+ tokens,
+ ).filter((t) => t.content);
+ }
+ return originalLine;
+};
+
const joiner = "<><>";
export const inlineTokens: {
rx: RegExp;
@@ -61,16 +113,17 @@ export const inlineTokens: {
},
},
{
- rx: /\^\[(.*?)\]\((.*?)\)/g,
+ rx: /\^\[(.*?)\]<<(.*?)>>/gm,
create(content, start, end, tokens) {
const [_, text, popover] = content;
+ // tokenizeInline("", true);
tokens.push({
content: text,
end,
start,
type: "popover",
data: {
- popover,
+ popover: tokenizeInline(popover),
},
});
},
diff --git a/lib/tcmd/singleLineTokens.ts b/lib/tcmd/tokenizeLine.ts
similarity index 56%
rename from lib/tcmd/singleLineTokens.ts
rename to lib/tcmd/tokenizeLine.ts
index 40c4c54..6288a08 100644
--- a/lib/tcmd/singleLineTokens.ts
+++ b/lib/tcmd/tokenizeLine.ts
@@ -1,3 +1,34 @@
+import { tokenizeInline } from "./tokenizeInline";
+
+export const tokenizeLine = (
+ line: string,
+ previous?: SingleLineToken,
+): SingleLineToken => {
+ for (const token of singleLineTokens) {
+ if (!token.rx.test(line)) continue;
+
+ const t = token.create(line);
+
+ if (t.type === "h2") {
+ }
+
+ t.line = tokenizeInline(line.replace(token.replaceRx, ""));
+ return t;
+ }
+
+ if (previous?.mends) {
+ previous.raw += " " + line;
+ previous.line = tokenizeInline(previous.raw.replace(previous.cfg!.rx, ""));
+ return previous;
+ }
+
+ return {
+ line: tokenizeInline(line),
+ type: "text",
+ raw: line,
+ };
+};
+
export const singleLineTokens: SingleLineCfg[] = [
{
rx: /^#\s/,
diff --git a/test.md b/test.md
index aebefb2..1dc5259 100644
--- a/test.md
+++ b/test.md
@@ -1,20 +1,24 @@
# Hello! Welcome to Tabletop Commander!
+
+
[][][]
[[
-Lorem ^[ipsum](This is a popover test) dolor sit amet, consectetur adipiscing
-elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-Sollicitudin tempor id eu nisl nunc mi ipsum faucibus vitae. Lobortis elementum
-nibh tellus molestie nunc. Purus non enim praesent elementum facilisis leo vel.
-Orci nulla pellentesque dignissim enim sit amet venenatis. Eu feugiat pretium
-nibh ipsum. Gravida dictum fusce ut placerat orci nulla pellentesque. Tincidunt
-vitae semper quis lectus nulla at volutpat diam ut. Proin sed libero enim sed
-faucibus turpis in eu mi. Dui sapien eget mi proin sed libero enim sed faucibus.
-Felis donec et odio pellentesque diam volutpat commodo sed egestas. Massa
-tincidunt dui ut ornare lectus sit amet est placerat. Auctor urna nunc id cursus
-metus aliquam eleifend.
+Lorem ^[ipsum]<>
+dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
+labore et dolore magna aliqua. Sollicitudin tempor id eu nisl nunc mi ipsum
+faucibus vitae. Lobortis elementum nibh tellus molestie nunc. Purus non enim
+praesent elementum facilisis leo vel. Orci nulla pellentesque dignissim enim sit
+amet venenatis. Eu feugiat pretium nibh ipsum. Gravida dictum fusce ut placerat
+orci nulla pellentesque. Tincidunt vitae semper quis lectus nulla at volutpat
+diam ut. Proin sed libero enim sed faucibus turpis in eu mi. Dui sapien eget mi
+proin sed libero enim sed faucibus. Felis donec et odio pellentesque diam
+volutpat commodo sed egestas. Massa tincidunt dui ut ornare lectus sit amet est
+placerat. Auctor urna nunc id cursus metus aliquam eleifend.
- Lorem ipsum dolor sit amet,
- consectetur adipiscing elit, bananana banana ban anana anaba bananananana
@@ -79,6 +83,8 @@ const blockTokens: {
this is the test of a single accordion
+
+
[/accordion]
]]