'use client';
import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
import Reveal from 'reveal.js';
import 'reveal.js/dist/reveal.css';
import { marked } from 'marked';
const parseThemeFromContent = (content) => {
if (!content || !content.startsWith('---')) return null;
const frontmatterEnd = content.indexOf('---', 3);
if (frontmatterEnd === -1) return null;
const frontmatter = content.substring(3, frontmatterEnd);
const themeMatch = frontmatter.match(/theme:\s*(\w+)/);
return themeMatch ? themeMatch[1] : null;
};
const loadTheme = async (themeName) => {
if (!themeName) return;
try {
await import(`./themes/${themeName}.css`);
} catch (error) {
try {
await import(`reveal.js/dist/theme/${themeName}.css`);
} catch (error2) {
await import('reveal.js/dist/theme/black.css');
}
}
};
const REVEAL_CONFIG = {
hash: true,
transition: 'slide',
transitionSpeed: 'default',
backgroundTransition: 'fade',
controls: true,
progress: true,
center: true,
touch: true,
loop: false,
rtl: false,
navigationMode: 'default',
shuffle: false,
fragments: true,
fragmentInURL: false,
embedded: false,
help: true,
showNotes: true,
autoPlayMedia: null,
preloadIframes: null,
autoSlide: 0,
autoSlideStoppable: true,
autoSlideMethod: Reveal.navigateNext,
defaultTiming: null,
mouseWheel: false,
hideInactiveCursor: true,
hideCursorTime: 5000,
previewLinks: false,
postMessage: true,
postMessageEvents: false,
focusBodyOnPageVisibilityChange: true,
viewDistance: 3,
mobileViewDistance: 2,
display: 'block',
hideAnchorsOnUrl: false,
plugins: []
};
marked.setOptions({
breaks: true,
gfm: true,
headerIds: false,
mangle: false,
});
export default function Presentation({ data }) {
const deckRef = useRef(null);
const revealRef = useRef(null);
const [mounted, setMounted] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setMounted(true);
}, []);
const parseMarkdownToSlides = useCallback((data) => {
if (!data) {
return ` 暂无内容 暂无内容 内容解析失败,请检查数据格式演示文稿
${data.title || '演示文稿'}
解析错误
PPT加载失败
{error}