a tool for shared writing and social publishing

add hard breaks

+29 -8
+9 -3
app/lish/[did]/[publication]/[rkey]/BaseTextBlock.tsx
··· 36 ${isStrikethrough ? "line-through decoration-tertiary" : ""} 37 ${isHighlighted ? "highlight bg-highlight-1" : ""}`.replaceAll("\n", " "); 38 39 if (isCode) { 40 children.push( 41 <code key={counter} className={className} id={id?.id}> 42 - {segment.text} 43 </code>, 44 ); 45 } else if (link) { ··· 50 className={`text-accent-contrast hover:underline ${className}`} 51 target="_blank" 52 > 53 - {segment.text} 54 </a>, 55 ); 56 } else { 57 children.push( 58 <span key={counter} className={className} id={id?.id}> 59 - {segment.text} 60 </span>, 61 ); 62 }
··· 36 ${isStrikethrough ? "line-through decoration-tertiary" : ""} 37 ${isHighlighted ? "highlight bg-highlight-1" : ""}`.replaceAll("\n", " "); 38 39 + // Split text by newlines and insert <br> tags 40 + const textParts = segment.text.split('\n'); 41 + const renderedText = textParts.flatMap((part, i) => 42 + i < textParts.length - 1 ? [part, <br key={`br-${counter}-${i}`} />] : [part] 43 + ); 44 + 45 if (isCode) { 46 children.push( 47 <code key={counter} className={className} id={id?.id}> 48 + {renderedText} 49 </code>, 50 ); 51 } else if (link) { ··· 56 className={`text-accent-contrast hover:underline ${className}`} 57 target="_blank" 58 > 59 + {renderedText} 60 </a>, 61 ); 62 } else { 63 children.push( 64 <span key={counter} className={className} id={id?.id}> 65 + {renderedText} 66 </span>, 67 ); 68 }
+8
components/Blocks/TextBlock/RenderYJSFragment.tsx
··· 60 ); 61 } 62 63 return null; 64 }) 65 )} ··· 144 node: XmlElement | XmlText | XmlHook, 145 ): string { 146 if (node.constructor === XmlElement) { 147 return node 148 .toArray() 149 .map((f) => YJSFragmentToString(f))
··· 60 ); 61 } 62 63 + if (node.constructor === XmlElement && node.nodeName === "hard_break") { 64 + return <br key={index} />; 65 + } 66 + 67 return null; 68 }) 69 )} ··· 148 node: XmlElement | XmlText | XmlHook, 149 ): string { 150 if (node.constructor === XmlElement) { 151 + // Handle hard_break nodes specially 152 + if (node.nodeName === "hard_break") { 153 + return "\n"; 154 + } 155 return node 156 .toArray() 157 .map((f) => YJSFragmentToString(f))
+5 -5
components/Blocks/TextBlock/keymap.ts
··· 145 ); 146 }, 147 "Shift-Enter": (state, dispatch, view) => { 148 - if (multiLine) { 149 - return baseKeymap.Enter(state, dispatch, view); 150 } 151 - return um.withUndoGroup(() => 152 - enter(propsRef, repRef)(state, dispatch, view), 153 - ); 154 }, 155 "Ctrl-Enter": CtrlEnter(propsRef, repRef), 156 "Meta-Enter": CtrlEnter(propsRef, repRef),
··· 145 ); 146 }, 147 "Shift-Enter": (state, dispatch, view) => { 148 + // Insert a hard break 149 + let hardBreak = schema.nodes.hard_break.create(); 150 + if (dispatch) { 151 + dispatch(state.tr.replaceSelectionWith(hardBreak).scrollIntoView()); 152 } 153 + return true; 154 }, 155 "Ctrl-Enter": CtrlEnter(propsRef, repRef), 156 "Meta-Enter": CtrlEnter(propsRef, repRef),
+7
components/Blocks/TextBlock/schema.ts
··· 115 text: { 116 group: "inline", 117 }, 118 }, 119 }; 120 export const schema = new Schema(baseSchema);
··· 115 text: { 116 group: "inline", 117 }, 118 + hard_break: { 119 + group: "inline", 120 + inline: true, 121 + selectable: false, 122 + parseDOM: [{ tag: "br" }], 123 + toDOM: () => ["br"] as const, 124 + }, 125 }, 126 }; 127 export const schema = new Schema(baseSchema);