mirror of
https://github.com/Blah-IM/Weblah.git
synced 2025-04-30 16:21:09 +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'> {
|
||||
onDocChange?: (doc: Node) => void;
|
||||
placeholder?: string;
|
||||
/**
|
||||
* The initial content in editor.
|
||||
*
|
||||
* This is higher priority than `children`.
|
||||
*/
|
||||
initialDoc?: Node | null;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
const { onDocChange, placeholder = '', children, ...stateConfiguration }: Props = $props();
|
||||
const {
|
||||
onDocChange,
|
||||
placeholder = '',
|
||||
children,
|
||||
initialDoc: initialDocProp,
|
||||
...stateConfiguration
|
||||
}: Props = $props();
|
||||
|
||||
let domEl: HTMLDivElement;
|
||||
let editorView: EditorView;
|
||||
|
@ -18,7 +30,8 @@
|
|||
let isEmpty = $state(!children);
|
||||
|
||||
$effect(() => {
|
||||
const initialDoc = DOMParser.fromSchema(stateConfiguration.schema).parse(domEl);
|
||||
const initialDoc =
|
||||
initialDocProp ?? DOMParser.fromSchema(stateConfiguration.schema).parse(domEl);
|
||||
domEl.replaceChildren();
|
||||
onDocChange?.(initialDoc);
|
||||
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({
|
||||
nodes: {
|
||||
doc: { content: 'block+' },
|
||||
paragragh: {
|
||||
paragraph: {
|
||||
content: 'inline*',
|
||||
...basicNodes.paragraph
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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) {
|
||||
for (const _ in obj) return false;
|
||||
|
@ -58,3 +58,28 @@ export function proseMirrorDocToBlahRichText(doc: Node): BlahRichText {
|
|||
|
||||
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 RichTextInput from '$lib/components/RichTextInput.svelte';
|
||||
import { messageSchema } from '$lib/components/RichTextInput/schema';
|
||||
import { blahRichTextToProseMirrorDoc } from '$lib/richText';
|
||||
import type { Node } from 'prosemirror-model';
|
||||
|
||||
const currentAccount = $derived(accountsManager.currentAccount);
|
||||
let profile: BlahProfile | null = $state(null);
|
||||
let initialBio: Node | null = $state(null);
|
||||
|
||||
let isBusy: boolean = $state(false);
|
||||
|
||||
|
@ -23,21 +26,17 @@
|
|||
if (currentAccount) {
|
||||
const snapshot = $state.snapshot(currentAccount.profile.signee.payload);
|
||||
profile = snapshot;
|
||||
console.log('Reloaded');
|
||||
initialBio = blahRichTextToProseMirrorDoc([snapshot.bio ?? ''], messageSchema);
|
||||
}
|
||||
});
|
||||
|
||||
$inspect(profile);
|
||||
|
||||
async function saveProfile() {
|
||||
if (!currentAccount || !profile) return;
|
||||
|
||||
console.log('Saving profile', $state.snapshot(profile));
|
||||
isBusy = true;
|
||||
const identity = await accountsManager.identityForAccount(currentAccount);
|
||||
await identity.updateProfile(profile);
|
||||
await accountsManager.saveIdentity(identity);
|
||||
console.log('Profile saved', identity.generateIdentityDescription());
|
||||
isBusy = false;
|
||||
}
|
||||
</script>
|
||||
|
@ -67,9 +66,8 @@
|
|||
schema={messageSchema}
|
||||
onDocChange={(doc) => profile && (profile.bio = doc.textContent)}
|
||||
placeholder="a 25 yo. artist from Paris."
|
||||
>
|
||||
{profile.bio ?? ''}
|
||||
</RichTextInput>
|
||||
initialDoc={initialBio}
|
||||
/>
|
||||
</GroupedListSection>
|
||||
</GroupedListContainer>
|
||||
{/if}
|
||||
|
|
Loading…
Add table
Reference in a new issue