Skip to content

Commit

Permalink
refactor: extract types to @prismicio/types
Browse files Browse the repository at this point in the history
  • Loading branch information
lihbr committed Jun 23, 2021
1 parent 2483ee5 commit f5084a8
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 227 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@
"unit": "nyc --reporter=lcovonly --reporter=text --exclude-after-remap=false ava",
"test": "npm run lint && npm run unit"
},
"dependencies": {
"@prismicio/types": "0.0.9"
},
"devDependencies": {
"@prismicio/types": "0.0.9",
"@typescript-eslint/eslint-plugin": "^4.27.0",
"@typescript-eslint/parser": "^4.27.0",
"ava": "^3.15.0",
Expand Down
2 changes: 1 addition & 1 deletion src/asText.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RichTextField, RTTextNode } from "./types";
import { RichTextField, RTTextNode } from "@prismicio/types";

export const asText = (
richTextField: RichTextField,
Expand Down
21 changes: 11 additions & 10 deletions src/asTree.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import {
NodeType,
RTAnyNode,
RichTextNodeType,
RTBlockNode,
RTEmbedNode,
RTImageNode,
RTInlineNode,
RTListItemNode,
RTNode,
RTOListItemNode,
Tree,
TreeNode,
} from "./types";
} from "@prismicio/types";
import { RTAnyNode, Tree, TreeNode } from "./types";

export const uuid = (): string => {
return (++uuid.i).toString();
Expand Down Expand Up @@ -46,7 +44,7 @@ const createTreeNode = (

const createTextTreeNode = (text: string): TreeNode => {
return createTreeNode({
type: NodeType.span,
type: RichTextNodeType.span,
text,
spans: [],
});
Expand All @@ -58,7 +56,10 @@ const prepareNodes = (nodes: RTNode[]): RTBlockNode[] => {
for (let i = 0; i < mutNodes.length; i++) {
const node = mutNodes[i];

if (node.type === NodeType.listItem || node.type === NodeType.oListItem) {
if (
node.type === RichTextNodeType.listItem ||
node.type === RichTextNodeType.oListItem
) {
const items: (RTListItemNode | RTOListItemNode)[] = [
node as RTListItemNode | RTOListItemNode,
];
Expand All @@ -68,14 +69,14 @@ const prepareNodes = (nodes: RTNode[]): RTBlockNode[] => {
mutNodes.splice(i, 1);
}

if (node.type === NodeType.listItem) {
if (node.type === RichTextNodeType.listItem) {
mutNodes[i] = {
type: NodeType.list,
type: RichTextNodeType.list,
items: items as RTListItemNode[],
};
} else {
mutNodes[i] = {
type: NodeType.oList,
type: RichTextNodeType.oList,
items: items as RTOListItemNode[],
};
}
Expand Down
12 changes: 5 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
export { asTree } from "./asTree";
export { asText } from "./asText";

export {
wrapObjectSerializer,
buildFinalSerializer,
serialize,
} from "./serialize";
export { wrapMapSerializer, composeSerializers, serialize } from "./serialize";

export { NodeType as Element } from "./types";
export { RichTextNodeType as Element } from "@prismicio/types";

export { RichTextError } from "./RichTextError";

export type {
RichTextFunctionSerializer,
RichTextObjectSerializer,
RichTextMapSerializer,
} from "./types";
271 changes: 63 additions & 208 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,143 +1,39 @@
import type {
FilledLinkToDocumentField,
FilledLinkToMediaField,
FilledLinkToWebField,
import {
RichTextNodeType,
RTBlockNode,
RTEmbedNode,
RTEmNode,
RTHeading1Node,
RTHeading2Node,
RTHeading3Node,
RTHeading4Node,
RTHeading5Node,
RTHeading6Node,
RTImageNode,
RTInlineNode,
RTLabelNode,
RTListItemNode,
RTListNode,
RTOListItemNode,
RTOListNode,
RTParagraphNode,
RTPreformattedNode,
RTSpanNode,
RTStrongNode,
RTTextNodeBase,
} from "@prismicio/types";

export const enum NodeType {
heading1 = "heading1",
heading2 = "heading2",
heading3 = "heading3",
heading4 = "heading4",
heading5 = "heading5",
heading6 = "heading6",
paragraph = "paragraph",
preformatted = "preformatted",
strong = "strong",
em = "em",
listItem = "list-item",
oListItem = "o-list-item",
list = "group-list-item",
oList = "group-o-list-item",
image = "image",
embed = "embed",
hyperlink = "hyperlink",
label = "label",
span = "span",
}

export const ReversedNodeType = {
[NodeType.heading1]: "heading1",
[NodeType.heading2]: "heading2",
[NodeType.heading3]: "heading3",
[NodeType.heading4]: "heading4",
[NodeType.heading5]: "heading5",
[NodeType.heading6]: "heading6",
[NodeType.paragraph]: "paragraph",
[NodeType.preformatted]: "preformatted",
[NodeType.strong]: "strong",
[NodeType.em]: "em",
[NodeType.listItem]: "listItem",
[NodeType.oListItem]: "oListItem",
[NodeType.list]: "list",
[NodeType.oList]: "oList",
[NodeType.image]: "image",
[NodeType.embed]: "embed",
[NodeType.hyperlink]: "hyperlink",
[NodeType.label]: "label",
[NodeType.span]: "span",
} as const;

// Node types

// Text nodes
interface RTTextNodeBase<T extends NodeType> {
type: T;
text: string;
spans: RTInlineNode[];
}

export type RTHeading1Node = RTTextNodeBase<NodeType.heading1>;
export type RTHeading2Node = RTTextNodeBase<NodeType.heading2>;
export type RTHeading3Node = RTTextNodeBase<NodeType.heading3>;
export type RTHeading4Node = RTTextNodeBase<NodeType.heading4>;
export type RTHeading5Node = RTTextNodeBase<NodeType.heading5>;
export type RTHeading6Node = RTTextNodeBase<NodeType.heading6>;

export type RTParagraphNode = RTTextNodeBase<NodeType.paragraph>;
export type RTPreformattedNode = RTTextNodeBase<NodeType.preformatted>;

// TODO: This one is so confusing
export type RTBlockSpanNode = RTTextNodeBase<NodeType.span>;

// Spans nodes
interface RTSpanNodeBase<T extends NodeType> {
start: number;
end: number;
type: T;
}

export type RTStrongNode = RTSpanNodeBase<NodeType.strong>;
export type RTEmNode = RTSpanNodeBase<NodeType.em>;
export interface RTLabelNode extends RTSpanNodeBase<NodeType.label> {
data: {
label: string;
};
}
export interface RTSpanNode extends RTSpanNodeBase<NodeType.span> {
text: string;
}

// Lists nodes
export type RTListItemNode = RTTextNodeBase<NodeType.listItem>;
export type RTListNode = {
type: NodeType.list;
items: RTListItemNode[];
};

export type RTOListItemNode = RTTextNodeBase<NodeType.oListItem>;
export type RTOListNode = {
type: NodeType.oList;
items: RTOListItemNode[];
};

// Media nodes
export type RTImageNode = {
type: NodeType.image;
url: string;
alt: string;
copyright: string | null;
dimensions: {
width: number;
height: number;
};
};

export type RTEmbedNode = {
type: NodeType.embed;
oembed: Record<string, string | number | null> & {
html: string;
};
};

export interface RTLinkNode extends RTSpanNodeBase<NodeType.hyperlink> {
data:
| FilledLinkToDocumentField
| FilledLinkToWebField
| FilledLinkToMediaField;
}

// Serializers
export type RichTextFunctionSerializer<T> = (
type: NodeType,
type: RichTextNodeType,
node: RTAnyNode,
text: string | undefined,
children: T[],
key: string,
) => T;

type RTObjectSerializerFunction<
Node extends { type: string },
export type RTMapSerializerFunction<
Node extends { type: RichTextNodeType },
T,
TextType = string | undefined,
ChildrenType = T,
Expand All @@ -149,94 +45,53 @@ type RTObjectSerializerFunction<
key: string;
}) => T;

export type RichTextObjectSerializer<T> = {
heading1?: RTObjectSerializerFunction<RTHeading1Node, T, undefined>;
heading2?: RTObjectSerializerFunction<RTHeading2Node, T, undefined>;
heading3?: RTObjectSerializerFunction<RTHeading3Node, T, undefined>;
heading4?: RTObjectSerializerFunction<RTHeading4Node, T, undefined>;
heading5?: RTObjectSerializerFunction<RTHeading5Node, T, undefined>;
heading6?: RTObjectSerializerFunction<RTHeading6Node, T, undefined>;
paragraph?: RTObjectSerializerFunction<RTParagraphNode, T, undefined>;
preformatted?: RTObjectSerializerFunction<RTPreformattedNode, T, undefined>;
strong?: RTObjectSerializerFunction<RTStrongNode, T, string>;
em?: RTObjectSerializerFunction<RTEmNode, T, string>;
listItem?: RTObjectSerializerFunction<RTListItemNode, T, undefined>;
oListItem?: RTObjectSerializerFunction<RTOListItemNode, T, undefined>;
list?: RTObjectSerializerFunction<RTListNode, T, undefined>;
oList?: RTObjectSerializerFunction<RTOListNode, T, undefined>;
image?: RTObjectSerializerFunction<RTImageNode, T, undefined, never>;
embed?: RTObjectSerializerFunction<RTEmbedNode, T, undefined, never>;
hyperlink?: RTObjectSerializerFunction<RTImageNode, T, string>;
label?: RTObjectSerializerFunction<RTLabelNode, T, string>;
span?: RTObjectSerializerFunction<RTSpanNode, T, never>;
export type RichTextMapSerializer<T> = {
heading1?: RTMapSerializerFunction<RTHeading1Node, T, undefined>;
heading2?: RTMapSerializerFunction<RTHeading2Node, T, undefined>;
heading3?: RTMapSerializerFunction<RTHeading3Node, T, undefined>;
heading4?: RTMapSerializerFunction<RTHeading4Node, T, undefined>;
heading5?: RTMapSerializerFunction<RTHeading5Node, T, undefined>;
heading6?: RTMapSerializerFunction<RTHeading6Node, T, undefined>;
paragraph?: RTMapSerializerFunction<RTParagraphNode, T, undefined>;
preformatted?: RTMapSerializerFunction<RTPreformattedNode, T, undefined>;
strong?: RTMapSerializerFunction<RTStrongNode, T, string>;
em?: RTMapSerializerFunction<RTEmNode, T, string>;
listItem?: RTMapSerializerFunction<RTListItemNode, T, undefined>;
oListItem?: RTMapSerializerFunction<RTOListItemNode, T, undefined>;
list?: RTMapSerializerFunction<RTListNode, T, undefined>;
oList?: RTMapSerializerFunction<RTOListNode, T, undefined>;
image?: RTMapSerializerFunction<RTImageNode, T, undefined, never>;
embed?: RTMapSerializerFunction<RTEmbedNode, T, undefined, never>;
hyperlink?: RTMapSerializerFunction<RTImageNode, T, string>;
label?: RTMapSerializerFunction<RTLabelNode, T, string>;
span?: RTMapSerializerFunction<RTSpanNode, T, never>;
};

// Helpers

// TODO: Actually all the above and this kinda needs to be moved to @prismicio/types...
export type RichTextField = RTNode[];

export type RTNode =
| RTHeading1Node
| RTHeading2Node
| RTHeading3Node
| RTHeading4Node
| RTHeading5Node
| RTHeading6Node
| RTParagraphNode
| RTPreformattedNode
| RTListItemNode
| RTOListItemNode
| RTImageNode
| RTEmbedNode;

export type RTTextNode =
| RTHeading1Node
| RTHeading2Node
| RTHeading3Node
| RTHeading4Node
| RTHeading5Node
| RTHeading6Node
| RTParagraphNode
| RTPreformattedNode
| RTListItemNode
| RTOListItemNode;

export type RTAnyNode = RTBlockNode | RTInlineNode | RTBlockSpanNode;

export type RTBlockNode =
| RTHeading1Node
| RTHeading2Node
| RTHeading3Node
| RTHeading4Node
| RTHeading5Node
| RTHeading6Node
| RTParagraphNode
| RTPreformattedNode
| RTListItemNode
| RTOListItemNode
| RTListNode
| RTOListNode
| RTImageNode
| RTEmbedNode;

export type RTInlineNode =
| RTStrongNode
| RTEmNode
| RTSpanNode
| RTLabelNode
| RTLinkNode;

// Misc
// Tree
export interface Tree {
key: string;
children: TreeNode[];
}

export interface TreeNode {
key: string;
type: NodeType;
type: RichTextNodeType;
text?: string;
node: RTAnyNode;
children: TreeNode[];
}

// Helpers
export type RTAnyNode = RTBlockNode | RTInlineNode | RTBlockSpanNode;

// Internal node type used when building the tree
export interface RTBlockSpanNode extends RTTextNodeBase {
type: RichTextNodeType.span;
}

export const RichTextReversedNoteType = {
[RichTextNodeType.listItem]: "list-item",
[RichTextNodeType.oListItem]: "o-list-item",
[RichTextNodeType.list]: "group-list-item",
[RichTextNodeType.oList]: "group-o-list-item",
} as const;

0 comments on commit f5084a8

Please sign in to comment.