Files
ERitors-Scribe-Desktop/lib/models/Chapter.ts
natreex ceaecb19fc Remove ExportBook component and integrate new export workflows
- Deleted `ExportBook` component and its usage in `BookCard.tsx`.
- Integrated improved book export workflows in `BookSettingOption` for better user experience.
- Updated database models and repositories to support export options with chapter/version selection.
- Added localization support for export-related messages and tooltips.
- Upgraded dependencies to include libraries required for export formats (e.g., DOCX, PDF, EPUB).
- Bumped app version to 0.4.1.
2026-03-05 16:31:56 -05:00

212 lines
6.2 KiB
TypeScript

import {SelectBoxProps} from "@/shared/interface";
export interface ActChapter {
chapterInfoId: string;
chapterId: string;
title: string;
chapterOrder: number;
actId: number;
incidentId?: string;
plotPointId?: string;
summary: string;
goal: string;
}
export interface ChapterListProps {
chapterId: string;
title: string;
summary?: string;
chapterOrder?: number;
goal?: string;
}
export interface ChapterProps {
chapterId: string;
chapterOrder: number;
title: string;
chapterContent: ChapterContent;
}
export interface ChapterContent {
version: number;
content: string;
wordsCount: number;
}
export interface ChapterVersion {
value: number;
label: 'Invite' | 'Brouillon' | 'Perfectionnement' | 'Révision' | 'Finale';
}
export type TiptapNode = {
type: string;
content?: TiptapNode[];
text?: string;
attrs?: {
[key: string]: any;
};
};
export type ExportFormat = 'epub' | 'pdf' | 'docx';
export interface ChapterExportInfo {
chapterId: string;
title: string;
chapterOrder: number;
availableVersions: number[];
}
export interface ChapterExportSelection {
chapterId: string;
version: number;
selected: boolean;
}
export const chapterVersions: SelectBoxProps[] = [
{value: '1', label: 'chapterVersions.prompt'},
{value: '2', label: 'chapterVersions.draft'},
{value: '3', label: 'chapterVersions.refine'},
{value: '4', label: 'chapterVersions.review'},
{value: '5', label: 'chapterVersions.final'},
];
export default class Chapter {
public static getPageCount(text: string): number {
const charactersPerLine = 90;
const linesPerPage = 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;
});
// Calcul du nombre de pages
return Math.ceil(totalLines / linesPerPage);
}
static convertTiptapToHTML(node: TiptapNode): string {
let html = '';
switch (node.type) {
case 'doc':
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
break;
case 'paragraph':
html += '<p>';
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
html += '</p>';
break;
case 'text':
let textContent = node.text || '';
// Apply attributes like bold, italic, etc.
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) {
textContent = `<a href="${node.attrs.link.href}">${textContent}</a>`;
}
}
html += textContent;
break;
case 'heading':
const level = node.attrs?.level || 1;
html += `<h${level}>`;
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
html += `</h${level}>`;
break;
case 'bulletList':
html += '<ul>';
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
html += '</ul>';
break;
case 'orderedList':
html += '<ol>';
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
html += '</ol>';
break;
case 'listItem':
html += '<li>';
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
html += '</li>';
break;
case 'blockquote':
html += '<blockquote>';
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
html += '</blockquote>';
break;
case 'codeBlock':
html += '<pre><code>';
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
html += '</code></pre>';
break;
default:
console.warn(`Unhandled node type: ${node.type}`);
if (node.content) {
node.content.forEach(childNode => {
html += this.convertTiptapToHTML(childNode);
});
}
break;
}
return html;
}
}