From 2bbc273bc10ea8a3081bb93746437a000a82606e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=98=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Sat, 8 Aug 2026 10:35:57 +0300 Subject: [PATCH 1/3] feat: separate short and full answers --- src/plugins/rehype-unwrap-details-table.ts | 53 +++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/plugins/rehype-unwrap-details-table.ts b/src/plugins/rehype-unwrap-details-table.ts index 544982c..ca6818d 100644 --- a/src/plugins/rehype-unwrap-details-table.ts +++ b/src/plugins/rehype-unwrap-details-table.ts @@ -2,6 +2,9 @@ import type {Element, ElementContent, Root, RootContent} from 'hast'; type Node = Root | RootContent | ElementContent; +const SHORT_ANSWER_TITLE = 'Короткий ответ'; +const FULL_ANSWER_TITLE = 'Полный ответ'; + const isElement = (node: Node): node is Element => node.type === 'element'; const isTag = (node: Node, tagName: string): node is Element => @@ -45,6 +48,54 @@ const getTextContent = (node: Node): string => { return node.children.map((child) => getTextContent(child)).join(''); }; +const isAnswerTitle = (node: ElementContent, title: string): node is Element => + isTag(node, 'p') && getTextContent(node).trim() === title; + +const createAnswerSection = ( + className: string, + children: ElementContent[], +): Element => ({ + type: 'element', + tagName: 'div', + properties: { + className: [className], + }, + children, +}); + +const splitAnswerSections = (children: ElementContent[]): ElementContent[] => { + const shortAnswerIndex = children.findIndex((child) => + isAnswerTitle(child, SHORT_ANSWER_TITLE), + ); + const fullAnswerIndex = children.findIndex( + (child, index) => + index > shortAnswerIndex && isAnswerTitle(child, FULL_ANSWER_TITLE), + ); + + if (shortAnswerIndex === -1 || fullAnswerIndex === -1) { + return children; + } + + const shortAnswerTitle = children[shortAnswerIndex]; + const fullAnswerTitle = children[fullAnswerIndex]; + + if (!isElement(shortAnswerTitle) || !isElement(fullAnswerTitle)) { + return children; + } + + shortAnswerTitle.properties.className = ['answer-title']; + fullAnswerTitle.properties.className = ['answer-title']; + + return [ + ...children.slice(0, shortAnswerIndex), + createAnswerSection( + 'answer-short', + children.slice(shortAnswerIndex, fullAnswerIndex), + ), + createAnswerSection('answer-full', children.slice(fullAnswerIndex)), + ]; +}; + const createSlug = (value: string): string => value .toLocaleLowerCase('ru') @@ -132,7 +183,7 @@ const unwrapDetailsTable = (details: Element): void => { properties: { className: ['answer'], }, - children: cellChildren, + children: splitAnswerSections(cellChildren), }); continue; From 81f85e9c68e587d93b36911e3e03aabd25f221a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=98=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Sat, 8 Aug 2026 10:36:08 +0300 Subject: [PATCH 2/3] style: highlight short answers --- src/styles/markdown-details.css | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/styles/markdown-details.css b/src/styles/markdown-details.css index 9ca6bb2..a7772fa 100644 --- a/src/styles/markdown-details.css +++ b/src/styles/markdown-details.css @@ -59,6 +59,44 @@ font-weight: 800; } +.content details .answer-short { + margin-bottom: 28px; + padding: 16px 18px; + border: 1px solid var(--border); + border-inline-start: 4px solid var(--accent); + border-radius: 10px; + background: var(--accent-soft); +} + +.content details .answer-short > :last-child, +.content details .answer-full > :last-child { + margin-bottom: 0; +} + +.content details .answer .answer-title { + color: var(--text); + font-size: 1.05rem; + line-height: 1.4; +} + +.content details .answer-short .answer-title { + margin-bottom: 8px; + color: var(--accent-strong); +} + +.content details .answer-short .answer-title strong { + color: inherit; +} + +.content details .answer-full { + padding-top: 20px; + border-top: 1px solid var(--border); +} + +.content details .answer-full .answer-title { + margin-bottom: 12px; +} + .content details .answer ul, .content details .answer ol { margin: 12px 0 20px; From eef0f4ddab63bc071d5b1da7532a8f813190c6a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=98=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Sat, 8 Aug 2026 10:47:26 +0300 Subject: [PATCH 3/3] fix: format rehype plugin --- src/plugins/rehype-unwrap-details-table.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/plugins/rehype-unwrap-details-table.ts b/src/plugins/rehype-unwrap-details-table.ts index ca6818d..ac6069f 100644 --- a/src/plugins/rehype-unwrap-details-table.ts +++ b/src/plugins/rehype-unwrap-details-table.ts @@ -51,10 +51,7 @@ const getTextContent = (node: Node): string => { const isAnswerTitle = (node: ElementContent, title: string): node is Element => isTag(node, 'p') && getTextContent(node).trim() === title; -const createAnswerSection = ( - className: string, - children: ElementContent[], -): Element => ({ +const createAnswerSection = (className: string, children: ElementContent[]): Element => ({ type: 'element', tagName: 'div', properties: {