From dafb240517a31d6b6a8508df6ef0b9b3e74d51d7 Mon Sep 17 00:00:00 2001
From: Bad Manners <me@badmanners.xyz>
Date: Wed, 14 Aug 2024 01:51:57 -0300
Subject: [PATCH] Update Marked dependency

---
 package-lock.json                  | 12 ++---
 package.json                       |  4 +-
 src/utils/markdown_to_bbcode.ts    | 83 +++++++++++++++++++++---------
 src/utils/markdown_to_plaintext.ts | 81 ++++++++++++++++++++---------
 4 files changed, 124 insertions(+), 56 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 7c8dcc0..4a64265 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "gallery-badmanners-xyz",
-  "version": "1.7.1",
+  "version": "1.7.2",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "gallery-badmanners-xyz",
-      "version": "1.7.1",
+      "version": "1.7.2",
       "hasInstallScript": true,
       "dependencies": {
         "@astrojs/check": "^0.9.2",
@@ -17,7 +17,7 @@
         "astro": "^4.13.3",
         "astro-pagefind": "^1.6.0",
         "github-slugger": "^2.0.0",
-        "marked": "^12.0.2",
+        "marked": "^14.0.0",
         "pagefind": "^1.1.0",
         "reading-time": "^1.5.0",
         "sanitize-html": "^2.13.0",
@@ -4263,9 +4263,9 @@
       }
     },
     "node_modules/marked": {
-      "version": "12.0.2",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz",
-      "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==",
+      "version": "14.0.0",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz",
+      "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==",
       "license": "MIT",
       "bin": {
         "marked": "bin/marked.js"
diff --git a/package.json b/package.json
index 9d7eb88..f74b3d0 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "gallery-badmanners-xyz",
   "type": "module",
-  "version": "1.7.1",
+  "version": "1.7.2",
   "scripts": {
     "postinstall": "astro sync",
     "dev": "astro dev",
@@ -23,7 +23,7 @@
     "astro": "^4.13.3",
     "astro-pagefind": "^1.6.0",
     "github-slugger": "^2.0.0",
-    "marked": "^12.0.2",
+    "marked": "^14.0.0",
     "pagefind": "^1.1.0",
     "reading-time": "^1.5.0",
     "sanitize-html": "^2.13.0",
diff --git a/src/utils/markdown_to_bbcode.ts b/src/utils/markdown_to_bbcode.ts
index b7e6c82..588ac37 100644
--- a/src/utils/markdown_to_bbcode.ts
+++ b/src/utils/markdown_to_bbcode.ts
@@ -1,33 +1,70 @@
-import { Marked, type RendererApi } from "marked";
+import { Marked, type RendererObject } from "marked";
 import { decode } from "tiny-decode";
 
-const renderer: RendererApi = {
-  strong: (text) => `[b]${text}[/b]`,
-  em: (text) => `[i]${text}[/i]`,
-  del: (text) => `[s]${text}[/s]`,
-  codespan: (code) => code,
-  br: () => `\n\n`,
-  link: (href, _, text) => `[url=${href}]${text}[/url]`,
-  image: (href) => `[img]${href}[/img]`,
-  text: (text) => text,
-  paragraph: (text) => `\n${text}\n`,
-  list: (body, ordered) => (ordered ? `\n[ol]\n${body}[/ol]\n` : `\n[ul]\n${body}[/ul]\n`),
-  listitem: (text) => `[li]${text}[/li]\n`,
-  blockquote: (quote) => `\n[quote]${quote}[/quote]\n`,
-  code: (code) => `\n[code]${code}[/code]\n`,
-  heading: (heading) => `\n${heading}\n`,
-  table: (header, body) => `\n[table]\n${header}${body}[/table]\n`,
-  tablerow: (content) => `[tr]\n${content}[/tr]\n`,
-  tablecell: (content, { header }) => (header ? `[th]${content}[/th]\n` : `[td]${content}[/td]\n`),
-  hr: () => `\n===\n`,
-  html: () => {
+const renderer: RendererObject = {
+  code({ text }) {
+    return `\n[code]${text}[/code]\n`;
+  },
+  blockquote({ tokens }) {
+    return `\n[quote]${this.parser.parseInline(tokens)}[/quote]\n`;
+  },
+  html() {
     throw new Error("Not supported by BBCode: html");
   },
-  checkbox: () => {
+  heading({ tokens }) {
+    return `\n${this.parser.parseInline(tokens)}\n`;
+  },
+  hr() {
+    return `\n===\n`;
+  },
+  list({ ordered, items }) {
+    const tag = ordered ? "ol" : "ul";
+    return `\n[${tag}]\n${items.map(this.listitem).join("\n")}[/${tag}]\n`;
+  },
+  listitem({ tokens }) {
+    return `[li]${this.parser.parseInline(tokens)}[/li]\n`;
+  },
+  checkbox() {
     throw new Error("Not supported by BBCode: checkbox");
   },
+  paragraph({ tokens }) {
+    return `\n${this.parser.parseInline(tokens)}\n`;
+  },
+  table({ header, rows }) {
+    return `\n[table]\n${this.tablerow({ text: header.map(this.tablecell).join("\n") })}\n${rows
+      .map((row) => this.tablerow({ text: row.map(this.tablecell).join("\n") }))
+      .join("\n")}[/table]\n`;
+  },
+  tablerow({ text }) {
+    return `[tr]\n${text}[/tr]\n`;
+  },
+  tablecell({ header, tokens }) {
+    const tag = header ? "th" : "td";
+    return `[${tag}]${this.parser.parseInline(tokens)}[/${tag}]\n`;
+  },
+  strong({ tokens }) {
+    return `[b]${this.parser.parseInline(tokens)}[/b]`;
+  },
+  em({ tokens }) {
+    return `[i]${this.parser.parseInline(tokens)}[/i]`;
+  },
+  codespan({ text }) {
+    return text;
+  },
+  br() {
+    return "\n\n";
+  },
+  del({ tokens }) {
+    return `[s]${this.parser.parseInline(tokens)}[/s]`;
+  },
+  link({ href, tokens }) {
+    return `[url=${href}]${this.parser.parseInline(tokens)}[/url]`;
+  },
+  image({ href }) {
+    return `[img]${href}[/url]`;
+  },
 };
 
 const bbcodeRenderer = new Marked({ renderer, async: false });
 
-export const markdownToBbcode = (text: string) => decode((bbcodeRenderer.parse(text) as string).trim());
+export const markdownToBbcode = (text: string) => decode(bbcodeRenderer.parse(text, { async: false }).trim());
diff --git a/src/utils/markdown_to_plaintext.ts b/src/utils/markdown_to_plaintext.ts
index 9042718..76cabae 100644
--- a/src/utils/markdown_to_plaintext.ts
+++ b/src/utils/markdown_to_plaintext.ts
@@ -1,37 +1,68 @@
-import { Marked, type RendererApi } from "marked";
+import { Marked, type RendererObject } from "marked";
 import { decode } from "tiny-decode";
 
-const renderer: RendererApi = {
-  strong: (text) => text,
-  em: (text) => `_${text}_`,
-  codespan: (code) => code,
-  br: () => `\n\n`,
-  link: (_href, _title, text) => text,
-  text: (text) => text,
-  paragraph: (text) => `\n${text}\n`,
-  list: (body) => `\n${body}\n`,
-  listitem: (text) => `- ${text}\n`,
-  blockquote: (quote) => `\n> ${quote}\n`,
-  code: (code) => `\n${code}\n`,
-  heading: (heading) => `\n== ${heading} ==\n`,
-  table: (header, body) => `\n${header}\n---\n${body}\n`,
-  tablerow: (content) => `${content.slice(0, -3)}\n`,
-  tablecell: (content) => `${content} | `,
-  hr: () => `\n***\n`,
-  del: () => {
-    throw new Error("Not supported by plaintext: del");
+const renderer: RendererObject = {
+  code({ text }) {
+    return `\n${text}\n`;
   },
-  image: () => {
-    throw new Error("Not supported by plaintext: img");
+  blockquote({ tokens }) {
+    return `\n> ${this.parser.parseInline(tokens)}\n`;
   },
-  html: () => {
+  html() {
     throw new Error("Not supported by plaintext: html");
   },
-  checkbox: () => {
+  heading({ tokens }) {
+    return `\n== ${this.parser.parseInline(tokens)} ==\n`;
+  },
+  hr() {
+    return `\n***\n`;
+  },
+  list({ items }) {
+    return `\n${items.map(this.listitem).join("\n")}\n`;
+  },
+  listitem({ tokens }) {
+    return `- ${this.parser.parseInline(tokens)}\n`;
+  },
+  checkbox() {
     throw new Error("Not supported by plaintext: checkbox");
   },
+  paragraph({ tokens }) {
+    return `\n${this.parser.parseInline(tokens)}\n`;
+  },
+  table({ header, rows }) {
+    return `\n${this.tablerow({ text: header.map(this.tablecell).join(" | ") })}\n---\n${rows
+      .map((row) => this.tablerow({ text: row.map(this.tablecell).join(" | ") }))
+      .join("\n")}\n`;
+  },
+  tablerow({ text }) {
+    return text;
+  },
+  tablecell({ tokens }) {
+    return this.parser.parseInline(tokens);
+  },
+  strong({ tokens }) {
+    return this.parser.parseInline(tokens);
+  },
+  em({ tokens }) {
+    return `_${this.parser.parseInline(tokens)}_`;
+  },
+  codespan({ text }) {
+    return text;
+  },
+  br() {
+    return "\n\n";
+  },
+  del() {
+    throw new Error("Not supported by plaintext: del");
+  },
+  link({ tokens }) {
+    return this.parser.parseInline(tokens);
+  },
+  image() {
+    throw new Error("Not supported by plaintext: img");
+  },
 };
 
 const plaintextRenderer = new Marked({ renderer, async: false });
 
-export const markdownToPlaintext = (text: string) => decode((plaintextRenderer.parse(text) as string).trim());
+export const markdownToPlaintext = (text: string) => decode(plaintextRenderer.parse(text, { async: false }).trim());