diff --git a/components/text.js b/components/text.js
index 36b06cf0e..757a568e5 100644
--- a/components/text.js
+++ b/components/text.js
@@ -255,7 +255,7 @@ function P ({ children, node, onlyImages, somethingBefore, somethingAfter, ...pr
)
}
-function Details({ children, node, ...props }) {
+function Details ({ children, node, ...props }) {
return (
{children}
@@ -263,7 +263,7 @@ function Details({ children, node, ...props }) {
)
}
-function Summary({ children, node, ...props }) {
+function Summary ({ children, node, ...props }) {
return (
{children}
diff --git a/components/text.module.css b/components/text.module.css
index b526da1ac..7b5dc2fd8 100644
--- a/components/text.module.css
+++ b/components/text.module.css
@@ -439,3 +439,42 @@
}
/* Details/Summary styling */
+.details {
+ border-left: 2px solid var(--theme-quoteBar);
+ padding-left: 0.75rem;
+ margin: calc(var(--grid-gap) * 0.5) 0;
+ transition: border-color 0.2s ease;
+}
+
+.details[open] {
+ border-left-color: #f7931a;
+}
+
+.summary {
+ cursor: pointer;
+ user-select: none;
+ color: #8b949e;
+ transition: color 0.2s ease;
+ padding: 0.25rem 0;
+}
+
+.summary:hover {
+ color: #ffd700;
+}
+
+
+.summary::marker,
+.summary::-webkit-details-marker {
+ color: #8b949e;
+}
+
+.details[open] > .summary::marker,
+.details[open] > .summary::-webkit-details-marker {
+ color: #f7931a;
+}
+
+
+.details > *:not(.summary) {
+ margin-top: calc(var(--grid-gap) * 0.5);
+ padding-bottom: calc(var(--grid-gap) * 0.25);
+}
diff --git a/lib/rehype-sn.js b/lib/rehype-sn.js
index 43290478d..6ee4241ab 100644
--- a/lib/rehype-sn.js
+++ b/lib/rehype-sn.js
@@ -13,14 +13,13 @@ const mentionRegex = new RegExp('@(' + userGroup + '(?:\\/' + userGroup + ')?)',
const subRegex = new RegExp('~(' + subGroup + '(?:\\/' + subGroup + ')?)', 'gi')
const nostrIdRegex = /\b((npub1|nevent1|nprofile1|note1|naddr1)[02-9ac-hj-np-z]+)\b/g
-export default function rehypeSN(options = {}) {
+export default function rehypeSN (options = {}) {
const { stylers = [] } = options
- return function transformer(tree) {
+ return function transformer (tree) {
try {
visit(tree, (node, index, parent) => {
-
- // Leave all other existing handlers unchanged
+ // Handle inline code property
if (node.tagName === 'code') {
node.properties.inline = !(parent && parent.tagName === 'pre')
}
@@ -233,7 +232,7 @@ export default function rehypeSN(options = {}) {
// Handle self-contained details block
if (node.value.includes('
')) {
let content = node.value
-
+
// Extract summary if present
const summaryMatch = content.match(/(.*?)<\/summary>/s)
if (summaryMatch) {
@@ -244,13 +243,13 @@ export default function rehypeSN(options = {}) {
detailsContent.summary.complete = true
content = content.replace(/.*?<\/summary>/s, '')
}
-
+
// Clean remaining content
const cleanedContent = content
.replace(//g, '')
.replace(/<\/details>/g, '')
.trim()
-
+
if (cleanedContent) {
detailsContent.content.push({
type: 'text',
@@ -263,7 +262,7 @@ export default function rehypeSN(options = {}) {
// Clean opening details tag and handle potential summary
let cleanedContent = node.value.replace(//g, '')
-
+
// Check for summary in opening node
const summaryMatch = cleanedContent.match(/(.*?)<\/summary>/s)
if (summaryMatch) {
@@ -274,7 +273,7 @@ export default function rehypeSN(options = {}) {
detailsContent.summary.complete = true
cleanedContent = cleanedContent.replace(/.*?<\/summary>/s, '')
}
-
+
if (cleanedContent.trim()) {
detailsContent.content.push({
type: 'text',
@@ -285,11 +284,11 @@ export default function rehypeSN(options = {}) {
// Collect remaining content
let currentIndex = index
let foundClosing = false
-
+
while (currentIndex < parent.children.length) {
const currentNode = parent.children[++currentIndex]
if (!currentNode) break
-
+
// Handle summary tags if we haven't found a complete summary yet
if (!detailsContent.summary.complete) {
if (currentNode.type === 'raw' && currentNode.value.includes('')) {
@@ -316,7 +315,7 @@ export default function rehypeSN(options = {}) {
const afterSummary = currentNode.value.substring(
currentNode.value.indexOf('
') + '
'.length
).trim()
-
+
if (afterSummary) {
detailsContent.content.push({
type: 'text',
@@ -335,7 +334,7 @@ export default function rehypeSN(options = {}) {
}
continue
}
-
+
// If we're collecting summary content
if (detailsContent.summary.found) {
if (currentNode.type === 'raw' && currentNode.value.includes('
')) {
@@ -360,9 +359,8 @@ export default function rehypeSN(options = {}) {
// Check for closing details tag
const hasClosingTag = (currentNode.type === 'raw' && currentNode.value.includes(' ')) ||
(currentNode.type === 'element' && toString(currentNode).includes(' '))
-
+
if (hasClosingTag) {
- let cleanedContent
if (currentNode.type === 'raw') {
const textBeforeClosing = currentNode.value.substring(0, currentNode.value.indexOf(''))
if (textBeforeClosing.includes('\n')) {
@@ -418,18 +416,17 @@ export default function rehypeSN(options = {}) {
return createDetailsElement(detailsContent, parent, index)
}
-
})
return tree
} catch (error) {
- console.error('❌ Error in rehypeSN transformer:', error)
+ console.error('Error in rehypeSN transformer:', error)
return tree
}
}
}
-function isImageOnlyParagraph(node) {
+function isImageOnlyParagraph (node) {
return node &&
node.tagName === 'p' &&
Array.isArray(node.children) &&
@@ -439,7 +436,7 @@ function isImageOnlyParagraph(node) {
)
}
-function replaceMention(value, username) {
+function replaceMention (value, username) {
return {
type: 'element',
tagName: 'mention',
@@ -448,7 +445,7 @@ function replaceMention(value, username) {
}
}
-function replaceSub(value, sub) {
+function replaceSub (value, sub) {
return {
type: 'element',
tagName: 'sub',
@@ -457,7 +454,7 @@ function replaceSub(value, sub) {
}
}
-function replaceNostrId(value, id) {
+function replaceNostrId (value, id) {
return {
type: 'element',
tagName: 'a',
@@ -466,7 +463,7 @@ function replaceNostrId(value, id) {
}
}
-function isMisleadingLink(text, href) {
+function isMisleadingLink (text, href) {
let misleading = false
if (/^\s*(\w+\.)+\w+/.test(text)) {
@@ -482,12 +479,7 @@ function isMisleadingLink(text, href) {
}
// Helper to create details element
-function createDetailsElement(detailsContent, parent, index) {
- console.log('\n🔨 Creating details element with:', {
- hasSummary: detailsContent.summary.complete,
- contentNodes: detailsContent.content.length
- })
-
+function createDetailsElement (detailsContent, parent, index) {
const detailsElement = {
type: 'element',
tagName: 'details',
@@ -504,12 +496,10 @@ function createDetailsElement(detailsContent, parent, index) {
children: detailsContent.summary.content
}
detailsElement.children.push(summaryElement)
- console.log('✨ Added summary element')
}
// Add main content
detailsElement.children.push(...detailsContent.content)
- console.log('✨ Added content elements')
// Replace nodes
parent.children.splice(