/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
import "@notesnook/editor/styles/styles.css";
import { Monograph } from "./types";
import {
Box,
Button,
Flex,
Image,
Input,
Link,
Text
} from "@theme-ui/components";
import { ClientOnly } from "remix-utils/client-only";
import { Editor } from "./editor.client";
import { formatDate } from "@notesnook/core";
import { slugify } from "../../utils/slugify";
import { useCallback, useEffect, useRef, useState } from "react";
import { NNCrypto } from "../../utils/nncrypto.client";
import { hashNavigate } from "../../utils/use-hash-location";
import { Icon } from "@notesnook/ui";
import {
mdiAlertCircleOutline,
mdiArrowUp,
mdiClose,
mdiListBoxOutline,
mdiLockOutline
} from "@mdi/js";
import { Footer } from "../footer";
import ReportDialog from "./report-modal";
type TableOfContent = {
title: string;
id: string;
level: number;
node: HTMLElement;
};
const headings = ["h1", "h2", "h3", "h4", "h5", "h6"];
const levelsMap: Record = {
H1: 0,
H2: 1,
H3: 2,
H4: 3,
H5: 4,
H6: 5
};
const selector = headings.map((h) => `.ProseMirror ${h}`).join(",");
function generateTableOfContents() {
const toc: TableOfContent[] = [];
const headings = document.querySelectorAll(selector);
let level = -1;
let currentHeading = 0;
for (const heading of headings) {
const isCalloutHeading = heading.closest(".callout");
if (isCalloutHeading) {
continue;
}
const text = heading.textContent || "";
const nodeName = heading.nodeName;
const headingLevel = levelsMap[nodeName];
let id = "heading-" + slugify(text);
const count = toc.filter((n) => n.id === id).length;
if (count > 0) id = `${id}-${count}`;
heading.setAttribute("id", id);
level =
currentHeading < headingLevel
? level + 1
: currentHeading > headingLevel
? headingLevel
: level;
currentHeading = headingLevel;
toc.push({
title: text,
id,
level,
node: heading
});
}
return toc;
}
export const MonographPage = ({
monograph,
encodedKey,
apiHost
}: {
monograph: Monograph;
encodedKey?: string;
apiHost: string;
}) => {
const [reportDialogVisible, setReportDialogVisible] = useState(false);
const [tableOfContents, setTableOfContents] = useState([]);
const [content, setContent] = useState(monograph.content);
const [showTableOfContents, setShowTableOfContents] = useState(false);
const editorContainer = useRef(null);
if (!content && monograph.encryptedContent)
return (
}>
{() => (
setContent(content)}
encodedKey={encodedKey}
/>
)}
);
return (
{monograph.title}
{formatDate(monograph.datePublished, {
type: "date-time",
dateFormat: "YYYY-MM-DD",
timeFormat: "24-hour"
})}
{monograph.encryptedContent ? (
End-to-end encrypted
) : (
)}