From 335f29c4b307f8b48d656ef7973d53f47803d37a Mon Sep 17 00:00:00 2001 From: David Prothero Date: Thu, 14 Mar 2024 19:16:55 -0700 Subject: [PATCH] Fix split random tables --- LGMRD.md | 50 ++++++++++++------- README.md | 6 +-- markdown_obsidian/21 - Monster Templates.md | 54 ++++++++++++--------- markdown_separate/21-monstertemplates.md | 50 ++++++++++++------- metadata/updates.json | 6 +-- src/formats/markdown.ts | 15 ++---- src/formats/markdownObsidian.ts | 4 +- src/formats/markdownSeparate.ts | 6 ++- src/index.ts | 36 +++++++------- src/utils/markdown.ts | 37 ++++++++++++++ 10 files changed, 168 insertions(+), 96 deletions(-) diff --git a/LGMRD.md b/LGMRD.md index 3e832d9..7db6711 100644 --- a/LGMRD.md +++ b/LGMRD.md @@ -1164,12 +1164,16 @@ The challenge ratings described in these templates are loose guides, so use your Apply this template to any monster to make an elemental version of that monster. Choose from or roll on the following table to determine the type of elemental template you want to apply: -| d8 | Elemental Template | d8 | Elemental Template | -| -- | ------------------ | -- | ------------------ | -| 1 | Fire | 5 | Poison | -| 2 | Cold | 6 | Necrotic | -| 3 | Lighting | 7 | Radiant | -| 4 | Acid | 8 | Thunder | +| d8 | Elemental Template | +| -- | ------------------ | +| 1 | Fire | +| 2 | Cold | +| 3 | Lighting | +| 4 | Acid | +| 5 | Poison | +| 6 | Necrotic | +| 7 | Radiant | +| 8 | Thunder | Then choose one or more of the following traits to customize your monster, making use of the damage type determined by the elemental template: @@ -1219,18 +1223,28 @@ Some monsters can innately cast magical spells. Spell-infused monsters typically Spell-infused creatures do not require components to cast their spells. They typically use each of their spells once, recovering the ability to do so when they finish a long rest. Roll for or choose from the table to determine which spells a creature can use. Spells that deal high damage can affect a creature's challenge rating. -| d20 | Spell | d20 | Spell | -| --- | -------------- | --- | ---------------- | -| 1 | Burning hands | 11 | Invisibility | -| 2 | Magic missile | 12 | Misty step | -| 3 | Disguise self | 13 | Scorching ray | -| 4 | Fog cloud | 14 | Shatter | -| 5 | Shield | 15 | Spirit guardians | -| 6 | Inflict wounds | 16 | Dispel magic | -| 7 | Faerie fire | 17 | Fly | -| 8 | Thunderwave | 18 | Gaseous form | -| 9 | Blur | 19 | Lightning bolt | -| 10 | Darkness | 20 | Fireball | +| d20 | Spell | +| --- | ---------------- | +| 1 | Burning hands | +| 2 | Magic missile | +| 3 | Disguise self | +| 4 | Fog cloud | +| 5 | Shield | +| 6 | Inflict wounds | +| 7 | Faerie fire | +| 8 | Thunderwave | +| 9 | Blur | +| 10 | Darkness | +| 11 | Invisibility | +| 12 | Misty step | +| 13 | Scorching ray | +| 14 | Shatter | +| 15 | Spirit guardians | +| 16 | Dispel magic | +| 17 | Fly | +| 18 | Gaseous form | +| 19 | Lightning bolt | +| 20 | Fireball | ## Undead Templates diff --git a/README.md b/README.md index 146e2bb..465924e 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ LGMRD is officially pronounced "Lymm Grid" and LGMMBRD "Lymm Bard". ### The Lazy GM's Resource Document - [HTML](https://github.com/crit-tech/LGMRD/blob/main/LGMRD.html) **Updated: Thu, 08 Feb 2024 02:14:22 GMT** -- [All-in-one Markdown](https://github.com/crit-tech/LGMRD/blob/main/LGMRD.md) **Updated: Sun, 10 Mar 2024 23:21:26 GMT** -- [Separate Markdown](https://github.com/crit-tech/LGMRD/tree/main/markdown_separate) files **Updated: Fri, 15 Mar 2024 00:39:57 GMT** -- [Markdown for Obsidian](https://github.com/crit-tech/LGMRD/tree/main/markdown_obsidian) **Updated: Fri, 15 Mar 2024 00:39:58 GMT** +- [All-in-one Markdown](https://github.com/crit-tech/LGMRD/blob/main/LGMRD.md) **Updated: Fri, 15 Mar 2024 02:06:34 GMT** +- [Separate Markdown](https://github.com/crit-tech/LGMRD/tree/main/markdown_separate) files **Updated: Fri, 15 Mar 2024 02:11:52 GMT** +- [Markdown for Obsidian](https://github.com/crit-tech/LGMRD/tree/main/markdown_obsidian) **Updated: Fri, 15 Mar 2024 02:11:53 GMT** - [JSON](https://github.com/crit-tech/LGMRD/blob/main/LGMRD.json) **Updated: Fri, 15 Mar 2024 00:39:58 GMT** - [NPM](https://www.npmjs.com/package/@crit-tech/lgmrd) **Updated: Fri, 15 Mar 2024 00:39:58 GMT** - [PDF](https://github.com/crit-tech/LGMRD/blob/main/LGMRD.pdf) **Updated: Thu, 08 Feb 2024 02:14:24 GMT** diff --git a/markdown_obsidian/21 - Monster Templates.md b/markdown_obsidian/21 - Monster Templates.md index d37f737..2b3253d 100644 --- a/markdown_obsidian/21 - Monster Templates.md +++ b/markdown_obsidian/21 - Monster Templates.md @@ -8,16 +8,18 @@ The challenge ratings described in these templates are loose guides, so use your Apply this template to any monster to make an elemental version of that monster. Choose from or roll on the following table to determine the type of elemental template you want to apply: -**Elemental Template: **`dice: [[21 - Monster Templates#^elemental-monsters]]|Elemental Template` -**d8: **`dice: [[21 - Monster Templates#^elemental-monsters]]|d8` **Elemental Template: **`dice: [[21 - Monster Templates#^elemental-monsters]]|Elemental Template` -| d8 | Elemental Template | d8 | Elemental Template | -| -- | ------------------ | -- | ------------------ | -| 1 | Fire | 5 | Poison | -| 2 | Cold | 6 | Necrotic | -| 3 | Lighting | 7 | Radiant | -| 4 | Acid | 8 | Thunder | +| d8 | Elemental Template | +| -- | ------------------ | +| 1 | Fire | +| 2 | Cold | +| 3 | Lighting | +| 4 | Acid | +| 5 | Poison | +| 6 | Necrotic | +| 7 | Radiant | +| 8 | Thunder | ^elemental-monsters @@ -69,21 +71,29 @@ Some monsters can innately cast magical spells. Spell-infused monsters typically Spell-infused creatures do not require components to cast their spells. They typically use each of their spells once, recovering the ability to do so when they finish a long rest. Roll for or choose from the table to determine which spells a creature can use. Spells that deal high damage can affect a creature's challenge rating. -**Spell: **`dice: [[21 - Monster Templates#^spell-infused-monsters]]|Spell` -**d20: **`dice: [[21 - Monster Templates#^spell-infused-monsters]]|d20` **Spell: **`dice: [[21 - Monster Templates#^spell-infused-monsters]]|Spell` -| d20 | Spell | d20 | Spell | -| --- | -------------- | --- | ---------------- | -| 1 | Burning hands | 11 | Invisibility | -| 2 | Magic missile | 12 | Misty step | -| 3 | Disguise self | 13 | Scorching ray | -| 4 | Fog cloud | 14 | Shatter | -| 5 | Shield | 15 | Spirit guardians | -| 6 | Inflict wounds | 16 | Dispel magic | -| 7 | Faerie fire | 17 | Fly | -| 8 | Thunderwave | 18 | Gaseous form | -| 9 | Blur | 19 | Lightning bolt | -| 10 | Darkness | 20 | Fireball | +| d20 | Spell | +| --- | ---------------- | +| 1 | Burning hands | +| 2 | Magic missile | +| 3 | Disguise self | +| 4 | Fog cloud | +| 5 | Shield | +| 6 | Inflict wounds | +| 7 | Faerie fire | +| 8 | Thunderwave | +| 9 | Blur | +| 10 | Darkness | +| 11 | Invisibility | +| 12 | Misty step | +| 13 | Scorching ray | +| 14 | Shatter | +| 15 | Spirit guardians | +| 16 | Dispel magic | +| 17 | Fly | +| 18 | Gaseous form | +| 19 | Lightning bolt | +| 20 | Fireball | ^spell-infused-monsters diff --git a/markdown_separate/21-monstertemplates.md b/markdown_separate/21-monstertemplates.md index f97c87b..d5fa4b7 100644 --- a/markdown_separate/21-monstertemplates.md +++ b/markdown_separate/21-monstertemplates.md @@ -10,12 +10,16 @@ The challenge ratings described in these templates are loose guides, so use your Apply this template to any monster to make an elemental version of that monster. Choose from or roll on the following table to determine the type of elemental template you want to apply: -| d8 | Elemental Template | d8 | Elemental Template | -| -- | ------------------ | -- | ------------------ | -| 1 | Fire | 5 | Poison | -| 2 | Cold | 6 | Necrotic | -| 3 | Lighting | 7 | Radiant | -| 4 | Acid | 8 | Thunder | +| d8 | Elemental Template | +| -- | ------------------ | +| 1 | Fire | +| 2 | Cold | +| 3 | Lighting | +| 4 | Acid | +| 5 | Poison | +| 6 | Necrotic | +| 7 | Radiant | +| 8 | Thunder | Then choose one or more of the following traits to customize your monster, making use of the damage type determined by the elemental template: @@ -65,15 +69,25 @@ Some monsters can innately cast magical spells. Spell-infused monsters typically Spell-infused creatures do not require components to cast their spells. They typically use each of their spells once, recovering the ability to do so when they finish a long rest. Roll for or choose from the table to determine which spells a creature can use. Spells that deal high damage can affect a creature's challenge rating. -| d20 | Spell | d20 | Spell | -| --- | -------------- | --- | ---------------- | -| 1 | Burning hands | 11 | Invisibility | -| 2 | Magic missile | 12 | Misty step | -| 3 | Disguise self | 13 | Scorching ray | -| 4 | Fog cloud | 14 | Shatter | -| 5 | Shield | 15 | Spirit guardians | -| 6 | Inflict wounds | 16 | Dispel magic | -| 7 | Faerie fire | 17 | Fly | -| 8 | Thunderwave | 18 | Gaseous form | -| 9 | Blur | 19 | Lightning bolt | -| 10 | Darkness | 20 | Fireball | +| d20 | Spell | +| --- | ---------------- | +| 1 | Burning hands | +| 2 | Magic missile | +| 3 | Disguise self | +| 4 | Fog cloud | +| 5 | Shield | +| 6 | Inflict wounds | +| 7 | Faerie fire | +| 8 | Thunderwave | +| 9 | Blur | +| 10 | Darkness | +| 11 | Invisibility | +| 12 | Misty step | +| 13 | Scorching ray | +| 14 | Shatter | +| 15 | Spirit guardians | +| 16 | Dispel magic | +| 17 | Fly | +| 18 | Gaseous form | +| 19 | Lightning bolt | +| 20 | Fireball | diff --git a/metadata/updates.json b/metadata/updates.json index c2337a8..f2e17d1 100644 --- a/metadata/updates.json +++ b/metadata/updates.json @@ -1,6 +1,6 @@ { - "markdown": "2024-03-10T23:21:26.543Z", - "markdown_separate": "2024-03-15T00:39:57.825Z", + "markdown": "2024-03-15T02:06:34.682Z", + "markdown_separate": "2024-03-15T02:11:52.524Z", "json": "2024-03-15T00:39:58.871Z", "html": "2024-02-08T02:14:22.742Z", "pdf": "2024-02-08T02:14:24.868Z", @@ -11,6 +11,6 @@ "mb-markdown": "2024-03-10T23:21:27.774Z", "mb-markdown_separate": "2024-03-15T00:40:01.262Z", "mb-json": "2024-03-15T00:40:01.862Z", - "markdown_obsidian": "2024-03-15T00:39:58.360Z", + "markdown_obsidian": "2024-03-15T02:11:53.171Z", "mb-markdown_obsidian": "2024-03-15T00:40:01.661Z" } diff --git a/src/formats/markdown.ts b/src/formats/markdown.ts index 0f43f88..5f88f67 100644 --- a/src/formats/markdown.ts +++ b/src/formats/markdown.ts @@ -7,19 +7,11 @@ import { defaultHandlers, State } from "hast-util-to-mdast"; import remarkGfm from "remark-gfm"; import remarkStringify from "remark-stringify"; import { Heading as MarkdownHeading } from "mdast"; -import { Root } from "mdast"; import getHtmlPlugin from "../utils/html.js"; import removePosition from "../utils/removePosition.js"; import { DocType, OUTPUT_PATH } from "../utils/constants.js"; - -function getMarkdownPlugin(callback: (tree: Root) => void) { - return () => { - return (tree: Root) => { - callback(tree); - }; - }; -} +import { getMarkdownPlugin, columnSmasherPlugin } from "../utils/markdown.js"; function getHeadingHandler(tagName: string) { return (state: State, node: any) => { @@ -57,7 +49,7 @@ export async function convertToMarkdown( ); }); - const markdownPlugin = getMarkdownPlugin((tree) => { + const saveSyntaxTreePlugin = getMarkdownPlugin((tree) => { const treeCopy = removePosition(tree); fs.writeFileSync( path.join(OUTPUT_PATH, "metadata", `${docType}_mdast.json`), @@ -77,7 +69,8 @@ export async function convertToMarkdown( .use(htmlPlugin) .use(rehypeRemark, rehypeRemarkOptions) .use(remarkGfm) - .use(markdownPlugin) + .use(saveSyntaxTreePlugin) + .use(columnSmasherPlugin) .use(remarkStringify) .process(html); diff --git a/src/formats/markdownObsidian.ts b/src/formats/markdownObsidian.ts index 332a1a1..d5b6614 100644 --- a/src/formats/markdownObsidian.ts +++ b/src/formats/markdownObsidian.ts @@ -3,8 +3,8 @@ TODO: - [X] Both - Order the pages by the order they appear in the book -- [ ] Both - Change detection not working (thinks it's new each time) -- [ ] LGMRD - Monster templates (has two-column tables) +- [X] Both - Change detection not working (thinks it's new each time) +- [X] LGMRD - Monster templates (has two-column tables) - [ ] LGMRD - Random items / Potions of healing - has table rows with ranges - [ ] LGMMBRD - General purpose statblocks - [ ] LGMMBRD - Monsters by Adventure Location has broken tables (also for regular markdown) diff --git a/src/formats/markdownSeparate.ts b/src/formats/markdownSeparate.ts index 94c18bc..d3664f5 100644 --- a/src/formats/markdownSeparate.ts +++ b/src/formats/markdownSeparate.ts @@ -13,7 +13,10 @@ import { visit } from "unist-util-visit"; import { rehypeRemarkOptions } from "./markdown.js"; import { DocType, MARKDOWN_SEPARATE_PATHS } from "../utils/constants.js"; -import { getAndDeletePreviousMarkdown } from "../utils/markdown.js"; +import { + getAndDeletePreviousMarkdown, + columnSmasherPlugin, +} from "../utils/markdown.js"; interface Section { sectionName: string; @@ -59,6 +62,7 @@ export async function convertToMarkdownSeparate( .use(rehypeParse) .use(rehypeRemark, rehypeRemarkOptions) .use(remarkGfm) + .use(columnSmasherPlugin) .use(sectionCapturePlugin) .use(remarkStringify) .process(html); diff --git a/src/index.ts b/src/index.ts index 1d66511..33266b7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,19 +25,19 @@ async function createOutput(docType: DocType) { logUpdate(docType, "html"); } - if ( - html !== prevHtml || - !fs.existsSync(path.join(OUTPUT_PATH, `${docType}.pdf`)) - ) { - await convertToPdf(docType, html); - logUpdate(docType, "pdf"); - } + // if ( + // html !== prevHtml || + // !fs.existsSync(path.join(OUTPUT_PATH, `${docType}.pdf`)) + // ) { + // await convertToPdf(docType, html); + // logUpdate(docType, "pdf"); + // } - const epubPath = path.join(OUTPUT_PATH, `${docType}.epub`); - if (html !== prevHtml || !fs.existsSync(epubPath)) { - await convertToEpub(docType, filePath, epubPath); - logUpdate(docType, "epub"); - } + // const epubPath = path.join(OUTPUT_PATH, `${docType}.epub`); + // if (html !== prevHtml || !fs.existsSync(epubPath)) { + // await convertToEpub(docType, filePath, epubPath); + // logUpdate(docType, "epub"); + // } const markdownUpdated = await convertToMarkdown(docType, html); if (markdownUpdated) { @@ -60,17 +60,17 @@ async function createOutput(docType: DocType) { logUpdate(docType, "markdown_obsidian"); } - const jsonUpdated = await convertToJson(docType); - if (jsonUpdated) { - logUpdate(docType, "json"); - } + // const jsonUpdated = await convertToJson(docType); + // if (jsonUpdated) { + // logUpdate(docType, "json"); + // } - await publishJsonPackage(docType); + // await publishJsonPackage(docType); } async function run() { await createOutput("LGMRD"); - await createOutput("5e_Monster_Builder"); + // await createOutput("5e_Monster_Builder"); } run(); diff --git a/src/utils/markdown.ts b/src/utils/markdown.ts index 8de866c..94747c5 100644 --- a/src/utils/markdown.ts +++ b/src/utils/markdown.ts @@ -1,6 +1,17 @@ import fs from "fs"; import path from "path"; +import { Root, Table, TableCell, TableRow } from "mdast"; +import { visit } from "unist-util-visit"; + +export function getMarkdownPlugin(callback: (tree: Root) => void) { + return () => { + return (tree: Root) => { + callback(tree); + }; + }; +} + export function getMarkdownFiles(folder: string): string[] { return fs .readdirSync(folder) @@ -23,3 +34,29 @@ export function getAndDeletePreviousMarkdown(folder: string): string { .join("\n") ); } + +const isDieRoll = (cell: TableCell) => + cell.children[0].type === "text" && cell.children[0].value.startsWith("d"); + +export const columnSmasherPlugin = getMarkdownPlugin((tree) => { + const tables: Table[] = []; + visit(tree, "table", (node) => { + tables.push(node); + }); + + for (const table of tables) { + const headerRow = table.children[0]; + if (headerRow.children.length !== 4) continue; + const [header1, _header2, header3] = headerRow.children; + if (!isDieRoll(header1) || !isDieRoll(header3)) continue; + + const newRows: TableRow[] = []; + for (const row of table.children) { + const [cell1, cell2, cell3, cell4] = row.children; + row.children = [cell1, cell2]; + if (isDieRoll(cell3)) continue; // don't add another header row + newRows.push({ type: "tableRow", children: [cell3, cell4] }); + } + table.children = [...table.children, ...newRows]; + } +});