From ae4136bf0e61b0e5e98fb6eea7b930c986f20dab Mon Sep 17 00:00:00 2001
From: Oleksii Nazarenko <alexeybread81@gmail.com>
Date: Thu, 20 Jun 2024 10:25:19 +0100
Subject: [PATCH 1/3] create a function to get extra content

---
 package.json                                 |  1 +
 src/components/router/useSmoothRouter.tsx    |  3 +-
 src/content/parsers/parser.ts                |  5 +-
 src/content/parsers/table/getExtraContent.ts | 25 +++++++++
 src/content/parsers/table/parseTable.ts      |  8 ++-
 src/pages/content/index.tsx                  |  5 +-
 src/pages/content/pages/Folder.tsx           |  3 +-
 yarn.lock                                    | 58 +++++++++++++++++++-
 8 files changed, 99 insertions(+), 9 deletions(-)
 create mode 100644 src/content/parsers/table/getExtraContent.ts

diff --git a/package.json b/package.json
index fdaf30e..ad2b762 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
         "class-variance-authority": "^0.7.0",
         "clsx": "^2.1.0",
         "cmdk": "^1.0.0",
+        "html-react-parser": "^5.1.10",
         "lucide-react": "^0.365.0",
         "react": "^18.2.0",
         "react-dom": "^18.2.0",
diff --git a/src/components/router/useSmoothRouter.tsx b/src/components/router/useSmoothRouter.tsx
index ff1d3ea..fb54e64 100644
--- a/src/components/router/useSmoothRouter.tsx
+++ b/src/components/router/useSmoothRouter.tsx
@@ -30,7 +30,8 @@ const useSmoothRouter = () => {
                     pageData = parsePageContent(document.body)
                     title = document.title
 
-                    history.replaceState({ ...pageData }, "", href)
+                    const now = new Date().getTime()
+                    history.replaceState({ now }, "", href)
                 }
 
                 document.title = title
diff --git a/src/content/parsers/parser.ts b/src/content/parsers/parser.ts
index 7cd0fc1..bd3d96f 100644
--- a/src/content/parsers/parser.ts
+++ b/src/content/parsers/parser.ts
@@ -3,6 +3,7 @@ import { FileLink, SortLinks } from "../../types/pageContentTypes"
 import { getPageHeader } from "./getPageHeader"
 import { parseTable } from "./table/parseTable"
 import { isRootPage } from "@src/components/router/isRootPage"
+import { ReactNode } from "react"
 
 export type PageType = "folder" | "not found" | "root" | "unknown"
 
@@ -14,6 +15,7 @@ export interface FolderContent {
     title: string
     sortLinks: SortLinks
     fileLinks: FileLink[]
+    extraContent: ReactNode
 }
 
 export interface FolderPageData extends BasePageData {
@@ -59,7 +61,7 @@ export function parsePageContent(content: HTMLElement): PageData {
 
     try {
         const title = getPageHeader(content)
-        const { fileLinks, sortLinks } = parseTable(content)
+        const { fileLinks, sortLinks, extraContent } = parseTable(content)
 
         if (fileLinks.length > 0) {
             return {
@@ -68,6 +70,7 @@ export function parsePageContent(content: HTMLElement): PageData {
                     title,
                     fileLinks,
                     sortLinks,
+                    extraContent,
                 },
             }
         }
diff --git a/src/content/parsers/table/getExtraContent.ts b/src/content/parsers/table/getExtraContent.ts
new file mode 100644
index 0000000..761e1d9
--- /dev/null
+++ b/src/content/parsers/table/getExtraContent.ts
@@ -0,0 +1,25 @@
+import parse from "html-react-parser"
+import { ReactNode } from "react"
+
+export function getExtraContent(htmlElement: HTMLElement): ReactNode {
+    // Save the original innerHTML
+    const originalHTML = htmlElement.innerHTML
+
+    try {
+        const firstH1 = htmlElement.querySelector("h1")
+        const firstTable = htmlElement.querySelector("table")
+
+        if (firstH1) {
+            firstH1.remove()
+        }
+
+        if (firstTable) {
+            firstTable.remove()
+        }
+
+        return parse(htmlElement.innerHTML)
+    } finally {
+        // Restore the original innerHTML
+        htmlElement.innerHTML = originalHTML
+    }
+}
diff --git a/src/content/parsers/table/parseTable.ts b/src/content/parsers/table/parseTable.ts
index df4dd64..405fda8 100644
--- a/src/content/parsers/table/parseTable.ts
+++ b/src/content/parsers/table/parseTable.ts
@@ -1,4 +1,6 @@
+import { ReactNode } from "react"
 import { FileLink, SortLinks } from "../../../types/pageContentTypes"
+import { getExtraContent } from "./getExtraContent"
 import { getTableRows } from "./getTableRows"
 import { parseFileLinkRows } from "./parseFileLinkRows"
 import { parseHeaderRow } from "./parseHeaderRow"
@@ -6,13 +8,15 @@ import { parseHeaderRow } from "./parseHeaderRow"
 /**
  * Parses a table to extract sort links and file links.
  * @param {HTMLElement} content - The content of the table to parse.
- * @returns {{ sortLinks: SortLinks, fileLinks: FileLink[] }} An object containing the sort links and file links.
+ * @returns {{ sortLinks: SortLinks, fileLinks: FileLink[], extraContent: ReactNode }}
  */
 export function parseTable(content: HTMLElement): {
     sortLinks: SortLinks
     fileLinks: FileLink[]
+    extraContent: ReactNode
 } {
     const tableRows = getTableRows(content)
+    const extraContent = getExtraContent(content)
 
     // eslint-disable-next-line @typescript-eslint/no-unused-vars
     const [headerRow, ...fileLinkRows] = tableRows
@@ -24,5 +28,5 @@ export function parseTable(content: HTMLElement): {
     const sortLinks: SortLinks = parseHeaderRow(headerRow)
     const fileLinks: FileLink[] = parseFileLinkRows(fileLinkRows)
 
-    return { sortLinks, fileLinks }
+    return { sortLinks, fileLinks, extraContent }
 }
diff --git a/src/pages/content/index.tsx b/src/pages/content/index.tsx
index 3dbfbf5..5dda962 100644
--- a/src/pages/content/index.tsx
+++ b/src/pages/content/index.tsx
@@ -10,7 +10,8 @@ try {
     rootContainer.style.overflowY = "scroll" // show scroll bar
 
     const pageData: PageData = parsePageContent(rootContainer)
-    history.replaceState({ ...pageData }, "", location.href.toString())
+    const now = new Date().getTime()
+    history.replaceState({ now }, "", location.href.toString())
 
     if (pageData.type === "unknown") {
         throw new Error("unknown page type")
@@ -35,6 +36,8 @@ try {
     )
 } catch (e) {
     // load only commands then
+    console.log("fallback")
+    console.log(e)
     const div = document.createElement("div")
     div.className = "__better_studres__root _tailwind_preflight_reset"
     document.body.appendChild(div)
diff --git a/src/pages/content/pages/Folder.tsx b/src/pages/content/pages/Folder.tsx
index 5b204d3..79bbd29 100644
--- a/src/pages/content/pages/Folder.tsx
+++ b/src/pages/content/pages/Folder.tsx
@@ -20,7 +20,7 @@ interface FolderProps {
 }
 
 export default function Folder({ content }: FolderProps) {
-    const { fileLinks, sortLinks } = content
+    const { fileLinks, sortLinks, extraContent } = content
 
     const { isLoading } = useContext(PageStateContext)
 
@@ -53,6 +53,7 @@ export default function Folder({ content }: FolderProps) {
                     fileLinks={fileLinks}
                     sortLinks={sortLinks}
                 />
+                {extraContent}
                 <FileMetricsTracker fileLinks={fileLinks} />
             </MainLayout>
         </div>
diff --git a/yarn.lock b/yarn.lock
index 823696c..b234d68 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2050,14 +2050,14 @@ domelementtype@^2.3.0:
   resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
   integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
 
-domhandler@^5.0.2, domhandler@^5.0.3:
+domhandler@5.0.3, domhandler@^5.0.2, domhandler@^5.0.3:
   version "5.0.3"
   resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
   integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
   dependencies:
     domelementtype "^2.3.0"
 
-domutils@^3.0.1:
+domutils@^3.0.1, domutils@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e"
   integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
@@ -2086,7 +2086,7 @@ emoji-regex@^9.2.2:
   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
   integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
 
-entities@^4.2.0, entities@^4.4.0:
+entities@^4.2.0, entities@^4.4.0, entities@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
   integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
@@ -2753,6 +2753,34 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
   dependencies:
     function-bind "^1.1.2"
 
+html-dom-parser@5.0.8:
+  version "5.0.8"
+  resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-5.0.8.tgz#540057d8eb7ff28c9fd45fa9eead374c34dae20c"
+  integrity sha512-vuWiX9EXgu8CJ5m9EP5c7bvBmNSuQVnrY8tl0z0ZX96Uth1IPlYH/8W8VZ/hBajFf18EN+j2pukbCNd01HEd1w==
+  dependencies:
+    domhandler "5.0.3"
+    htmlparser2 "9.1.0"
+
+html-react-parser@^5.1.10:
+  version "5.1.10"
+  resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-5.1.10.tgz#e65bf68df9b505756680d2cae842f7add3da5305"
+  integrity sha512-gV22PvLij4wdEdtrZbGVC7Zy2OVWnQ0bYhX63S196ZRSx4+K0TuutCreHSXr+saUia8KeKB+2TYziVfijpH4Tw==
+  dependencies:
+    domhandler "5.0.3"
+    html-dom-parser "5.0.8"
+    react-property "2.0.2"
+    style-to-js "1.1.12"
+
+htmlparser2@9.1.0:
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23"
+  integrity sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==
+  dependencies:
+    domelementtype "^2.3.0"
+    domhandler "^5.0.3"
+    domutils "^3.1.0"
+    entities "^4.5.0"
+
 htmlparser2@^8.0.1:
   version "8.0.2"
   resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21"
@@ -2799,6 +2827,11 @@ inherits@2:
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
 
+inline-style-parser@0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.3.tgz#e35c5fb45f3a83ed7849fe487336eb7efa25971c"
+  integrity sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==
+
 internal-slot@^1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802"
@@ -3610,6 +3643,11 @@ react-is@^16.13.1:
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
 
+react-property@2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.2.tgz#d5ac9e244cef564880a610bc8d868bd6f60fdda6"
+  integrity sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==
+
 react-refresh@^0.13.0:
   version "0.13.0"
   resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.13.0.tgz#cbd01a4482a177a5da8d44c9755ebb1f26d5a1c1"
@@ -3987,6 +4025,20 @@ strip-json-comments@^3.1.1:
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
   integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
 
+style-to-js@1.1.12:
+  version "1.1.12"
+  resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.12.tgz#112dd054231e71643514013a4475d4649bb2b581"
+  integrity sha512-tv+/FkgNYHI2fvCoBMsqPHh5xovwiw+C3X0Gfnss/Syau0Nr3IqGOJ9XiOYXoPnToHVbllKFf5qCNFJGwFg5mg==
+  dependencies:
+    style-to-object "1.0.6"
+
+style-to-object@1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.6.tgz#0c28aed8be1813d166c60d962719b2907c26547b"
+  integrity sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==
+  dependencies:
+    inline-style-parser "0.2.3"
+
 sucrase@^3.32.0:
   version "3.35.0"
   resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263"

From efe1137ac1beca25f43762aaf34e2d9b132f96cb Mon Sep 17 00:00:00 2001
From: Oleksii Nazarenko <alexeybread81@gmail.com>
Date: Thu, 20 Jun 2024 11:15:04 +0100
Subject: [PATCH 2/3] show extra content with tailwind prose styles

---
 package.json                       |  1 +
 src/pages/content/pages/Folder.tsx |  2 +-
 tailwind.config.cjs                |  1 +
 yarn.lock                          | 28 ++++++++++++++++++++++++++++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index ad2b762..d72052a 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
     },
     "devDependencies": {
         "@crxjs/vite-plugin": "^1.0.14",
+        "@tailwindcss/typography": "^0.5.13",
         "@tanstack/eslint-plugin-query": "^5.32.1",
         "@types/chrome": "^0.0.253",
         "@types/node": "^18.17.1",
diff --git a/src/pages/content/pages/Folder.tsx b/src/pages/content/pages/Folder.tsx
index 79bbd29..a5b1ec8 100644
--- a/src/pages/content/pages/Folder.tsx
+++ b/src/pages/content/pages/Folder.tsx
@@ -53,7 +53,7 @@ export default function Folder({ content }: FolderProps) {
                     fileLinks={fileLinks}
                     sortLinks={sortLinks}
                 />
-                {extraContent}
+                <div className="prose">{extraContent}</div>
                 <FileMetricsTracker fileLinks={fileLinks} />
             </MainLayout>
         </div>
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
index ea0a5c5..a667878 100644
--- a/tailwind.config.cjs
+++ b/tailwind.config.cjs
@@ -90,6 +90,7 @@ module.exports = {
     },
     plugins: [
         require("tailwindcss-animate"),
+        require("@tailwindcss/typography"),
         scopedPreflightStyles({
             isolationStrategy: isolateInsideOfContainer(
                 "._tailwind_preflight_reset"
diff --git a/yarn.lock b/yarn.lock
index b234d68..e0312df 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1137,6 +1137,16 @@
   dependencies:
     "@swc/counter" "^0.1.3"
 
+"@tailwindcss/typography@^0.5.13":
+  version "0.5.13"
+  resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.13.tgz#cd788a4fa4d0ca2506e242d512f377b22c1f7932"
+  integrity sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==
+  dependencies:
+    lodash.castarray "^4.4.0"
+    lodash.isplainobject "^4.0.6"
+    lodash.merge "^4.6.2"
+    postcss-selector-parser "6.0.10"
+
 "@tanstack/eslint-plugin-query@^5.32.1":
   version "5.35.6"
   resolved "https://registry.yarnpkg.com/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.35.6.tgz#805610e1fbeac5f814a6e952354b28ea3a65b64e"
@@ -3182,6 +3192,16 @@ locate-path@^6.0.0:
   dependencies:
     p-locate "^5.0.0"
 
+lodash.castarray@^4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
+  integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==
+
+lodash.isplainobject@^4.0.6:
+  version "4.0.6"
+  resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+  integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
+
 lodash.merge@^4.6.2:
   version "4.6.2"
   resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -3559,6 +3579,14 @@ postcss-nested@^6.0.1:
   dependencies:
     postcss-selector-parser "^6.0.11"
 
+postcss-selector-parser@6.0.10:
+  version "6.0.10"
+  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
+  integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
+  dependencies:
+    cssesc "^3.0.0"
+    util-deprecate "^1.0.2"
+
 postcss-selector-parser@^6.0.11:
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53"

From 4c4f36ea32710f6f9c6a99d0181c109e16600497 Mon Sep 17 00:00:00 2001
From: Oleksii Nazarenko <alexeybread81@gmail.com>
Date: Thu, 20 Jun 2024 11:20:34 +0100
Subject: [PATCH 3/3] fix styling

---
 src/pages/content/pages/Folder.tsx | 4 +++-
 tailwind.config.cjs                | 7 +++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/pages/content/pages/Folder.tsx b/src/pages/content/pages/Folder.tsx
index a5b1ec8..b45d5b0 100644
--- a/src/pages/content/pages/Folder.tsx
+++ b/src/pages/content/pages/Folder.tsx
@@ -53,7 +53,9 @@ export default function Folder({ content }: FolderProps) {
                     fileLinks={fileLinks}
                     sortLinks={sortLinks}
                 />
-                <div className="prose">{extraContent}</div>
+                {extraContent && !isLoading && (
+                    <div className="prose w-full">{extraContent}</div>
+                )}
                 <FileMetricsTracker fileLinks={fileLinks} />
             </MainLayout>
         </div>
diff --git a/tailwind.config.cjs b/tailwind.config.cjs
index a667878..7a28c44 100644
--- a/tailwind.config.cjs
+++ b/tailwind.config.cjs
@@ -26,6 +26,13 @@ module.exports = {
             },
         },
         extend: {
+            typography: {
+                DEFAULT: {
+                    css: {
+                        maxWidth: "100ch",
+                    },
+                },
+            },
             gridTemplateColumns: {
                 files: "max-content auto 4fr max-content max-content 3fr",
             },