diff --git a/package-lock.json b/package-lock.json index 8718301..3c95d9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,6 @@ "turndown": "^7.1.1" }, "devDependencies": { - "@tailwindcss/typography": "^0.5.2", "@types/node": "17.0.21", "@types/react": "17.0.40", "@types/react-dom": "^17.0.13", @@ -455,20 +454,6 @@ "integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==", "dev": true }, - "node_modules/@tailwindcss/typography": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz", - "integrity": "sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==", - "dev": true, - "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || insiders" - } - }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -2405,18 +2390,6 @@ "node": ">=4" } }, - "node_modules/lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3950,17 +3923,6 @@ "integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==", "dev": true }, - "@tailwindcss/typography": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz", - "integrity": "sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==", - "dev": true, - "requires": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2" - } - }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -5394,18 +5356,6 @@ "path-exists": "^3.0.0" } }, - "lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", diff --git a/package.json b/package.json index 20c6682..661ba85 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "turndown": "^7.1.1" }, "devDependencies": { - "@tailwindcss/typography": "^0.5.2", "@types/node": "17.0.21", "@types/react": "17.0.40", "@types/react-dom": "^17.0.13", diff --git a/src/components/Markdown/Markdawn.tsx b/src/components/Markdown/Markdawn.tsx index 38bf661..6414a1e 100644 --- a/src/components/Markdown/Markdawn.tsx +++ b/src/components/Markdown/Markdawn.tsx @@ -1,6 +1,9 @@ +import HorizontalLine from "components/HorizontalLine"; +import InsetBox from "components/InsetBox"; import { useAppLayout } from "contexts/AppLayoutContext"; import Markdown from "markdown-to-jsx"; -import SceneBreak from "./SceneBreak"; +import { slugify } from "queries/helpers"; +import React from "react"; type ScenBreakProps = { className?: string; @@ -9,15 +12,31 @@ type ScenBreakProps = { export default function Markdawn(props: ScenBreakProps): JSX.Element { const appLayout = useAppLayout(); + const text = preprocessMarkDawn(props.text); - if (props.text) { + if (text) { return ( { + return
; + }, + }, + SceneBreak: { + component: (props: { id: string }) => { + return ( +
+ * * * +
+ ); + }, }, player: { component: () => { @@ -28,12 +47,80 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { ); }, }, + Transcript: { + component: (props) => { + return ( +
+ {props.children} +
+ ); + }, + }, + Line: { + component: (props) => { + return ( + <> + + {props.name} + +

{props.children}

+ + ); + }, + }, + InsetBox: { + component: (props) => { + return {props.children}; + }, + }, + li: { + component: (props: { children: React.ReactNode }) => { + return ( +
  • 100 + ? "my-4" + : "" + } + > + {props.children} +
  • + ); + }, + }, + Highlight: { + component: (props: { children: React.ReactNode }) => { + return {props.children}; + }, + }, + footer: { + component: (props: { children: React.ReactNode }) => { + return ( + <> + +
    {props.children}
    + + ); + }, + }, }, }} > - {props.text} + {text}
    ); } return <>; } + +export function preprocessMarkDawn(text: string): string { + let scenebreakIndex = 0; + const result = text.split("\n").map((line) => { + if (line === "* * *" || line === "---") { + scenebreakIndex++; + return ``; + } + return line; + }); + return result.join("\n"); +} diff --git a/src/components/Markdown/SceneBreak.tsx b/src/components/Markdown/SceneBreak.tsx deleted file mode 100644 index a636120..0000000 --- a/src/components/Markdown/SceneBreak.tsx +++ /dev/null @@ -1,15 +0,0 @@ -type ScenBreakProps = { - className?: string; -}; - -export default function SceneBreak(props: ScenBreakProps): JSX.Element { - return ( -
    - * * * -
    - ); -} diff --git a/src/components/Markdown/TOC.tsx b/src/components/Markdown/TOC.tsx new file mode 100644 index 0000000..ff0c15f --- /dev/null +++ b/src/components/Markdown/TOC.tsx @@ -0,0 +1,153 @@ +import { slugify } from "queries/helpers"; +import { preprocessMarkDawn } from "./Markdawn"; + +type TOCProps = { + text: string; + title?: string; +}; + +export default function TOC(props: TOCProps): JSX.Element { + const toc = getTocFromMarkdawn(preprocessMarkDawn(props.text), props.title); + + return ( +
    +

    Table of content

    +
      +
    1. + + {{toc.title}} + +
    2. + {toc.children.map((h2, h2Index) => ( + <> +
    3. + {`${h2Index + 1}. `} + + {{h2.title}} + +
    4. +
        + {h2.children.map((h3, h3Index) => ( +
      1. + {`${h2Index + 1}.${ + h3Index + 1 + }. `} + + {{h3.title}} + +
      2. + ))} +
      + + ))} +
    +
    + ); +} + +export type TOC = { + title: string; + slug: string; + children: TOC[]; +}; + +export function getTocFromMarkdawn(text: string, title?: string): TOC { + if (!title) title = "Return to top"; + let toc: TOC = { title: title, slug: slugify(title) || "", children: [] }; + let h2 = -1; + let h3 = -1; + let h4 = -1; + let h5 = -1; + let scenebreak = 0; + let scenebreakIndex = 0; + text.split("\n").map((line) => { + if (line.startsWith("# ")) { + toc.slug = slugify(line); + } else if (line.startsWith("## ")) { + toc.children.push({ + title: line.slice("## ".length), + slug: slugify(line), + children: [], + }); + h2++; + h3 = -1; + h4 = -1; + h5 = -1; + scenebreak = 0; + } else if (line.startsWith("### ")) { + toc.children[h2].children.push({ + title: line.slice("### ".length), + slug: slugify(line), + children: [], + }); + h3++; + h4 = -1; + h5 = -1; + scenebreak = 0; + } else if (line.startsWith("#### ")) { + toc.children[h2].children[h3].children.push({ + title: line.slice("#### ".length), + slug: slugify(line), + children: [], + }); + h4++; + h5 = -1; + scenebreak = 0; + } else if (line.startsWith("##### ")) { + toc.children[h2].children[h3].children[h4].children.push({ + title: line.slice("##### ".length), + slug: slugify(line), + children: [], + }); + h5++; + scenebreak = 0; + } else if (line.startsWith("###### ")) { + toc.children[h2].children[h3].children[h4].children[h5].children.push({ + title: line.slice("###### ".length), + slug: slugify(line), + children: [], + }); + } else if (line.startsWith(`= 0) { + toc.children[h2].children[h3].children[h4].children[h5].children.push({ + title: `Scene break ${scenebreak}`, + slug: slugify(`scene-break-${scenebreakIndex}`), + children: [], + }); + } else if (h4 >= 0) { + toc.children[h2].children[h3].children[h4].children.push({ + title: `Scene break ${scenebreak}`, + slug: slugify(`scene-break-${scenebreakIndex}`), + children: [], + }); + } else if (h3 >= 0) { + toc.children[h2].children[h3].children.push({ + title: `Scene break ${scenebreak}`, + slug: slugify(`scene-break-${scenebreakIndex}`), + children: [], + }); + } else if (h2 >= 0) { + toc.children[h2].children.push({ + title: `Scene break ${scenebreak}`, + slug: slugify(`scene-break-${scenebreakIndex}`), + children: [], + }); + } else { + toc.children.push({ + title: `Scene break ${scenebreak}`, + slug: slugify(`scene-break-${scenebreakIndex}`), + children: [], + }); + } + } + }); + return toc; +} diff --git a/src/components/Panels/ContentPanel.tsx b/src/components/Panels/ContentPanel.tsx index 5b0dfa5..513f864 100644 --- a/src/components/Panels/ContentPanel.tsx +++ b/src/components/Panels/ContentPanel.tsx @@ -12,12 +12,15 @@ export enum ContentPanelWidthSizes { export default function ContentPanel(props: ContentPanelProps): JSX.Element { const width = props.width ? props.width : ContentPanelWidthSizes.default; const widthCSS = - width === ContentPanelWidthSizes.default ? "max-w-[45rem]" : "w-full"; - const prose = props.autoformat ? "prose text-justify" : ""; + width === ContentPanelWidthSizes.default ? "max-w-2xl" : "w-full"; return (
    -
    +
    {props.children}
    diff --git a/src/tailwind.css b/src/tailwind.css index e1aa100..a17a243 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -24,6 +24,10 @@ @apply bg-dark text-light; } + mark { + @apply bg-mid px-2 + } + /* SCROLLBARS STYLING */ * { @@ -42,45 +46,82 @@ @apply bg-dark rounded-full border-[3px] border-solid border-light; } - /* CHANGE PROSE DEFAULTS */ + /* CHANGE FORMATTED DEFAULTS */ - .prose, - .prose p, - .prose h1, - .prose h2, - .prose h3, - .prose h4, - .prose h5, - .prose h6, - .prose a, - .prose strong { - @apply text-black; + .formatted h1, + .formatted h2, + .formatted h3, + .formatted h4, + .formatted h5, + .formatted h6 { + @apply text-center; } - .prose a { - @apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark; + .formatted h1 { + @apply text-4xl my-16; } - .prose footer { + .formatted h1 + h2 { + @apply -mt-10; + } + + .formatted h2 { + @apply text-3xl my-12; + } + + .formatted h2 + h3 { + @apply -mt-8; + } + + .formatted h3 { + @apply text-2xl my-8; + } + + .formatted h3 + h4 { + @apply -mt-6; + } + + .formatted h4 { + @apply text-xl my-6; + } + + .formatted h5 { + @apply text-lg my-4; + } + + .formatted p, + .formatted strong { + @apply my-2 text-justify; + } + + .formatted footer { @apply border-t-[3px] border-dotted pt-6; } - .prose footer > div { + .formatted footer > div { @apply my-2 px-6 py-4 rounded-xl; } - .prose footer > div:target { + .formatted footer > div:target { @apply bg-mid shadow-inner-sm shadow-shade; } - .prose li::marker { + .formatted li::marker { @apply text-dark; } - .prose blockquote { + .formatted blockquote { @apply border-l-dark; } + .formatted ul { + @apply list-disc pl-4; + } + + .formatted ol { + @apply list-decimal pl-4; + } + /* INPUT */ input {