Add article + graph support
This commit is contained in:
@@ -11,10 +11,119 @@ const axios = require('axios'); // Add axios for reCAPTCHA verification
|
|||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
// Set options for marked to use highlight.js for syntax highlighting
|
// Set options for marked to use highlight.js for syntax highlighting
|
||||||
marked.setOptions({
|
// Configure custom renderer for code blocks to handle mermaid
|
||||||
|
marked.use({
|
||||||
|
renderer: {
|
||||||
|
code(code, language) {
|
||||||
|
// In marked v4+, code is an object with properties: text, lang, raw, etc.
|
||||||
|
// Extract the actual code text and language
|
||||||
|
let codeStr = '';
|
||||||
|
let lang = '';
|
||||||
|
|
||||||
|
if (typeof code === 'object' && code !== null) {
|
||||||
|
// Marked v4+ format: code is an object
|
||||||
|
codeStr = code.text || code.raw || String(code);
|
||||||
|
lang = code.lang || language || '';
|
||||||
|
} else if (typeof code === 'string') {
|
||||||
|
// Fallback for string format (older marked versions)
|
||||||
|
codeStr = code;
|
||||||
|
lang = language || '';
|
||||||
|
} else {
|
||||||
|
codeStr = String(code);
|
||||||
|
lang = language || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize language
|
||||||
|
if (lang && typeof lang === 'string') {
|
||||||
|
lang = lang.trim();
|
||||||
|
} else {
|
||||||
|
lang = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If language is mermaid, wrap in a div with class "mermaid"
|
||||||
|
if (lang === 'mermaid') {
|
||||||
|
// Ensure mermaid code is properly formatted (trim and preserve newlines)
|
||||||
|
const mermaidCode = codeStr.trim();
|
||||||
|
return `<div class="mermaid">${mermaidCode}</div>\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine valid language for highlighting - default to plaintext
|
||||||
|
let validLanguage = 'plaintext';
|
||||||
|
if (lang && lang.length > 0) {
|
||||||
|
try {
|
||||||
|
// Only check if language is valid if lang is a non-empty string
|
||||||
|
const langInfo = hljs.getLanguage(lang);
|
||||||
|
if (langInfo) {
|
||||||
|
validLanguage = lang;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// If getLanguage throws, use plaintext
|
||||||
|
validLanguage = 'plaintext';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure validLanguage is always a valid string before highlighting
|
||||||
|
if (!validLanguage || typeof validLanguage !== 'string') {
|
||||||
|
validLanguage = 'plaintext';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight the code
|
||||||
|
try {
|
||||||
|
// Use new highlight.js API (v11+)
|
||||||
|
const highlighted = hljs.highlight(codeStr, { language: validLanguage }).value;
|
||||||
|
return `<pre><code class="hljs language-${validLanguage}">${highlighted}</code></pre>\n`;
|
||||||
|
} catch (e) {
|
||||||
|
// Fallback if highlighting fails - escape HTML and return plain code
|
||||||
|
const escapedCode = codeStr.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||||
|
return `<pre><code class="hljs language-plaintext">${escapedCode}</code></pre>\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
highlight: function (code, language) {
|
highlight: function (code, language) {
|
||||||
const validLanguage = hljs.getLanguage(language) ? language : 'plaintext';
|
// In marked v4+, code might be an object with a text property
|
||||||
return hljs.highlight(validLanguage, code).value;
|
let codeStr = '';
|
||||||
|
if (typeof code === 'object' && code !== null) {
|
||||||
|
codeStr = code.text || code.raw || String(code);
|
||||||
|
} else if (typeof code === 'string') {
|
||||||
|
codeStr = code;
|
||||||
|
} else {
|
||||||
|
codeStr = String(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle undefined/null/empty language - ensure it's always a string
|
||||||
|
let lang = '';
|
||||||
|
if (language && typeof language === 'string') {
|
||||||
|
lang = language.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine valid language for highlighting - default to plaintext
|
||||||
|
let validLanguage = 'plaintext';
|
||||||
|
if (lang && lang.length > 0) {
|
||||||
|
try {
|
||||||
|
// Only check if language is valid if lang is a non-empty string
|
||||||
|
const langInfo = hljs.getLanguage(lang);
|
||||||
|
if (langInfo) {
|
||||||
|
validLanguage = lang;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// If getLanguage throws, use plaintext
|
||||||
|
validLanguage = 'plaintext';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure validLanguage is always a valid string before highlighting
|
||||||
|
if (!validLanguage || typeof validLanguage !== 'string') {
|
||||||
|
validLanguage = 'plaintext';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight the code
|
||||||
|
try {
|
||||||
|
// Use new highlight.js API (v11+)
|
||||||
|
return hljs.highlight(codeStr, { language: validLanguage }).value;
|
||||||
|
} catch (e) {
|
||||||
|
// Fallback if highlighting fails - return code as-is (will be escaped by marked)
|
||||||
|
return codeStr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -357,7 +466,7 @@ app.use((req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Server Listening
|
// Server Listening
|
||||||
const PORT = process.env.PORT || 8899;
|
const PORT = process.env.PORT || 8888;
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Server running on http://localhost:${PORT}`);
|
console.log(`Server running on http://localhost:${PORT}`);
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,21 @@
|
|||||||
|
|
||||||
<!-- Bootstrap JS Bundle -->
|
<!-- Bootstrap JS Bundle -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<!-- Mermaid.js Script -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
||||||
|
<script>
|
||||||
|
// Initialize Mermaid first (before DOMContentLoaded)
|
||||||
|
mermaid.initialize({
|
||||||
|
startOnLoad: false,
|
||||||
|
theme: 'default',
|
||||||
|
securityLevel: 'loose'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Render Mermaid after DOM is ready
|
||||||
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
mermaid.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,21 @@
|
|||||||
|
|
||||||
<!-- Bootstrap JS Bundle -->
|
<!-- Bootstrap JS Bundle -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<!-- Mermaid.js Script -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
||||||
|
<script>
|
||||||
|
// Initialize Mermaid first (before DOMContentLoaded)
|
||||||
|
mermaid.initialize({
|
||||||
|
startOnLoad: false,
|
||||||
|
theme: 'default',
|
||||||
|
securityLevel: 'loose'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Render Mermaid after DOM is ready
|
||||||
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
mermaid.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -71,12 +71,25 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- Highlight.js Script -->
|
<!-- Highlight.js Script -->
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
||||||
|
<!-- Mermaid.js Script -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// Initialize Highlight.js
|
// Initialize Mermaid first (before DOMContentLoaded)
|
||||||
|
mermaid.initialize({
|
||||||
|
startOnLoad: false,
|
||||||
|
theme: 'default',
|
||||||
|
securityLevel: 'loose'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize Highlight.js and render Mermaid after DOM is ready
|
||||||
document.addEventListener('DOMContentLoaded', (event) => {
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
// Initialize Highlight.js
|
||||||
document.querySelectorAll('pre code').forEach((block) => {
|
document.querySelectorAll('pre code').forEach((block) => {
|
||||||
hljs.highlightElement(block);
|
hljs.highlightElement(block);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Manually run mermaid to render all diagrams
|
||||||
|
mermaid.run();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user