@portabletext/block-tools
Version:
Can format HTML, Slate JSON or Sanity block array into any other format.
61 lines (55 loc) • 1.97 kB
text/typescript
import type {ArraySchemaType} from '@sanity/types'
import {DEFAULT_SPAN} from '../../constants'
import type {DeserializerRule} from '../../types'
import {isElement, tagName} from '../helpers'
// font-style:italic seems like the most important rule for italic / emphasis in their html
function isEmphasis(el: Node): boolean {
const style = isElement(el) && el.getAttribute('style')
return /font-style:italic/.test(style || '')
}
// font-weight:700 or 600 seems like the most important rule for bold in their html
function isStrong(el: Node): boolean {
const style = isElement(el) && el.getAttribute('style')
return (
/font-weight:700/.test(style || '') || /font-weight:600/.test(style || '')
)
}
// text-decoration seems like the most important rule for underline in their html
function isUnderline(el: Node): boolean {
const style = isElement(el) && el.getAttribute('style')
return /text-decoration:underline/.test(style || '')
}
// Check for attribute given by the Notion preprocessor
function isNotion(el: Node): boolean {
return isElement(el) && Boolean(el.getAttribute('data-is-notion'))
}
export default function createNotionRules(
_blockContentType: ArraySchemaType,
): DeserializerRule[] {
return [
{
deserialize(el) {
// Notion normally exports semantic HTML. However, if you copy a single block, the formatting will be inline styles
// This handles a limited set of styles
if (isElement(el) && tagName(el) === 'span' && isNotion(el)) {
const span = {
...DEFAULT_SPAN,
marks: [] as string[],
text: el.textContent,
}
if (isStrong(el)) {
span.marks.push('strong')
}
if (isUnderline(el)) {
span.marks.push('underline')
}
if (isEmphasis(el)) {
span.marks.push('em')
}
return span
}
return undefined
},
},
]
}