ttcMD: mostly working nested grid parser

This commit is contained in:
Emmaline Autumn 2024-03-12 23:52:31 -06:00
parent 32eb0c7408
commit 23cf8c263d
6 changed files with 183 additions and 35 deletions

3
.gitignore vendored
View File

@ -38,4 +38,5 @@ next-env.d.ts
# vscode
.vscode
temp.json
temp.json
temp.md

View File

@ -10,6 +10,7 @@ import { sanitize } from "isomorphic-dompurify";
import StaticGenerationSearchParamsBailoutProvider from "next/dist/client/components/static-generation-searchparams-bailout-provider";
export const TTCMD: FC<{ body: Promise<string> }> = ({ body }) => {
"use client";
const text = use(body);
const [elements, tabSpacing] = useMemo(() => createElements(text), [text]);
const tada = useMemo(

View File

@ -1,7 +1,18 @@
export const TokenIdentifiers = new Map<string, {
type TokenIdentifier = {
rx: RegExp;
parse: (s: string) => Token;
}>();
search?: (s: string, start: number, end: number) => {
start: number;
end: number;
text: string;
lastIndex: number;
};
};
export const TokenIdentifiers = new Map<
string,
TokenIdentifier
>();
// TokenIdentifiers.set("p", {
// rx: /\n{2,}((?:.|\n)*?)\n{2,}/g,
@ -81,14 +92,44 @@ TokenIdentifiers.set("list-item", {
},
});
TokenIdentifiers.set("grid", {
search(s, start, end) {
const rx = /(?<!\/)(?:\[\])+/g;
const closeRx = /\/\[\]/g;
const oldEnd = end;
const newEnd = findMatchingClosedParenthesis(
s,
rx,
closeRx,
);
if (newEnd === null) throw Error("BAD BAD BAD BAD");
end = newEnd + start;
return {
start,
end,
text: s.substring(0, newEnd),
lastIndex: oldEnd === end
? end
: start + s.match(new RegExp(rx))![0].length,
};
},
rx: /(?:\[\])+\n+((?:.|\n)*?)\n+\/\[\]/g,
parse(s) {
const rx = /((?:\[\])+)\n+([\s\S]*)\n+\/\[\]/;
console.log(s);
const [_, columns, content] = s.match(rx) ||
["", "..", "Unable to parse grid"];
console.log(columns);
return {
content: s.match(new RegExp(this.rx, ""))?.at(1) ||
"Unable to parse grid",
content,
raw: s,
metadata: {
columns: s.split("\n").at(0)?.match(/\[\]/g)?.length.toString() || "1",
columns: (columns.length / 2).toString(),
},
type: "grid",
uuid: crypto.randomUUID(),
@ -254,3 +295,49 @@ TokenIdentifiers.set("p", {
// const p = TokenIdentifiers.get("p");
// TokenIdentifiers.clear();
// p && TokenIdentifiers.set("p", p);
function findMatchingClosedParenthesis(
str: string,
openRegex: RegExp,
closedRegex: RegExp,
): number | null {
let openings = 0;
let closings = 0;
openRegex = new RegExp(openRegex, "g");
closedRegex = new RegExp(closedRegex, "g");
let lastOpeningSuccessIndex = 0;
let lastClosingSuccessIndex = 0;
debugger;
do {
const openingMatch = openRegex.exec(str);
const closingMatch = closedRegex.exec(str);
if ((openingMatch && !closingMatch)) {
throw Error("Things have gone horribly wrong");
}
// if ((!openingMatch && closingMatch) || (!openingMatch && !closingMatch)) break;
if (
openingMatch && closingMatch && openingMatch.index < closingMatch.index
) {
openings++;
lastOpeningSuccessIndex = openingMatch.index + openingMatch[0].length;
closedRegex.lastIndex = lastClosingSuccessIndex;
} else if (
(!openingMatch && closingMatch) ||
(openingMatch && closingMatch && openingMatch.index > closingMatch.index)
) {
closings++;
lastClosingSuccessIndex = closingMatch.index + closingMatch[0].length;
openRegex.lastIndex = lastOpeningSuccessIndex;
} else {
return closingMatch?.index ?? null;
}
} while (openings > closings);
return closedRegex.lastIndex;
}

View File

@ -35,6 +35,19 @@ const tokenize = (body: string) => {
const start = match.index;
const end = rx.lastIndex;
if (token.search) {
const found = token.search(body.substring(start), start, end);
rx.lastIndex = found.lastIndex;
addToken({
start: found.start,
end: found.end,
type,
token: token.parse(found.text),
});
continue;
}
addToken({
start,
end,
@ -69,34 +82,6 @@ function buildAbstractSyntaxTree(markers: TokenMarker[]) {
return markers;
}
// function establishClosestParent(blocks: TokenMarker[]): void {
// blocks.sort((a, b) => a.start - b.start); // Sort blocks by start position
// for (let i = 0; i < blocks.length; i++) {
// const block = blocks[i];
// if (block.parent) continue; // Skip blocks that already have a parent
// let closestParent: TokenMarker | undefined = undefined;
// let minDistance = Number.MAX_SAFE_INTEGER;
// // Find the closest parent block for each block
// for (let j = 0; j < i; j++) {
// const otherBlock = blocks[j];
// if (otherBlock.end >= block.start && otherBlock.start <= block.start) {
// const distance = block.start - otherBlock.start;
// if (distance < minDistance) {
// minDistance = distance;
// closestParent = otherBlock;
// }
// }
// }
// if (closestParent) {
// block.parent = closestParent; // Assign the closest parent block
// }
// }
// }
function establishClosestParent(blocks: TokenMarker[]): void {
blocks.sort((a, b) => a.start - b.start); // Sort blocks by start position
@ -166,6 +151,7 @@ function filterOverlappingPBlocks(blocks: TokenMarker[]): TokenMarker[] {
const contentToChildren = (token: Token) => {
let content = token.content;
if (!content) return;
const wasSpecialCase = handleSpecial(token);
@ -260,7 +246,6 @@ function processChunks(chunks: Token[][]) {
}
}
// console.log(chunks);
// Filter out chunks that were merged into others
return chunks.filter((c) => !mergedChunks.find((c2) => c === c2));
}

View File

@ -8,6 +8,7 @@
- [Block-level Elements](#block-level-elements)
- [Accordions](#accordions)
- [Card](#card)
- [Grid](#grid)
# How do you use ttcMD?
@ -101,6 +102,7 @@ super secret! I'll never tell!
]]
```
[[
Card text!
This is a real wild thing! Look, an accordion!
@ -119,4 +121,49 @@ And hurt you.
[/accordion]
]]
/[]
### Grid
Grid blocks give you access to basic grid layouts. You define the number of columns in the grid by using a number of matching brackets.
[][][]
[[
```
[][][]
This will make three columns, just like how this is laid out right now.
Each element will get its own cell in the grid.
So each of these paragraphs will end up in a separate column.
/[]
```
]]
[[
```
[][]
This will make two columns
[[
Each column can use a different element
]]
/[]
```
]]
[[
This card will end up in the third column...
]]
[[
... but since there isn't enough for this one, it will automatically get moved to the next row.
]]
/[]

27
md/help articles/test.md Normal file
View File

@ -0,0 +1,27 @@
# TEST
[][][]
[][][]
This will make three columns, just like how this is laid out right now.
Each element will get its own cell in the grid.
So each of these paragraphs will end up in a separate column.
/[]
[][]
This will make two columns
Each column can use a different element
/[]
This card will end up in the third column...
... but since there isn't enough for this one, it will automatically get moved to the next row.
/[]