@storyblok/richtext
Advanced tools
Comparing version 0.4.0 to 0.4.1
import { SbRichTextOptions, SbRichTextNode } from './types'; | ||
export declare function richTextResolver<T>(options: SbRichTextOptions<T>): { | ||
/** | ||
* Creates a rich text resolver with the given options. | ||
* | ||
* @export | ||
* @template T | ||
* @param {SbRichTextOptions<T>} [options={}] | ||
* @return {*} | ||
*/ | ||
export declare function richTextResolver<T>(options?: SbRichTextOptions<T>): { | ||
render: (node: SbRichTextNode<T>) => T; | ||
}; |
@@ -9,4 +9,3 @@ /** | ||
function x(e, r) { | ||
if (!r) | ||
return { src: e, attrs: {} }; | ||
if (!r) return { src: e, attrs: {} }; | ||
let l = 0, d = 0; | ||
@@ -45,3 +44,3 @@ const m = {}, s = []; | ||
} | ||
function G(e) { | ||
function G(e = {}) { | ||
let r = 0; | ||
@@ -48,0 +47,0 @@ const { |
@@ -7,2 +7,2 @@ /** | ||
*/ | ||
(function(m,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(m=typeof globalThis<"u"?globalThis:m||self,l(m.StoryblokRichtext={}))})(this,function(m){"use strict";var l=(e=>(e.DOCUMENT="doc",e.HEADING="heading",e.PARAGRAPH="paragraph",e.QUOTE="blockquote",e.OL_LIST="ordered_list",e.UL_LIST="bullet_list",e.LIST_ITEM="list_item",e.CODE_BLOCK="code_block",e.HR="horizontal_rule",e.BR="hard_break",e.IMAGE="image",e.EMOJI="emoji",e.COMPONENT="blok",e))(l||{}),o=(e=>(e.BOLD="bold",e.STRONG="strong",e.STRIKE="strike",e.UNDERLINE="underline",e.ITALIC="italic",e.CODE="code",e.LINK="link",e.ANCHOR="anchor",e.STYLED="styled",e.SUPERSCRIPT="superscript",e.SUBSCRIPT="subscript",e.TEXT_STYLE="textStyle",e.HIGHLIGHT="highlight",e))(o||{}),A=(e=>(e.TEXT="text",e))(A||{}),j=(e=>(e.SELF="_self",e.BLANK="_blank",e))(j||{}),T=(e=>(e.URL="url",e.STORY="story",e.ASSET="asset",e.EMAIL="email",e))(T||{});function C(e,r){if(!r)return{src:e,attrs:{}};let a=0,R=0;const g={},c=[];function f(u,d,$,s,E){typeof u!="number"||u<=d||u>=$?console.warn(`[SbRichText] - ${s.charAt(0).toUpperCase()+s.slice(1)} value must be a number between ${d} and ${$} (inclusive)`):E.push(`${s}(${u})`)}if(typeof r=="object"){if(typeof r.width=="number"&&r.width>0?(g.width=r.width,a=r.width):console.warn("[SbRichText] - Width value must be a number greater than 0"),r.height&&typeof r.height=="number"&&r.height>0?(g.height=r.height,R=r.height):console.warn("[SbRichText] - Height value must be a number greater than 0"),r.loading&&["lazy","eager"].includes(r.loading)&&(g.loading=r.loading),r.class&&(g.class=r.class),r.filters){const{filters:u}=r||{},{blur:d,brightness:$,fill:s,format:E,grayscale:O,quality:L,rotate:v}=u||{};d&&f(d,0,100,"blur",c),L&&f(L,0,100,"quality",c),$&&f($,0,100,"brightness",c),s&&c.push(`fill(${s})`),O&&c.push("grayscale()"),v&&[0,90,180,270].includes(r.filters.rotate||0)&&c.push(`rotate(${v})`),E&&["webp","png","jpeg"].includes(E)&&c.push(`format(${E})`)}r.srcset&&(g.srcset=r.srcset.map(u=>{if(typeof u=="number")return`${e}/m/${u}x0/${c.length>0?"filters:"+c.join(":"):""} ${u}w`;if(Array.isArray(u)&&u.length===2){const[d,$]=u;return`${e}/m/${d}x${$}/${c.length>0?"filters:"+c.join(":"):""} ${d}w`}}).join(", ")),r.sizes&&(g.sizes=r.sizes.join(", "))}let I=`${e}/m/`;return a>0&&R>0&&(I=`${I}${a}x${R}/`),c.length>0&&(I=`${I}filters:${c.join(":")}`),{src:I,attrs:g}}const H=(e={})=>Object.keys(e).map(r=>`${r}="${e[r]}"`).join(" "),_=(e={})=>Object.keys(e).map(r=>`${r}: ${e[r]}`).join("; ");function w(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function x(e,r={},a){const R=H(r);return`<${R?`${e} ${R}`:e}>${Array.isArray(a)?a.join(""):a||""}</${e}>`}function P(e){let r=0;const{renderFn:a=x,textFn:R=w,resolvers:g={},optimizeImages:c=!1}=e,f=t=>i=>a(t,{...i.attrs,key:`${t}-${r}`},i.children||null),I=t=>{const{src:i,alt:n,...h}=t.attrs||{};let b=i,S={};if(c){const{src:p,attrs:G}=C(i,c);b=p,S=G}const D={src:b,alt:n||"",key:`img-${r}`,...h,...S};return a("img",D,"")},u=t=>{const{level:i,...n}=t.attrs||{};return a(`h${i}`,{...n,key:`h${i}-${r}`},t.children)},d=t=>{var i,n,h,b;return a("span",{"data-type":"emoji","data-name":(i=t.attrs)==null?void 0:i.name,emoji:(n=t.attrs)==null?void 0:n.emoji,key:`emoji-${r}`},a("img",{src:(h=t.attrs)==null?void 0:h.fallbackImage,alt:(b=t.attrs)==null?void 0:b.alt,style:"width: 1.25em; height: 1.25em; vertical-align: text-top",draggable:"false",loading:"lazy"},""))},$=t=>a("pre",{...t.attrs,key:`code-${r}`},a("code",{key:`code-${r}`},t.children||"")),s=(t,i=!1)=>({text:n,attrs:h})=>a(t,i?{style:_(h),key:`${t}-${r}`}:{...h,key:`${t}-${r}`},n),E=t=>y(t),O=t=>{const{marks:i,...n}=t;return"text"in t?i?i.reduce((h,b)=>E({...b,text:h}),E({...n,children:n.children})):R(n.text):""},L=t=>{const{linktype:i,href:n,anchor:h,...b}=t.attrs||{};let S="";switch(i){case T.ASSET:case T.URL:S=n;break;case T.EMAIL:S=`mailto:${n}`;break;case T.STORY:S=n;break}return h&&(S=`${S}#${h}`),a("a",{...b,href:S,key:`a-${r}`},t.text)},v=t=>{var i,n;return console.warn("[SbRichtText] - BLOK resolver is not available for vanilla usage"),a("span",{blok:(i=t==null?void 0:t.attrs)==null?void 0:i.body[0],id:(n=t.attrs)==null?void 0:n.id,key:`component-${r}`,style:"display: none"},"")},U=new Map([[l.DOCUMENT,f("div")],[l.HEADING,u],[l.PARAGRAPH,f("p")],[l.UL_LIST,f("ul")],[l.OL_LIST,f("ol")],[l.LIST_ITEM,f("li")],[l.IMAGE,I],[l.EMOJI,d],[l.CODE_BLOCK,$],[l.HR,f("hr")],[l.BR,f("br")],[l.QUOTE,f("blockquote")],[l.COMPONENT,v],[A.TEXT,O],[o.LINK,L],[o.ANCHOR,L],[o.STYLED,s("span",!0)],[o.BOLD,s("strong")],[o.TEXT_STYLE,s("span",!0)],[o.ITALIC,s("em")],[o.UNDERLINE,s("u")],[o.STRIKE,s("s")],[o.CODE,s("code")],[o.SUPERSCRIPT,s("sup")],[o.SUBSCRIPT,s("sub")],[o.HIGHLIGHT,s("mark")],...Object.entries(g).map(([t,i])=>[t,i])]);function N(t){r+=1;const i=U.get(t.type);if(!i)return console.error("<Storyblok>",`No resolver found for node type ${t.type}`),"";if(t.type==="text")return i(t);const n=t.content?t.content.map(y):void 0;return i({...t,children:n})}function y(t){return Array.isArray(t)?t.map(N):N(t)}return{render:y}}m.BlockTypes=l,m.LinkTargets=j,m.LinkTypes=T,m.MarkTypes=o,m.TextTypes=A,m.richTextResolver=P,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})}); | ||
(function(m,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(m=typeof globalThis<"u"?globalThis:m||self,l(m.StoryblokRichtext={}))})(this,function(m){"use strict";var l=(e=>(e.DOCUMENT="doc",e.HEADING="heading",e.PARAGRAPH="paragraph",e.QUOTE="blockquote",e.OL_LIST="ordered_list",e.UL_LIST="bullet_list",e.LIST_ITEM="list_item",e.CODE_BLOCK="code_block",e.HR="horizontal_rule",e.BR="hard_break",e.IMAGE="image",e.EMOJI="emoji",e.COMPONENT="blok",e))(l||{}),o=(e=>(e.BOLD="bold",e.STRONG="strong",e.STRIKE="strike",e.UNDERLINE="underline",e.ITALIC="italic",e.CODE="code",e.LINK="link",e.ANCHOR="anchor",e.STYLED="styled",e.SUPERSCRIPT="superscript",e.SUBSCRIPT="subscript",e.TEXT_STYLE="textStyle",e.HIGHLIGHT="highlight",e))(o||{}),A=(e=>(e.TEXT="text",e))(A||{}),j=(e=>(e.SELF="_self",e.BLANK="_blank",e))(j||{}),T=(e=>(e.URL="url",e.STORY="story",e.ASSET="asset",e.EMAIL="email",e))(T||{});function C(e,r){if(!r)return{src:e,attrs:{}};let a=0,R=0;const g={},c=[];function f(u,d,$,s,E){typeof u!="number"||u<=d||u>=$?console.warn(`[SbRichText] - ${s.charAt(0).toUpperCase()+s.slice(1)} value must be a number between ${d} and ${$} (inclusive)`):E.push(`${s}(${u})`)}if(typeof r=="object"){if(typeof r.width=="number"&&r.width>0?(g.width=r.width,a=r.width):console.warn("[SbRichText] - Width value must be a number greater than 0"),r.height&&typeof r.height=="number"&&r.height>0?(g.height=r.height,R=r.height):console.warn("[SbRichText] - Height value must be a number greater than 0"),r.loading&&["lazy","eager"].includes(r.loading)&&(g.loading=r.loading),r.class&&(g.class=r.class),r.filters){const{filters:u}=r||{},{blur:d,brightness:$,fill:s,format:E,grayscale:O,quality:L,rotate:v}=u||{};d&&f(d,0,100,"blur",c),L&&f(L,0,100,"quality",c),$&&f($,0,100,"brightness",c),s&&c.push(`fill(${s})`),O&&c.push("grayscale()"),v&&[0,90,180,270].includes(r.filters.rotate||0)&&c.push(`rotate(${v})`),E&&["webp","png","jpeg"].includes(E)&&c.push(`format(${E})`)}r.srcset&&(g.srcset=r.srcset.map(u=>{if(typeof u=="number")return`${e}/m/${u}x0/${c.length>0?"filters:"+c.join(":"):""} ${u}w`;if(Array.isArray(u)&&u.length===2){const[d,$]=u;return`${e}/m/${d}x${$}/${c.length>0?"filters:"+c.join(":"):""} ${d}w`}}).join(", ")),r.sizes&&(g.sizes=r.sizes.join(", "))}let I=`${e}/m/`;return a>0&&R>0&&(I=`${I}${a}x${R}/`),c.length>0&&(I=`${I}filters:${c.join(":")}`),{src:I,attrs:g}}const H=(e={})=>Object.keys(e).map(r=>`${r}="${e[r]}"`).join(" "),_=(e={})=>Object.keys(e).map(r=>`${r}: ${e[r]}`).join("; ");function w(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function x(e,r={},a){const R=H(r);return`<${R?`${e} ${R}`:e}>${Array.isArray(a)?a.join(""):a||""}</${e}>`}function P(e={}){let r=0;const{renderFn:a=x,textFn:R=w,resolvers:g={},optimizeImages:c=!1}=e,f=t=>i=>a(t,{...i.attrs,key:`${t}-${r}`},i.children||null),I=t=>{const{src:i,alt:n,...h}=t.attrs||{};let b=i,S={};if(c){const{src:p,attrs:G}=C(i,c);b=p,S=G}const D={src:b,alt:n||"",key:`img-${r}`,...h,...S};return a("img",D,"")},u=t=>{const{level:i,...n}=t.attrs||{};return a(`h${i}`,{...n,key:`h${i}-${r}`},t.children)},d=t=>{var i,n,h,b;return a("span",{"data-type":"emoji","data-name":(i=t.attrs)==null?void 0:i.name,emoji:(n=t.attrs)==null?void 0:n.emoji,key:`emoji-${r}`},a("img",{src:(h=t.attrs)==null?void 0:h.fallbackImage,alt:(b=t.attrs)==null?void 0:b.alt,style:"width: 1.25em; height: 1.25em; vertical-align: text-top",draggable:"false",loading:"lazy"},""))},$=t=>a("pre",{...t.attrs,key:`code-${r}`},a("code",{key:`code-${r}`},t.children||"")),s=(t,i=!1)=>({text:n,attrs:h})=>a(t,i?{style:_(h),key:`${t}-${r}`}:{...h,key:`${t}-${r}`},n),E=t=>y(t),O=t=>{const{marks:i,...n}=t;return"text"in t?i?i.reduce((h,b)=>E({...b,text:h}),E({...n,children:n.children})):R(n.text):""},L=t=>{const{linktype:i,href:n,anchor:h,...b}=t.attrs||{};let S="";switch(i){case T.ASSET:case T.URL:S=n;break;case T.EMAIL:S=`mailto:${n}`;break;case T.STORY:S=n;break}return h&&(S=`${S}#${h}`),a("a",{...b,href:S,key:`a-${r}`},t.text)},v=t=>{var i,n;return console.warn("[SbRichtText] - BLOK resolver is not available for vanilla usage"),a("span",{blok:(i=t==null?void 0:t.attrs)==null?void 0:i.body[0],id:(n=t.attrs)==null?void 0:n.id,key:`component-${r}`,style:"display: none"},"")},U=new Map([[l.DOCUMENT,f("div")],[l.HEADING,u],[l.PARAGRAPH,f("p")],[l.UL_LIST,f("ul")],[l.OL_LIST,f("ol")],[l.LIST_ITEM,f("li")],[l.IMAGE,I],[l.EMOJI,d],[l.CODE_BLOCK,$],[l.HR,f("hr")],[l.BR,f("br")],[l.QUOTE,f("blockquote")],[l.COMPONENT,v],[A.TEXT,O],[o.LINK,L],[o.ANCHOR,L],[o.STYLED,s("span",!0)],[o.BOLD,s("strong")],[o.TEXT_STYLE,s("span",!0)],[o.ITALIC,s("em")],[o.UNDERLINE,s("u")],[o.STRIKE,s("s")],[o.CODE,s("code")],[o.SUPERSCRIPT,s("sup")],[o.SUBSCRIPT,s("sub")],[o.HIGHLIGHT,s("mark")],...Object.entries(g).map(([t,i])=>[t,i])]);function N(t){r+=1;const i=U.get(t.type);if(!i)return console.error("<Storyblok>",`No resolver found for node type ${t.type}`),"";if(t.type==="text")return i(t);const n=t.content?t.content.map(y):void 0;return i({...t,children:n})}function y(t){return Array.isArray(t)?t.map(N):N(t)}return{render:y}}m.BlockTypes=l,m.LinkTargets=j,m.LinkTypes=T,m.MarkTypes=o,m.TextTypes=A,m.richTextResolver=P,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})}); |
@@ -74,8 +74,42 @@ export declare enum BlockTypes { | ||
} | ||
/** | ||
* Represents a resolver function for a Storyblok rich text node. | ||
* @template T - The type of the resolved value. | ||
* @param node - The rich text node to resolve. | ||
* @returns The resolved value of type T. | ||
*/ | ||
export type SbRichTextNodeResolver<T = string> = (node: SbRichTextNode<T> | TextNode<T> | MarkNode<T> | LinkNode<T>) => T; | ||
/** | ||
* Represents the configuration options for optimizing images in rich text content. | ||
*/ | ||
export interface SbRichTextImageOptimizationOptions { | ||
/** | ||
* CSS class to be applied to the image. | ||
*/ | ||
class: string; | ||
/** | ||
* Width of the image in pixels. | ||
*/ | ||
width: number; | ||
/** | ||
* Height of the image in pixels. | ||
*/ | ||
height: number; | ||
/** | ||
* Loading strategy for the image. 'lazy' loads the image when it enters the viewport. 'eager' loads the image immediately. | ||
*/ | ||
loading: 'lazy' | 'eager'; | ||
/** | ||
* Optional filters that can be applied to the image to adjust its appearance. | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* const filters: Partial<SbRichTextImageOptimizationOptions['filters']> = { | ||
* blur: 5, | ||
* brightness: 150, | ||
* grayscale: true | ||
* } | ||
* ``` | ||
*/ | ||
filters: Partial<{ | ||
@@ -90,11 +124,112 @@ blur: number; | ||
}>; | ||
/** | ||
* Defines a set of source set values that tell the browser different image sizes to load based on screen conditions. | ||
* The entries can be just the width in pixels or a tuple of width and pixel density. | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* const srcset: (number | [number, number])[] = [ | ||
* 320, | ||
* [640, 2] | ||
* ] | ||
* ``` | ||
*/ | ||
srcset: (number | [number, number])[]; | ||
/** | ||
* A list of sizes that correspond to different viewport widths, instructing the browser on which srcset source to use. | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* const sizes: string[] = [ | ||
* '(max-width: 320px) 280px', | ||
* '(max-width: 480px) 440px', | ||
* '800px' | ||
* ] | ||
* ``` | ||
*/ | ||
sizes: string[]; | ||
} | ||
/** | ||
* Resolvers for Storyblok RichText nodes. | ||
* | ||
* @template T - The type of the resolved value. | ||
*/ | ||
export type SbRichTextResolvers<T = string> = Partial<Record<SbRichTextNodeTypes, SbRichTextNodeResolver<T>>>; | ||
/** | ||
* Represents the options for rendering rich text. | ||
*/ | ||
export interface SbRichTextOptions<T = string, S = (tag: string, attrs: Record<string, any>, text: string) => T> { | ||
/** | ||
* Defines the function that will be used to render the final HTML string (vanilla) or Framework component (React, Vue). | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* const renderFn = (tag: string, attrs: Record<string, any>, text: string) => { | ||
* return `<${tag} ${Object.keys(attrs).map(key => `${key}="${attrs[key]}"`).join(' ')}>${text}</${tag}>` | ||
* } | ||
* | ||
* const options: SbRichTextOptions = { | ||
* renderFn | ||
* } | ||
* ``` | ||
*/ | ||
renderFn?: S; | ||
/** | ||
* Defines the function that will be used to render HTML text. | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* import { h, createTextVNode } from 'vue' | ||
* | ||
* const options: SbRichTextOptions = { | ||
* renderFn: h, | ||
* textFn: createTextVNode | ||
* } | ||
* ``` | ||
*/ | ||
textFn?: Function; | ||
/** | ||
* Defines the resolvers for each type of node. | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* const options: SbRichTextOptions = { | ||
* resolvers: { | ||
* [MarkTypes.LINK]: (node: SbRichTextNode) => { | ||
* return `<a href="${node.attrs.href}">${node.text}</a>` | ||
* } | ||
* } | ||
* } | ||
* ``` | ||
*/ | ||
resolvers?: SbRichTextResolvers<T>; | ||
/** | ||
* Defines opt-out image optimization options. | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* const options: SbRichTextOptions = { | ||
* optimizeImages: true | ||
* } | ||
* ``` | ||
* | ||
* @example | ||
* | ||
* ```typescript | ||
* const options: SbRichTextOptions = { | ||
* optimizeImages: { | ||
* class: 'my-image', | ||
* width: 800, | ||
* height: 600, | ||
* loading: 'lazy', | ||
* } | ||
* ``` | ||
*/ | ||
optimizeImages?: boolean | Partial<SbRichTextImageOptimizationOptions>; | ||
} |
{ | ||
"name": "@storyblok/richtext", | ||
"type": "module", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"packageManager": "pnpm@9.1.4", | ||
@@ -57,19 +57,19 @@ "description": "Storyblok RichText Resolver", | ||
"@vitejs/plugin-basic-ssl": "^1.1.0", | ||
"@vitest/coverage-v8": "^1.6.0", | ||
"@vitest/ui": "^1.6.0", | ||
"@vitest/coverage-v8": "^2.0.3", | ||
"@vitest/ui": "^2.0.3", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-vue": "^9.26.0", | ||
"eslint-plugin-vue": "^9.27.0", | ||
"kolorist": "^1.8.0", | ||
"lint-staged": "^15.2.4", | ||
"lint-staged": "^15.2.7", | ||
"pathe": "^1.1.2", | ||
"prettier": "^3.2.5", | ||
"release-it": "^17.3.0", | ||
"typescript": "^5.4.5", | ||
"vite": "^5.2.11", | ||
"prettier": "^3.3.3", | ||
"release-it": "^17.6.0", | ||
"typescript": "^5.5.3", | ||
"vite": "^5.3.4", | ||
"vite-plugin-banner": "^0.7.1", | ||
"vite-plugin-dts": "^3.9.1", | ||
"vite-plugin-inspect": "^0.8.4", | ||
"vite-plugin-dts": "4.0.0-beta.1", | ||
"vite-plugin-inspect": "^0.8.5", | ||
"vite-plugin-qrcode": "^0.2.3", | ||
"vitest": "^1.6.0", | ||
"vue": "^3.4.27" | ||
"vitest": "^2.0.3", | ||
"vue": "^3.4.32" | ||
}, | ||
@@ -76,0 +76,0 @@ "lint-staged": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32353
458