mirror of
				https://github.com/Blah-IM/Weblah.git
				synced 2025-10-31 10:01:37 +00:00 
			
		
		
		
	fix: Add initialDoc prop and BlahRichText conversion utility
Fix typo in schema ("paragragh" -> "paragraph") and implement
bidirectional conversion between BlahRichText and ProseMirror formats.
Update profile page to use new initialDoc prop instead of children.
			
			
This commit is contained in:
		
							parent
							
								
									aaedd69889
								
							
						
					
					
						commit
						b56b47df82
					
				
					 4 changed files with 48 additions and 12 deletions
				
			
		|  | @ -7,10 +7,22 @@ | ||||||
| 	export interface Props extends Omit<EditorStateConfiguration, 'initialDoc'> { | 	export interface Props extends Omit<EditorStateConfiguration, 'initialDoc'> { | ||||||
| 		onDocChange?: (doc: Node) => void; | 		onDocChange?: (doc: Node) => void; | ||||||
| 		placeholder?: string; | 		placeholder?: string; | ||||||
|  | 		/** | ||||||
|  | 		 * The initial content in editor. | ||||||
|  | 		 * | ||||||
|  | 		 * This is higher priority than `children`. | ||||||
|  | 		 */ | ||||||
|  | 		initialDoc?: Node | null; | ||||||
| 		children?: import('svelte').Snippet; | 		children?: import('svelte').Snippet; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const { onDocChange, placeholder = '', children, ...stateConfiguration }: Props = $props(); | 	const { | ||||||
|  | 		onDocChange, | ||||||
|  | 		placeholder = '', | ||||||
|  | 		children, | ||||||
|  | 		initialDoc: initialDocProp, | ||||||
|  | 		...stateConfiguration | ||||||
|  | 	}: Props = $props(); | ||||||
| 
 | 
 | ||||||
| 	let domEl: HTMLDivElement; | 	let domEl: HTMLDivElement; | ||||||
| 	let editorView: EditorView; | 	let editorView: EditorView; | ||||||
|  | @ -18,7 +30,8 @@ | ||||||
| 	let isEmpty = $state(!children); | 	let isEmpty = $state(!children); | ||||||
| 
 | 
 | ||||||
| 	$effect(() => { | 	$effect(() => { | ||||||
| 		const initialDoc = DOMParser.fromSchema(stateConfiguration.schema).parse(domEl); | 		const initialDoc = | ||||||
|  | 			initialDocProp ?? DOMParser.fromSchema(stateConfiguration.schema).parse(domEl); | ||||||
| 		domEl.replaceChildren(); | 		domEl.replaceChildren(); | ||||||
| 		onDocChange?.(initialDoc); | 		onDocChange?.(initialDoc); | ||||||
| 		isEmpty = initialDoc.textContent.length === 0; | 		isEmpty = initialDoc.textContent.length === 0; | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ import { nodes as basicNodes, marks as basicMarks } from 'prosemirror-schema-bas | ||||||
| export const messageSchema = new Schema({ | export const messageSchema = new Schema({ | ||||||
| 	nodes: { | 	nodes: { | ||||||
| 		doc: { content: 'block+' }, | 		doc: { content: 'block+' }, | ||||||
| 		paragragh: { | 		paragraph: { | ||||||
| 			content: 'inline*', | 			content: 'inline*', | ||||||
| 			...basicNodes.paragraph | 			...basicNodes.paragraph | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import type { BlahRichText, BlahRichTextSpanAttributes } from '@blah-im/core/richText'; | import type { BlahRichText, BlahRichTextSpanAttributes } from '@blah-im/core/richText'; | ||||||
| import type { Node } from 'prosemirror-model'; | import type { Node, Schema } from 'prosemirror-model'; | ||||||
| 
 | 
 | ||||||
| function isObjectEmpty(obj: object) { | function isObjectEmpty(obj: object) { | ||||||
| 	for (const _ in obj) return false; | 	for (const _ in obj) return false; | ||||||
|  | @ -58,3 +58,28 @@ export function proseMirrorDocToBlahRichText(doc: Node): BlahRichText { | ||||||
| 
 | 
 | ||||||
| 	return spans; | 	return spans; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export function blahRichTextToProseMirrorDoc(richText: BlahRichText, schema: Schema): Node { | ||||||
|  | 	console.log(schema); | ||||||
|  | 	const paragraphs = richText.flatMap((span) => { | ||||||
|  | 		if (typeof span === 'string') { | ||||||
|  | 			if (!span.trim().length) return []; | ||||||
|  | 			return [schema.nodes.paragraph.create({}, schema.text(span))]; | ||||||
|  | 		} else { | ||||||
|  | 			const [text, attributes] = span; | ||||||
|  | 			const marks = []; | ||||||
|  | 			if (attributes.b) marks.push(schema.marks.strong.create()); | ||||||
|  | 			if (attributes.i) marks.push(schema.marks.em.create()); | ||||||
|  | 			if (attributes.m) marks.push(schema.marks.code.create()); | ||||||
|  | 			if (attributes.link) marks.push(schema.marks.link.create({ href: attributes.link })); | ||||||
|  | 			if (attributes.u) marks.push(schema.marks.underline.create()); | ||||||
|  | 			if (attributes.s) marks.push(schema.marks.strikethrough.create()); | ||||||
|  | 			if (attributes.tag) marks.push(schema.marks.tag.create()); | ||||||
|  | 			if (attributes.spoiler) marks.push(schema.marks.spoiler.create()); | ||||||
|  | 
 | ||||||
|  | 			return [schema.nodes.paragraph.create({}, schema.text(text, marks))]; | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	return schema.nodes.doc.create({}, paragraphs); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -13,9 +13,12 @@ | ||||||
| 	import Button from '$lib/components/Button.svelte'; | 	import Button from '$lib/components/Button.svelte'; | ||||||
| 	import RichTextInput from '$lib/components/RichTextInput.svelte'; | 	import RichTextInput from '$lib/components/RichTextInput.svelte'; | ||||||
| 	import { messageSchema } from '$lib/components/RichTextInput/schema'; | 	import { messageSchema } from '$lib/components/RichTextInput/schema'; | ||||||
|  | 	import { blahRichTextToProseMirrorDoc } from '$lib/richText'; | ||||||
|  | 	import type { Node } from 'prosemirror-model'; | ||||||
| 
 | 
 | ||||||
| 	const currentAccount = $derived(accountsManager.currentAccount); | 	const currentAccount = $derived(accountsManager.currentAccount); | ||||||
| 	let profile: BlahProfile | null = $state(null); | 	let profile: BlahProfile | null = $state(null); | ||||||
|  | 	let initialBio: Node | null = $state(null); | ||||||
| 
 | 
 | ||||||
| 	let isBusy: boolean = $state(false); | 	let isBusy: boolean = $state(false); | ||||||
| 
 | 
 | ||||||
|  | @ -23,21 +26,17 @@ | ||||||
| 		if (currentAccount) { | 		if (currentAccount) { | ||||||
| 			const snapshot = $state.snapshot(currentAccount.profile.signee.payload); | 			const snapshot = $state.snapshot(currentAccount.profile.signee.payload); | ||||||
| 			profile = snapshot; | 			profile = snapshot; | ||||||
| 			console.log('Reloaded'); | 			initialBio = blahRichTextToProseMirrorDoc([snapshot.bio ?? ''], messageSchema); | ||||||
| 		} | 		} | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	$inspect(profile); |  | ||||||
| 
 |  | ||||||
| 	async function saveProfile() { | 	async function saveProfile() { | ||||||
| 		if (!currentAccount || !profile) return; | 		if (!currentAccount || !profile) return; | ||||||
| 
 | 
 | ||||||
| 		console.log('Saving profile', $state.snapshot(profile)); |  | ||||||
| 		isBusy = true; | 		isBusy = true; | ||||||
| 		const identity = await accountsManager.identityForAccount(currentAccount); | 		const identity = await accountsManager.identityForAccount(currentAccount); | ||||||
| 		await identity.updateProfile(profile); | 		await identity.updateProfile(profile); | ||||||
| 		await accountsManager.saveIdentity(identity); | 		await accountsManager.saveIdentity(identity); | ||||||
| 		console.log('Profile saved', identity.generateIdentityDescription()); |  | ||||||
| 		isBusy = false; | 		isBusy = false; | ||||||
| 	} | 	} | ||||||
| </script> | </script> | ||||||
|  | @ -67,9 +66,8 @@ | ||||||
| 				schema={messageSchema} | 				schema={messageSchema} | ||||||
| 				onDocChange={(doc) => profile && (profile.bio = doc.textContent)} | 				onDocChange={(doc) => profile && (profile.bio = doc.textContent)} | ||||||
| 				placeholder="a 25 yo. artist from Paris." | 				placeholder="a 25 yo. artist from Paris." | ||||||
| 			> | 				initialDoc={initialBio} | ||||||
| 				{profile.bio ?? ''} | 			/> | ||||||
| 			</RichTextInput> |  | ||||||
| 		</GroupedListSection> | 		</GroupedListSection> | ||||||
| 	</GroupedListContainer> | 	</GroupedListContainer> | ||||||
| {/if} | {/if} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Shibo Lyu
						Shibo Lyu