prismicio / prismic-helpers

Set of helpers to manage Prismic data
https://prismic.io/docs/technical-reference/prismicio-helpers
Apache License 2.0
15 stars 9 forks source link

feat: provide `defineHTMLFunctionSerializer` and `defineHTMLMapSerializer` helpers #31

Closed lihbr closed 2 years ago

lihbr commented 3 years ago

Is your feature request related to a problem? Please describe.

Function and map serializers are now beautifully typed but often defined outside of asHTML calls for reusability purposes.

This leads to forcing TypeScript users to specifically type their functions/map (which is fine), but also kills any IntelliSense JavaScript users might have had from them.

Describe the solution you'd like

Exposing two functions, defineHTMLFunctionSerializer and defineHTMLMapSerizlizer, that simply receive said arguments and return them, would allow to get seamless IntelliSense for both TypeScript and JavaScript users.

Describe alternatives you've considered

n/a, haven't thought about it much tbh

Additional context

This is pattern somewhat adopted by other technologies, for example siroc: https://github.com/unjs/siroc/blob/main/src/core/package/index.ts#L100

I also adopted that pattern for the 11ty plugin: https://github.com/prismicio-community/eleventy-plugin-prismic/blob/master/src/definePrismicPluginOptions.ts

angeloashmore commented 3 years ago

JavaScript users

An alternative to consider is JSDoc. Rather than adding to the API, we could document how JavaScript users can hook into the TypeScript types.

/** @type prismicH.HTMLMapSerializer */
const htmlMapSerializer = {
    paragraph: ({ children }) => `<p>${children}</p>`,
};

/** @type prismicH.HTMLFunctionSerializer */
const htmlFunctionSerializer = (type, _node, _text, children) => {
    switch (type) {
        case prismicH.Element.paragraph:
            return `<p>${children}</p>`;
    }
};

TypeScript

For TypeScript users, we could similarly recommend users type it like standard TypeScript. Like the JSDoc approach, this doesn't add to the API and follows existing TypeScript practices.

const htmlMapSerializer: prismicH.HTMLMapSerializer = {
    paragraph: ({ children }) => `<p>${children}</p>`,
};

const htmlFunctionSerializer: prismicH.HTMLFunctionSerializer = (
    type,
    _node,
    _text,
    children,
) => {
    switch (type) {
        case prismicH.Element.paragraph:
            return `<p>${children}</p>`;
    }
};

I personally would lean toward the JSDoc + explicit TS types approach since it builds on existing code. It also won't raise questions about what the defineHTML*Serializer functions are doing (e.g. "Will it modify my serializer?").

This method relies on documenting it and making it clearly available. The same is true for the defineHTML*Serializer functions, but using a function may be more familiar than using @type comments and explicit const types.

lihbr commented 3 years ago

I agree, that's the dilemma. I'm perfectly fine with the JSDoc approach, it's just not that common of a pattern (at least in users' mind?)

If we're fine taking the lead and advocating for JSDoc then I'm all for it 🤷‍♀️

Bringing @samlfair here for input 🙏

samlfair commented 2 years ago

@lihbr I don't have much thoughts on this. The JSDocs approach sounds preferable because it simplifies the DX.

lihbr commented 2 years ago

Let's try JSDoc for now then :) And try to update tech refs accordingly

lihbr commented 2 years ago

Update 01/05/2022:

lihbr commented 2 years ago

Closing this for now, last update highlights our current position on the topic. May this issue be reopened if further consideration is desired.