- Implement `Content` model for converting Tiptap raw data into HTML and plain text. - Add `Model` for storing and managing AI model configurations with pricing and metadata. - Introduce `Story` model to handle verbal styles and linguistic properties for diverse narrative structures. - Update `book.repository.ts` to refine `updateBookBasicInformation` and `insertNewPlotPoint` methods, removing unused parameters and optimizing queries.
161 lines
5.3 KiB
TypeScript
Executable File
161 lines
5.3 KiB
TypeScript
Executable File
export interface TiptapNode {
|
|
type: string;
|
|
content?: TiptapNode[];
|
|
text?: string;
|
|
attrs?: {
|
|
[key: string]: any;
|
|
};
|
|
}
|
|
|
|
export default class Content {
|
|
static convertTipTapRawToText(content: string): string {
|
|
const text: string = this.convertTiptapToHTMLFromString(content);
|
|
return this.htmlToText(text);
|
|
}
|
|
|
|
static htmlToText(html: string) {
|
|
return html
|
|
.replace(/<br\s*\/?>/gi, '\n') // Gérer les <br> d'abord
|
|
.replace(/<\/?(p|h[1-6]|div)(\s+[^>]*)?>/gi, '\n') // Balises bloc
|
|
.replace(/<\/?[^>]+(>|$)/g, '') // Supprimer toutes les balises restantes
|
|
.replace(/(\n\s*){2,}/g, '\n\n') // Préserver les paragraphes
|
|
.replace(/^\s+|\s+$|(?<=\s)\s+/g, '') // Nettoyer les espaces
|
|
.trim();
|
|
}
|
|
|
|
static convertTiptapToHTMLFromString(jsonString: string): string {
|
|
// Convert the JSON string to an object
|
|
let jsonObject: TiptapNode;
|
|
try {
|
|
jsonObject = JSON.parse(jsonString);
|
|
} catch (error) {
|
|
console.error('Invalid JSON string:', error);
|
|
return '';
|
|
}
|
|
|
|
// Use the existing conversion function
|
|
return this.convertTiptapToHTML(jsonObject);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|