@storyblok/richtext
Version:
Storyblok RichText Resolver
8 lines (7 loc) • 7.25 kB
JavaScript
/**
* name: @storyblok/richtext
* (c) 2025
* description: Storyblok RichText Resolver
* author: Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)
*/
(function(E,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(E=typeof globalThis<"u"?globalThis:E||self,w(E.StoryblokRichText={}))})(this,function(E){"use strict";function w(e,n){if(!n)return{src:e,attrs:{}};let m=0,L=0;const g={},o=[];function O(l,S,$,A,T){typeof l!="number"||l<=S||l>=$?console.warn(`[StoryblokRichText] - ${A.charAt(0).toUpperCase()+A.slice(1)} value must be a number between ${S} and ${$} (inclusive)`):T.push(`${A}(${l})`)}if(typeof n=="object"){if(typeof n.width=="number"&&n.width>0?(g.width=n.width,m=n.width):console.warn("[StoryblokRichText] - Width value must be a number greater than 0"),n.height&&typeof n.height=="number"&&n.height>0?(g.height=n.height,L=n.height):console.warn("[StoryblokRichText] - Height value must be a number greater than 0"),n.loading&&["lazy","eager"].includes(n.loading)&&(g.loading=n.loading),n.class&&(g.class=n.class),n.filters){const{filters:l}=n||{},{blur:S,brightness:$,fill:A,format:T,grayscale:R,quality:C,rotate:_}=l||{};S&&O(S,0,100,"blur",o),C&&O(C,0,100,"quality",o),$&&O($,0,100,"brightness",o),A&&o.push(`fill(${A})`),R&&o.push("grayscale()"),_&&[0,90,180,270].includes(n.filters.rotate||0)&&o.push(`rotate(${_})`),T&&["webp","png","jpeg"].includes(T)&&o.push(`format(${T})`)}n.srcset&&(g.srcset=n.srcset.map(l=>{if(typeof l=="number")return`${e}/m/${l}x0/${o.length>0?`filters:${o.join(":")}`:""} ${l}w`;if(Array.isArray(l)&&l.length===2){const[S,$]=l;return`${e}/m/${S}x${$}/${o.length>0?`filters:${o.join(":")}`:""} ${S}w`}else{console.warn("[StoryblokRichText] - srcset entry must be a number or a tuple of two numbers");return}}).join(", ")),n.sizes&&(g.sizes=n.sizes.join(", "))}let I=`${e}/m/`;return m>0&&L>0&&(I=`${I}${m}x${L}/`),o.length>0&&(I=`${I}filters:${o.join(":")}`),{src:I,attrs:g}}var c=(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.TABLE="table",e.TABLE_ROW="tableRow",e.TABLE_CELL="tableCell",e.TABLE_HEADER="tableHeader",e))(c||{}),h=(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))(h||{}),x=(e=>(e.TEXT="text",e))(x||{}),N=(e=>(e.SELF="_self",e.BLANK="_blank",e))(N||{}),v=(e=>(e.URL="url",e.STORY="story",e.ASSET="asset",e.EMAIL="email",e))(v||{});const G=["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"],z=(e={})=>Object.keys(e).map(n=>`${n}="${e[n]}"`).join(" "),k=(e={})=>Object.keys(e).map(n=>`${n}: ${e[n]}`).join("; ");function F(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}const p=e=>Object.fromEntries(Object.entries(e).filter(([n,m])=>m!==void 0));function H(e,n={},m){const L=z(n),g=L?`${e} ${L}`:e,o=Array.isArray(m)?m.join(""):m||"";if(e){if(G.includes(e))return`<${g}>`}else return o;return`<${g}>${o}</${e}>`}function K(e={}){const n=new Map,{renderFn:m=H,textFn:L=F,resolvers:g={},optimizeImages:o=!1,keyedResolvers:O=!1}=e,I=m!==H,l=t=>(s,r)=>{const i=s.attrs||{};return r.render(t,i,s.children||null)},S=(t,s)=>{const{src:r,alt:i,title:a,srcset:u,sizes:f}=t.attrs||{};let d=r,b={};if(o){const{src:Q,attrs:V}=w(r,o);d=Q,b=V}const J={src:d,alt:i,title:a,srcset:u,sizes:f,...b};return s.render("img",p(J))},$=(t,s)=>{const{level:r,...i}=t.attrs||{};return s.render(`h${r}`,i,t.children)},A=(t,s)=>{var i,a,u,f;const r=s.render("img",{src:(i=t.attrs)==null?void 0:i.fallbackImage,alt:(a=t.attrs)==null?void 0:a.alt,style:"width: 1.25em; height: 1.25em; vertical-align: text-top",draggable:"false",loading:"lazy"});return s.render("span",{"data-type":"emoji","data-name":(u=t.attrs)==null?void 0:u.name,"data-emoji":(f=t.attrs)==null?void 0:f.emoji},r)},T=(t,s)=>s.render("pre",t.attrs||{},s.render("code",{},t.children||"")),R=(t,s=!1)=>({text:r,attrs:i},a)=>{const{class:u,id:f,...d}=i||{},b=s?{class:u,id:f,style:k(d)||void 0}:i||{};return a.render(t,p(b),r)},C=t=>y(t),_=t=>{const{marks:s,...r}=t;if("text"in t){if(s)return s.reduce((a,u)=>C({...u,text:a}),C({...r,children:r.children}));const i=t.attrs||{};if(O){const a=n.get("txt")||0;n.set("txt",a+1),i.key=`txt-${a}`}return L(r.text,i)}return""},D=(t,s)=>{const{linktype:r,href:i,anchor:a,...u}=t.attrs||{};let f="";switch(r){case v.ASSET:case v.URL:f=i;break;case v.EMAIL:f=`mailto:${i}`;break;case v.STORY:f=i,a&&(f=`${f}#${a}`);break;default:f=i;break}const d={...u};return f&&(d.href=f),s.render("a",d,t.text)},Y=(t,s)=>{var r,i;return console.warn("[StoryblokRichtText] - BLOK resolver is not available for vanilla usage"),s.render("span",{blok:(r=t==null?void 0:t.attrs)==null?void 0:r.body[0],id:(i=t.attrs)==null?void 0:i.id,style:"display: none"})},q=(t,s)=>{const r={},i=s.render("tbody",{},t.children);return s.render("table",r,i)},B=(t,s)=>{const r={};return s.render("tr",r,t.children)},M=(t,s)=>{const{colspan:r,rowspan:i,colwidth:a,backgroundColor:u,...f}=t.attrs||{},d={...f};r>1&&(d.colspan=r),i>1&&(d.rowspan=i);const b=[];return a&&b.push(`width: ${a}px;`),u&&b.push(`background-color: ${u};`),b.length>0&&(d.style=b.join(" ")),s.render("td",p(d),t.children)},W=(t,s)=>{const{colspan:r,rowspan:i,colwidth:a,backgroundColor:u,...f}=t.attrs||{},d={...f};r>1&&(d.colspan=r),i>1&&(d.rowspan=i);const b=[];return a&&b.push(`width: ${a}px;`),u&&b.push(`background-color: ${u};`),b.length>0&&(d.style=b.join(" ")),s.render("th",p(d),t.children)},P=new Map([[c.DOCUMENT,l("")],[c.HEADING,$],[c.PARAGRAPH,l("p")],[c.UL_LIST,l("ul")],[c.OL_LIST,l("ol")],[c.LIST_ITEM,l("li")],[c.IMAGE,S],[c.EMOJI,A],[c.CODE_BLOCK,T],[c.HR,l("hr")],[c.BR,l("br")],[c.QUOTE,l("blockquote")],[c.COMPONENT,Y],[x.TEXT,_],[h.LINK,D],[h.ANCHOR,D],[h.STYLED,R("span",!0)],[h.BOLD,R("strong")],[h.TEXT_STYLE,R("span",!0)],[h.ITALIC,R("em")],[h.UNDERLINE,R("u")],[h.STRIKE,R("s")],[h.CODE,R("code")],[h.SUPERSCRIPT,R("sup")],[h.SUBSCRIPT,R("sub")],[h.HIGHLIGHT,R("mark")],[c.TABLE,q],[c.TABLE_ROW,B],[c.TABLE_CELL,M],[c.TABLE_HEADER,W]]),U=new Map([...P,...Object.entries(g).map(([t,s])=>[t,s])]),X=()=>({render:(r,i={},a)=>{if(O&&r){const u=n.get(r)||0;n.set(r,u+1),i.key=`${r}-${u}`}return m(r,i,a)},originalResolvers:P,mergedResolvers:U});function j(t){const s=U.get(t.type);if(!s)return console.error("<Storyblok>",`No resolver found for node type ${t.type}`),"";const r=X();if(t.type==="text")return s(t,r);const i=t.content?t.content.map(y):void 0;return s({...t,children:i},r)}function y(t){return t.type==="doc"?I?t.content.map(j):t.content.map(j).join(""):Array.isArray(t)?t.map(j):j(t)}return{render:y}}E.BlockTypes=c,E.LinkTargets=N,E.LinkTypes=v,E.MarkTypes=h,E.TextTypes=x,E.richTextResolver=K,Object.defineProperty(E,Symbol.toStringTag,{value:"Module"})});