maj export project
This commit is contained in:
@@ -9,6 +9,11 @@ const nextConfig: NextConfig = {
|
|||||||
ignoreBuildErrors: true,
|
ignoreBuildErrors: true,
|
||||||
},
|
},
|
||||||
output: "standalone",
|
output: "standalone",
|
||||||
|
experimental: {
|
||||||
|
turbopack: {
|
||||||
|
root: './',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
|||||||
const [pageSize, setPageSize] = useState<PageSize>('A4');
|
const [pageSize, setPageSize] = useState<PageSize>('A4');
|
||||||
const [includeCover, setIncludeCover] = useState(true);
|
const [includeCover, setIncludeCover] = useState(true);
|
||||||
const [includeTOC, setIncludeTOC] = useState(true);
|
const [includeTOC, setIncludeTOC] = useState(true);
|
||||||
|
const [includeBible, setIncludeBible] = useState(true);
|
||||||
|
const [includeOutils, setIncludeOutils] = useState(true);
|
||||||
const { t } = useLanguage();
|
const { t } = useLanguage();
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
@@ -41,7 +43,14 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
|||||||
a { color: #000; text-decoration: none; }
|
a { color: #000; text-decoration: none; }
|
||||||
ul { list-style-type: none; padding: 0; }
|
ul { list-style-type: none; padding: 0; }
|
||||||
li { margin-bottom: 0.5em; }
|
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>
|
</style>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true, theme: 'neutral' });
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
`;
|
`;
|
||||||
@@ -72,6 +81,80 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
|||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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>`;
|
html += `</body></html>`;
|
||||||
return html;
|
return html;
|
||||||
};
|
};
|
||||||
@@ -116,6 +199,58 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
|||||||
const text = c.content.replace(/<[^>]+>/g, '\n');
|
const text = c.content.replace(/<[^>]+>/g, '\n');
|
||||||
md += `## ${c.title}\n\n${text}\n\n---\n\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' });
|
const blob = new Blob([md], { type: 'text/markdown' });
|
||||||
downloadBlob(blob, `${filename}.md`);
|
downloadBlob(blob, `${filename}.md`);
|
||||||
}
|
}
|
||||||
@@ -227,6 +362,28 @@ const ExportModal: React.FC<ExportModalProps> = ({ isOpen, onClose, project, onP
|
|||||||
/>
|
/>
|
||||||
</div>
|
</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' && (
|
{format === 'epub' && (
|
||||||
<p className="text-xs text-amber-600 bg-amber-50 p-2 rounded mt-2">
|
<p className="text-xs text-amber-600 bg-amber-50 p-2 rounded mt-2">
|
||||||
{t('export.epub_note')}
|
{t('export.epub_note')}
|
||||||
|
|||||||
Reference in New Issue
Block a user