feat: markdown tables

This commit is contained in:
Alejandro Gómez
2025-12-10 16:29:48 +01:00
parent b1be04cb39
commit 88e34441b8
3 changed files with 24 additions and 18 deletions

View File

@@ -3,6 +3,7 @@ import type { Components } from "react-markdown";
import { useMemo } from "react";
import { useGrimoire } from "@/core/state";
import { MediaEmbed } from "@/components/nostr/MediaEmbed";
import remarkGfm from "remark-gfm";
interface MarkdownProps {
content: string;
@@ -79,15 +80,18 @@ export function Markdown({ content, className = "" }: MarkdownProps) {
console.log("[Markdown Link]", { href, children });
// Check if it's a relative NIP link (e.g., "./01.md" or "01.md" or "30.md")
if (href && (href.endsWith(".md") || href.includes(".md#"))) {
console.log("[Markdown] Detected .md link:", href);
// Must be relative (not start with http:// or https://)
const isRelativeLink =
href && !href.startsWith("http://") && !href.startsWith("https://");
if (isRelativeLink && (href.endsWith(".md") || href.includes(".md#"))) {
console.log("[Markdown] Detected relative .md link:", href);
// Extract NIP number from various formats (1-3 digits)
const nipMatch = href.match(/(\d{1,3})\.md/);
// Extract NIP number from various formats (numeric 1-3 digits or hex A0-FF)
const nipMatch = href.match(/([0-9A-F]{1,3})\.md/i);
console.log("[Markdown] Regex match result:", nipMatch);
if (nipMatch) {
const nipNumber = nipMatch[1];
const nipNumber = nipMatch[1].toUpperCase();
console.log("[Markdown] Creating NIP link for NIP-" + nipNumber);
return (
@@ -221,7 +225,9 @@ export function Markdown({ content, className = "" }: MarkdownProps) {
return (
<div className={className}>
<ReactMarkdown components={components}>{content}</ReactMarkdown>
<ReactMarkdown components={components} remarkPlugins={[remarkGfm]}>
{content}
</ReactMarkdown>
</div>
);
}

View File

@@ -12,23 +12,26 @@ function hasRTLCharacters(text: string): boolean {
export function Text({ node }: TextNodeProps) {
const text = node.value;
// If no newlines, render as inline span
if (!text.includes("\n")) {
const isRTL = hasRTLCharacters(text);
return <span dir={isRTL ? "rtl" : "auto"}>{text || "\u00A0"}</span>;
}
// If has newlines, use divs for proper RTL per line
// If has newlines, use regular inline spans with <br> tags
const lines = text.split("\n");
return (
<>
{lines.map((line, idx) => {
const isRTL = hasRTLCharacters(line);
return (
<div key={idx} dir={isRTL ? "rtl" : "auto"}>
{line || "\u00A0"}
</div>
<>
{idx > 0 && <br key={`br-${idx}`} />}
<span key={idx} dir={isRTL ? "rtl" : "auto"}>
{line || "\u00A0"}
</span>
</>
);
})}
</>

View File

@@ -1,4 +1,3 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { EventStoreProvider } from "applesauce-react/providers";
import Root from "./root";
@@ -10,9 +9,7 @@ import "react-mosaic-component/react-mosaic-component.css";
document.documentElement.classList.add("dark");
createRoot(document.getElementById("root")!).render(
<StrictMode>
<EventStoreProvider eventStore={eventStore}>
<Root />
</EventStoreProvider>
</StrictMode>,
<EventStoreProvider eventStore={eventStore}>
<Root />
</EventStoreProvider>,
);