datocms-html-to-structured-text
Version:
Convert HTML (or a `hast` syntax tree) to a valid DatoCMS Structured Text `dast` document
94 lines (85 loc) • 2.81 kB
text/typescript
import type {
Node,
Root,
NodeType,
Mark,
Heading,
} from 'datocms-structured-text-utils';
import type { Nodes as HastNodes } from 'hast';
export type { Node, Root, NodeType, Mark };
/** The DAST node variant produced for a given `NodeType`. */
export type NodeOf<T extends NodeType> = Extract<Node, { type: T }>;
/**
* The props (everything but `type`) accepted when creating a DAST node of a
* given `NodeType`. For nodes with children, the `children` array can be
* either the strict variant (e.g. `Span[]` for `link`) or the wide `Node[]`
* produced by `visitChildren`. Handlers are responsible for validation.
*/
export type NodePropsFor<T extends NodeType> = NodeOf<T> extends {
children: Array<infer C>;
}
? Omit<NodeOf<T>, 'type' | 'children'> & {
children: Array<C> | Array<Node>;
}
: Omit<NodeOf<T>, 'type'>;
export type CreateNodeFunction = <T extends NodeType>(
type: T,
props: NodePropsFor<T>,
) => NodeOf<T>;
export interface GlobalContext {
/**
* Whether the library has found a <base> tag or should not look further.
* See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
*/
baseUrlFound?: boolean;
/** <base> tag url. This is used for resolving relative URLs. */
baseUrl?: string | null;
[key: string]: unknown;
}
export interface Context {
/** The parent `dast` node type. */
parentNodeType: NodeType;
/** The parent `hast` node. */
parentNode: HastNodes | null;
/** A reference to the current handlers - merged default + user handlers. */
handlers: Record<string, Handler>;
/** A reference to the default handlers record (map). */
defaultHandlers: Record<string, Handler>;
/** true if the content can include newlines, and false if not (such as in headings). */
wrapText: boolean;
/** Marks for span nodes. */
marks?: Mark[];
/** Allowed block types */
allowedBlocks: string[];
/** Allowed heading levels */
allowedHeadingLevels: Heading['level'][];
/** Allowed marks */
allowedMarks: Mark[];
/**
* Prefix for language detection in code blocks.
*
* Detection is done on a class name eg class="language-html".
* Default is `language-`.
*/
codePrefix?: string;
/** Properties in this object are avaliable to every handler as Context
* is not deeply cloned.
*/
global: GlobalContext;
}
/**
* What a `Handler` is allowed to return — sync or wrapped in a promise.
* Custom user handlers can also return an array containing a mix of nodes
* and unresolved promises; `visitChildren` flattens those.
*/
export type HandlerReturn =
| Node
| Array<Node | Promise<Node>>
| null
| undefined
| void;
export type Handler = (
createNodeFunction: CreateNodeFunction,
node: HastNodes,
context: Context,
) => Promise<HandlerReturn> | HandlerReturn;