maj export project
This commit is contained in:
@@ -9,6 +9,11 @@ const nextConfig: NextConfig = {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
output: "standalone",
|
||||
experimental: {
|
||||
turbopack: {
|
||||
root: './',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
@@ -20,6 +20,8 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
||||
const [pageSize, setPageSize] = useState<PageSize>('A4');
|
||||
const [includeCover, setIncludeCover] = useState(true);
|
||||
const [includeTOC, setIncludeTOC] = useState(true);
|
||||
const [includeBible, setIncludeBible] = useState(true);
|
||||
const [includeOutils, setIncludeOutils] = useState(true);
|
||||
const { t } = useLanguage();
|
||||
|
||||
if (!isOpen) return null;
|
||||
@@ -41,7 +43,14 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
||||
a { color: #000; text-decoration: none; }
|
||||
ul { list-style-type: none; padding: 0; }
|
||||
li { margin-bottom: 0.5em; }
|
||||
.mermaid-container { margin: 2em 0; text-align: center; }
|
||||
.node-info { margin-bottom: 1.5em; padding-left: 1em; border-left: 3px solid #e2e8f0; }
|
||||
.node-type { font-size: 0.8em; font-weight: bold; text-transform: uppercase; color: #64748b; }
|
||||
</style>
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
||||
<script>
|
||||
mermaid.initialize({ startOnLoad: true, theme: 'neutral' });
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
`;
|
||||
@@ -71,6 +80,80 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
if (includeBible && project.entities && project.entities.length > 0) {
|
||||
html += `
|
||||
<div class="chapter">
|
||||
<h1>La Bible de l'Univers</h1>
|
||||
`;
|
||||
|
||||
const types = ['Personnage', 'Lieu', 'Objet', 'Note'];
|
||||
types.forEach(type => {
|
||||
const entitiesOfType = project.entities.filter(e => e.type === type);
|
||||
if (entitiesOfType.length > 0) {
|
||||
html += `<h3>${type}s</h3><ul>`;
|
||||
entitiesOfType.forEach(e => {
|
||||
html += `<li><strong>${e.name}</strong>: ${e.description}</li>`;
|
||||
});
|
||||
html += `</ul>`;
|
||||
}
|
||||
});
|
||||
html += `</div>`;
|
||||
}
|
||||
|
||||
if (includeOutils) {
|
||||
if (project.workflow && project.workflow.nodes && project.workflow.nodes.length > 0) {
|
||||
// Generate Mermaid syntax
|
||||
let mermaidText = "graph TD\n";
|
||||
project.workflow.nodes.forEach(node => {
|
||||
const safeTitle = node.title.replace(/[()]/g, '');
|
||||
mermaidText += ` ${node.id}["${safeTitle}"]\n`;
|
||||
});
|
||||
if (project.workflow.connections) {
|
||||
project.workflow.connections.forEach(conn => {
|
||||
mermaidText += ` ${conn.source} --> ${conn.target}\n`;
|
||||
});
|
||||
}
|
||||
|
||||
html += `
|
||||
<div class="chapter">
|
||||
<h1>Structure du Récit</h1>
|
||||
<div class="mermaid-container">
|
||||
<pre class="mermaid">
|
||||
${mermaidText}
|
||||
</pre>
|
||||
</div>
|
||||
<h2>Détails des Étapes</h2>
|
||||
`;
|
||||
project.workflow.nodes.forEach(node => {
|
||||
html += `
|
||||
<div class="node-info">
|
||||
<div class="node-type">${node.type || 'Étape'}</div>
|
||||
<strong>${node.title}</strong>
|
||||
<p>${node.description}</p>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
html += `</div>`;
|
||||
}
|
||||
|
||||
if (project.ideas && project.ideas.length > 0) {
|
||||
html += `
|
||||
<div class="chapter">
|
||||
<h1>Idées & Notes</h1>
|
||||
`;
|
||||
project.ideas.forEach(idea => {
|
||||
html += `
|
||||
<div class="node-info">
|
||||
<div class="node-type">${idea.category} • ${idea.status}</div>
|
||||
<strong>${idea.title}</strong>
|
||||
<p>${idea.description}</p>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
html += `</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
html += `</body></html>`;
|
||||
return html;
|
||||
@@ -116,6 +199,58 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
||||
const text = c.content.replace(/<[^>]+>/g, '\n');
|
||||
md += `## ${c.title}\n\n${text}\n\n---\n\n`;
|
||||
});
|
||||
|
||||
if (includeBible && project.entities && project.entities.length > 0) {
|
||||
md += `# La Bible de l'Univers\n\n`;
|
||||
const types = ['Personnage', 'Lieu', 'Objet', 'Note'];
|
||||
types.forEach(type => {
|
||||
const entitiesOfType = project.entities.filter(e => e.type === type);
|
||||
if (entitiesOfType.length > 0) {
|
||||
md += `## ${type}s\n\n`;
|
||||
entitiesOfType.forEach(e => {
|
||||
md += `### ${e.name}\n${e.description}\n\n`;
|
||||
});
|
||||
}
|
||||
});
|
||||
md += `---\n\n`;
|
||||
}
|
||||
|
||||
if (includeOutils) {
|
||||
if (project.workflow && project.workflow.nodes && project.workflow.nodes.length > 0) {
|
||||
md += `# Structure du Récit\n\n`;
|
||||
|
||||
// Mermaid block
|
||||
md += `\`\`\`mermaid\ngraph TD\n`;
|
||||
project.workflow.nodes.forEach(node => {
|
||||
const safeTitle = node.title.replace(/[()]/g, '');
|
||||
md += ` ${node.id}["${safeTitle}"]\n`;
|
||||
});
|
||||
if (project.workflow.connections) {
|
||||
project.workflow.connections.forEach(conn => {
|
||||
md += ` ${conn.source} --> ${conn.target}\n`;
|
||||
});
|
||||
}
|
||||
md += `\`\`\`\n\n`;
|
||||
|
||||
md += `## Détails des Étapes\n\n`;
|
||||
project.workflow.nodes.forEach(node => {
|
||||
md += `### ${node.title}\n`;
|
||||
md += `**Type**: ${node.type || 'Étape'}\n\n`;
|
||||
md += `${node.description}\n\n`;
|
||||
});
|
||||
md += `\n---\n\n`;
|
||||
}
|
||||
|
||||
if (project.ideas && project.ideas.length > 0) {
|
||||
md += `# Idées & Notes\n\n`;
|
||||
project.ideas.forEach(idea => {
|
||||
md += `## ${idea.title}\n`;
|
||||
md += `**Catégorie**: ${idea.category} | **Statut**: ${idea.status}\n\n`;
|
||||
md += `${idea.description}\n\n`;
|
||||
});
|
||||
md += `\n---\n\n`;
|
||||
}
|
||||
}
|
||||
const blob = new Blob([md], { type: 'text/markdown' });
|
||||
downloadBlob(blob, `${filename}.md`);
|
||||
}
|
||||
@@ -227,6 +362,28 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between border-t border-slate-200 pt-4 mt-4">
|
||||
<label className="text-slate-700 font-medium cursor-pointer" htmlFor="bible">Inclure la Bible (Personnages, Lieux...)</label>
|
||||
<input
|
||||
id="bible"
|
||||
type="checkbox"
|
||||
checked={includeBible}
|
||||
onChange={(e) => setIncludeBible(e.target.checked)}
|
||||
className="w-5 h-5 rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<label className="text-slate-700 font-medium cursor-pointer" htmlFor="outils">Inclure les Outils (Nodes, Idées)</label>
|
||||
<input
|
||||
id="outils"
|
||||
type="checkbox"
|
||||
checked={includeOutils}
|
||||
onChange={(e) => setIncludeOutils(e.target.checked)}
|
||||
className="w-5 h-5 rounded border-slate-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{format === 'epub' && (
|
||||
<p className="text-xs text-amber-600 bg-amber-50 p-2 rounded mt-2">
|
||||
{t('export.epub_note')}
|
||||
|
||||
Reference in New Issue
Block a user