Major Features:
- Enhanced Mode v2: Smart Adaptive section selection strategy
* AI automatically selects ONE optimal section per iteration
* Intelligent selection based on quality assessment and strategic importance
* Section tracking to avoid duplicate modifications
* Fixed header level preservation (## stays ##, ### stays ###)
* Updated document code block format (document)
- Mermaid Auto-Fix System
* New POST /api/ai/fix-mermaid endpoint for automatic diagram correction
* Automatic error detection in preview and presentation modes
* Inter-window communication for seamless editor updates
* AI-powered syntax error resolution
- Comprehensive Logging System
* Centralized logger utility (utils/logger.js)
* API request/response middleware logging
* AI operations: rephrase, check-inconsistencies, check-duplications, give-advice, liberty-mode, fix-mermaid
* Storage operations: create, read, update, delete journals
* Export operations: PDF and Web ZIP generation
* Structured logging with timestamps, levels, categories, and metadata
Improvements:
- Table of Contents: Clean display with markdown formatting stripped from titles
- Section badges: Fixed visibility with hardcoded blue background (#2563eb)
- Internationalization: Complete English translation (lang, UI text, placeholders, comments)
- Code cleanup: Removed all emojis from codebase
Technical Changes:
- routes/ai.js: Enhanced mode implementation, Mermaid fix endpoint, comprehensive logging
- routes/api.js: Storage operation logging
- routes/export.js: Export operation logging
- routes/index.js: Presentation mode Mermaid auto-fix
- assets/js/app.js: TOC markdown stripping, Mermaid error handling, message listeners
- assets/css/style.css: Dark mode comment, English placeholders, header icon
- views/page.js: English lang attribute, favicon, scroll-to-top button
- views/header.js: Theme toggle icon
- utils/logger.js: New centralized logging system
- app.js: API request/response logging middleware
253 lines
8.5 KiB
JavaScript
253 lines
8.5 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { getPage } = require('../views/page');
|
|
|
|
// Main route
|
|
router.get('/', (req, res) => {
|
|
res.send(getPage());
|
|
});
|
|
|
|
// Present route - Display document in presentation mode
|
|
router.post('/present', (req, res) => {
|
|
const { content } = req.body;
|
|
|
|
res.send(`
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Presentation - Design Journal</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="stylesheet" href="/assets/css/style.css">
|
|
<link rel="stylesheet" href="/assets/css/github-preview.css">
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
background: var(--bg-color);
|
|
}
|
|
#presentation-container {
|
|
max-width: 900px;
|
|
margin: 0 auto;
|
|
padding: 3rem 2rem;
|
|
min-height: 100vh;
|
|
}
|
|
.presentation-header {
|
|
text-align: center;
|
|
padding: 2rem 0;
|
|
border-bottom: 2px solid var(--border-color);
|
|
margin-bottom: 3rem;
|
|
}
|
|
.presentation-header h1 {
|
|
margin: 0 0 0.5rem 0;
|
|
color: var(--primary-color);
|
|
}
|
|
.presentation-header .date {
|
|
color: var(--text-light);
|
|
font-size: 0.9rem;
|
|
}
|
|
.presentation-content {
|
|
line-height: 1.8;
|
|
}
|
|
.print-button {
|
|
position: fixed;
|
|
top: 1rem;
|
|
right: 1rem;
|
|
padding: 0.5rem 1rem;
|
|
background: var(--primary-color);
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 0.9rem;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
|
transition: all 0.3s ease;
|
|
}
|
|
.print-button:hover {
|
|
background: var(--primary-hover);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
|
}
|
|
@media print {
|
|
.print-button {
|
|
display: none;
|
|
}
|
|
#presentation-container {
|
|
padding: 1rem;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<button class="print-button" onclick="window.print()">Print / Save PDF</button>
|
|
|
|
<div id="presentation-container">
|
|
<div class="presentation-header">
|
|
<h1>Design Journal</h1>
|
|
<div class="date">${new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}</div>
|
|
</div>
|
|
<div class="presentation-content markdown-body" id="content"></div>
|
|
</div>
|
|
|
|
<script>
|
|
// Render markdown content first
|
|
const content = ${JSON.stringify(content)};
|
|
const contentDiv = document.getElementById('content');
|
|
contentDiv.innerHTML = marked.parse(content);
|
|
|
|
// Initialize Mermaid
|
|
mermaid.initialize({
|
|
startOnLoad: false,
|
|
theme: document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'default',
|
|
securityLevel: 'loose'
|
|
});
|
|
|
|
// Process Mermaid diagrams
|
|
setTimeout(() => {
|
|
// Find all code blocks with 'mermaid' language
|
|
const mermaidBlocks = contentDiv.querySelectorAll('code.language-mermaid, pre code.language-mermaid');
|
|
|
|
mermaidBlocks.forEach((block, index) => {
|
|
try {
|
|
const mermaidCode = block.textContent;
|
|
const uniqueId = 'mermaid-' + Date.now() + '-' + index;
|
|
|
|
// Create div with unique ID for Mermaid
|
|
const mermaidDiv = document.createElement('div');
|
|
mermaidDiv.id = uniqueId;
|
|
mermaidDiv.className = 'mermaid';
|
|
mermaidDiv.textContent = mermaidCode;
|
|
|
|
// Replace code block with Mermaid div
|
|
const pre = block.closest('pre') || block;
|
|
pre.parentNode.replaceChild(mermaidDiv, pre);
|
|
|
|
// Render diagram
|
|
mermaid.render(uniqueId + '-svg', mermaidCode).then(function(result) {
|
|
mermaidDiv.innerHTML = result.svg;
|
|
}).catch(async function(err) {
|
|
console.warn('Mermaid rendering error:', err);
|
|
|
|
// Show error message with auto-fix option
|
|
mermaidDiv.innerHTML = '<div style="padding: 1.5rem; background: #fff3cd; border: 2px solid #ffc107; border-radius: 8px; margin: 1rem 0;">' +
|
|
'<h4 style="margin-top: 0; color: #856404;">[!] Mermaid Diagram Error</h4>' +
|
|
'<p style="margin: 0.5rem 0;"><strong>Error:</strong> ' + err.message + '</p>' +
|
|
'<p style="margin: 1rem 0 0.5rem 0; color: #666;">Attempting to fix automatically...</p>' +
|
|
'<div id="fix-status-' + uniqueId + '" style="margin-top: 0.5rem;"></div>' +
|
|
'</div>';
|
|
|
|
const statusDiv = document.getElementById('fix-status-' + uniqueId);
|
|
|
|
try {
|
|
// Call AI API to fix Mermaid diagram
|
|
const response = await fetch('/api/ai/fix-mermaid', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
mermaidCode: mermaidCode,
|
|
error: err.message
|
|
})
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success && result.data.fixedCode) {
|
|
statusDiv.innerHTML = '<p style="color: #28a745; font-weight: 500;">[OK] Diagram fixed! Please close this window and reopen presentation mode from the editor to see the corrected diagram.</p>';
|
|
|
|
// Try to update parent window if available
|
|
if (window.opener && !window.opener.closed) {
|
|
try {
|
|
// Send message to parent window to update content
|
|
window.opener.postMessage({
|
|
type: 'mermaid-fixed',
|
|
originalCode: mermaidCode,
|
|
fixedCode: result.data.fixedCode
|
|
}, '*');
|
|
|
|
statusDiv.innerHTML += '<p style="color: #28a745; margin-top: 0.5rem;">Document updated in editor. You can now close this window and reopen presentation mode.</p>';
|
|
} catch (e) {
|
|
console.warn('Could not update parent window:', e);
|
|
}
|
|
}
|
|
} else {
|
|
statusDiv.innerHTML = '<p style="color: #dc3545;">[ERROR] Automatic fix failed. Please check the syntax in the editor.</p>';
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fixing Mermaid:', error);
|
|
statusDiv.innerHTML = '<p style="color: #dc3545;">[ERROR] Could not fix diagram automatically. Please check your syntax in the editor.</p>';
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.warn('Mermaid processing error:', error);
|
|
}
|
|
});
|
|
}, 200);
|
|
</script>
|
|
</body>
|
|
</html>
|
|
`);
|
|
});
|
|
|
|
// About route
|
|
router.get('/about', (req, res) => {
|
|
const { getHeader } = require('../views/header');
|
|
const { getFooter } = require('../views/footer');
|
|
|
|
res.send(`
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>About - Design Journal</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<link rel="stylesheet" href="/assets/css/style.css">
|
|
</head>
|
|
<body>
|
|
${getHeader()}
|
|
|
|
<main style="display: block; max-width: 800px; margin: 0 auto; padding: 2rem;">
|
|
<section>
|
|
<h2>About the Application</h2>
|
|
<div style="padding: 2rem;">
|
|
<p>
|
|
This application helps teams maintain structured and collaborative tracking of their design projects. It allows archiving key steps, ensuring traceability of decisions, and simplifying coordination.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section style="margin-top: 2rem;">
|
|
<h2>History</h2>
|
|
<div style="padding: 2rem;">
|
|
<p>
|
|
This project was born from the need to centralize and organize design notes during the development of technical projects. It offers an intuitive environment for documenting architectural decisions and tracking project evolution.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section style="margin-top: 2rem;">
|
|
<h2>Open Source</h2>
|
|
<div style="padding: 2rem;">
|
|
<p>
|
|
This project is open source and available under the MIT License. Contributions are welcome!
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<div style="text-align: center; margin: 3rem 0 2rem 0;">
|
|
<a href="/" style="background: var(--secondary-color); color: white; padding: 0.8rem 2rem; text-decoration: none; border-radius: 25px; display: inline-block; transition: all 0.3s ease;">
|
|
Back to Application
|
|
</a>
|
|
</div>
|
|
</main>
|
|
|
|
${getFooter()}
|
|
|
|
<script src="/assets/js/theme.js"></script>
|
|
</body>
|
|
</html>
|
|
`);
|
|
});
|
|
|
|
module.exports = router; |