Files
natreex 64ed90d993 Remove unused components and models for improved maintainability
- Deleted redundant components (`AddActionButton`, `AlertBox`, `AlertStack`, `BackButton`, `CancelButton`, and `CollapsableArea`) and related files.
- Removed unused models (`Book`, `BookSerie`, `BookTables`, `Character`, and `Chapter`) to reduce codebase clutter.
- Updated project structure and references to reflect these removals.
2026-03-22 22:37:31 -04:00

141 lines
4.5 KiB
TypeScript

import {TiptapAttrValue, TiptapLinkAttrs, TiptapNode} from "@/lib/types/chapter";
function isTiptapLinkAttrs(value: TiptapAttrValue): value is TiptapLinkAttrs {
return typeof value === 'object' && value !== null && 'href' in value;
}
export function getPageCount(text: string): number {
const charactersPerLine: number = 90;
const linesPerPage: number = 40;
const lines: string[] = text.split('\n');
let totalLines: number = 0;
lines.forEach((line: string) => {
const lineLength: number = line.length;
const estimatedLines: number = Math.ceil(lineLength / charactersPerLine);
totalLines += estimatedLines;
});
return Math.ceil(totalLines / linesPerPage);
}
export function convertTiptapToHTML(node: TiptapNode): string {
let html: string = '';
switch (node.type) {
case 'doc':
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
break;
case 'paragraph':
html += '<p>';
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
html += '</p>';
break;
case 'text':
let textContent: string = node.text || '';
if (node.attrs) {
if (node.attrs.bold) {
textContent = `<strong>${textContent}</strong>`;
}
if (node.attrs.italic) {
textContent = `<em>${textContent}</em>`;
}
if (node.attrs.underline) {
textContent = `<u>${textContent}</u>`;
}
if (node.attrs.strike) {
textContent = `<s>${textContent}</s>`;
}
if (node.attrs.link && isTiptapLinkAttrs(node.attrs.link)) {
textContent = `<a href="${node.attrs.link.href}">${textContent}</a>`;
}
}
html += textContent;
break;
case 'heading':
const level: number = typeof node.attrs?.level === 'number' ? node.attrs.level : 1;
html += `<h${level}>`;
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
html += `</h${level}>`;
break;
case 'bulletList':
html += '<ul>';
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
html += '</ul>';
break;
case 'orderedList':
html += '<ol>';
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
html += '</ol>';
break;
case 'listItem':
html += '<li>';
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
html += '</li>';
break;
case 'blockquote':
html += '<blockquote>';
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
html += '</blockquote>';
break;
case 'codeBlock':
html += '<pre><code>';
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
html += '</code></pre>';
break;
default:
if (node.content) {
node.content.forEach((childNode: TiptapNode) => {
html += convertTiptapToHTML(childNode);
});
}
break;
}
return html;
}