Weblah/src/lib/richText.ts
2024-08-30 03:21:51 +08:00

70 lines
2.2 KiB
TypeScript

import type { AttributeMap, Delta } from 'typewriter-editor';
import { z } from 'zod';
export const blahRichTextSpanAttributesSchema = z.object({
b: z.boolean().default(false),
i: z.boolean().default(false),
u: z.boolean().default(false),
s: z.boolean().default(false),
m: z.boolean().default(false),
hashtag: z.boolean().default(false),
link: z.string().url().optional()
});
export type BlahRichTextSpanAttributes = z.input<typeof blahRichTextSpanAttributesSchema>;
export const blahRichTextSpanSchema = z.union([
z.tuple([z.string()]),
z.tuple([z.string(), blahRichTextSpanAttributesSchema])
]);
export type BlahRichTextSpan = z.input<typeof blahRichTextSpanSchema>;
export const blahRichTextBlockSchema = z.array(blahRichTextSpanSchema);
export type BlahRichTextBlock = z.input<typeof blahRichTextBlockSchema>;
export const blahRichTextSchema = z.array(blahRichTextBlockSchema);
export type BlahRichText = z.input<typeof blahRichTextSchema>;
function isObjectEmpty(obj: object) {
for (const _ in obj) return false;
return true;
}
function deltaAttributesToBlahRichTextSpanAttributes(
attributes?: AttributeMap
): BlahRichTextSpanAttributes | null {
if (!attributes) return null;
const blahRichTextSpanAttributes: BlahRichTextSpanAttributes = {};
if (attributes.bold) blahRichTextSpanAttributes.b = true;
if (attributes.italic) blahRichTextSpanAttributes.i = true;
if (attributes.code) blahRichTextSpanAttributes.m = true;
if (attributes.link) blahRichTextSpanAttributes.link = attributes.link;
if (attributes.underline) blahRichTextSpanAttributes.u = true;
if (attributes.strike) blahRichTextSpanAttributes.s = true;
return isObjectEmpty(blahRichTextSpanAttributes) ? null : blahRichTextSpanAttributes;
}
export function deltaToBlahRichText(delta: Delta): BlahRichText {
const blocks: BlahRichText = [];
let block: BlahRichTextBlock = [];
for (const op of delta.ops) {
const lines = op.insert?.split('\n');
if (!lines) continue;
const attributes = deltaAttributesToBlahRichTextSpanAttributes(op.attributes);
const line = lines.shift();
block.push(attributes ? [line, attributes] : [line]);
for (const line of lines) {
blocks.push(block);
block = [];
block.push(attributes ? [line, attributes] : [line]);
}
}
return blocks;
}