73 lines
1.9 KiB
TypeScript
73 lines
1.9 KiB
TypeScript
import { splitFrontmatter } from '@tolaria/markdown'
|
|
|
|
export type MobileEditorBlock = {
|
|
id: string
|
|
kind: 'bullet' | 'paragraph'
|
|
text: string
|
|
}
|
|
|
|
export type MobileEditorDocument = {
|
|
title: string
|
|
blocks: MobileEditorBlock[]
|
|
}
|
|
|
|
export type MobileEditorDocumentInput = {
|
|
id: string
|
|
title: string
|
|
content: string
|
|
}
|
|
|
|
export function createMobileEditorDocument(input: MobileEditorDocumentInput): MobileEditorDocument {
|
|
const [, body] = splitFrontmatter(input.content)
|
|
|
|
return {
|
|
title: input.title,
|
|
blocks: createBlocks({ body, title: input.title }),
|
|
}
|
|
}
|
|
|
|
export function createMobileEditorHtml(document: MobileEditorDocument) {
|
|
return `<h1>${escapeHtml({ value: document.title })}</h1>${document.blocks.map(blockToHtml).join('')}`
|
|
}
|
|
|
|
function createBlocks({ body, title }: { body: string; title: string }) {
|
|
return body
|
|
.split('\n')
|
|
.map((line) => line.trim())
|
|
.filter((line) => line && !isTitleHeading({ line, title }))
|
|
.map((line, index) => createBlock({ index, line }))
|
|
}
|
|
|
|
function createBlock({ index, line }: { index: number; line: string }): MobileEditorBlock {
|
|
const bulletText = bulletContent({ line })
|
|
|
|
return {
|
|
id: `${index}:${line}`,
|
|
kind: bulletText ? 'bullet' : 'paragraph',
|
|
text: bulletText ?? line,
|
|
}
|
|
}
|
|
|
|
function bulletContent({ line }: { line: string }) {
|
|
const match = /^[-*]\s+(.+)$/.exec(line)
|
|
return match?.[1] ?? null
|
|
}
|
|
|
|
function isTitleHeading({ line, title }: { line: string; title: string }) {
|
|
return line === `# ${title}`
|
|
}
|
|
|
|
function blockToHtml(block: MobileEditorBlock) {
|
|
const text = escapeHtml({ value: block.text })
|
|
return block.kind === 'bullet' ? `<ul><li>${text}</li></ul>` : `<p>${text}</p>`
|
|
}
|
|
|
|
function escapeHtml({ value }: { value: string }) {
|
|
return value
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
}
|