UNPKG

@d3plus/text

Version:

A smart SVG text box with line wrapping and automatic font size scaling.

237 lines 29.6 kB
/* @d3plus/text v3.0.6 A smart SVG text box with line wrapping and automatic font size scaling. Copyright (c) 2025 D3plus - https://d3plus.org @license MIT */ (t=>{"function"==typeof define&&define.amd?define(t):t()})(function(){if("undefined"!=typeof window){try{if("undefined"==typeof SVGElement||Boolean(SVGElement.prototype.innerHTML))return}catch(t){return}function r(t){switch(t.nodeType){case 1:var e=t,n="";return n+="<"+e.tagName,e.hasAttributes()&&[].forEach.call(e.attributes,function(t){n+=" "+t.name+'="'+t.value+'"'}),n+=">",e.hasChildNodes()&&[].forEach.call(e.childNodes,function(t){n+=r(t)}),n+="</"+e.tagName+">";case 3:return t.textContent.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");case 8:return"\x3c!--"+t.nodeValue+"--\x3e"}}Object.defineProperty(SVGElement.prototype,"innerHTML",{get:function(){var e="";return[].forEach.call(this.childNodes,function(t){e+=r(t)}),e},set:function(t){for(;this.firstChild;)this.removeChild(this.firstChild);try{var e=new DOMParser,n=(e.async=!1,"<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>"+t+"</svg>"),r=e.parseFromString(n,"text/xml").documentElement;[].forEach.call(r.childNodes,function(t){this.appendChild(this.ownerDocument.importNode(t,!0))}.bind(this))}catch(t){throw new Error("Error parsing markup string")}}}),Object.defineProperty(SVGElement.prototype,"innerSVG",{get:function(){return this.innerHTML},set:function(t){this.innerHTML=t}})}}),((t,e)=>{"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define("@d3plus/text",["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).d3plus={})})(this,function(t){ /** @const fontFamily @desc The default fallback font list used for all text labels as an Array of Strings. @returns {Array<string>} */var i,l,n,s,e,a; /** @const fontFamilyStringify @desc Converts an Array of font-family names into a CSS font-family string. @param {String|Array<string>} *family* @returns {String} */ /** @function stringify @desc Coerces value into a String. @param {String} value */function A(t){return void 0===t?t="undefined":"string"==typeof t||t instanceof String||(t=JSON.stringify(t)),t} // great unicode list: http://asecuritysite.com/coding/asc2 let o=[[/[\300-\305]/g,"A"],[/[\340-\345]/g,"a"],[/[\306]/g,"AE"],[/[\346]/g,"ae"],[/[\337]/g,"B"],[/[\307]/g,"C"],[/[\347]/g,"c"],[/[\320\336\376]/g,"D"],[/[\360]/g,"d"],[/[\310-\313]/g,"E"],[/[\350-\353]/g,"e"],[/[\314-\317]/g,"I"],[/[\354-\357]/g,"i"],[/[\321]/g,"N"],[/[\361]/g,"n"],[/[\u014c\322-\326\330]/g,"O"],[/[\u014d\362-\366\370]/g,"o"],[/[\u016a\331-\334]/g,"U"],[/[\u016b\371-\374]/g,"u"],[/[\327]/g,"x"],[/[\335]/g,"Y"],[/[\375\377]/g,"y"]]; /** @function strip @desc Removes all non ASCII characters from a string. @param {String} value @param {String} [spacer = "-"] */function r(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function u(){if(!l){l=1; /* build fixed length tree */for(var y=0,w=-3,A=new r,m=new r,o=new Uint8Array(30),u=new Uint16Array(30),f=new Uint8Array(30),c=new Uint16Array(30),P=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),L=new r,x=new Uint8Array(320),a=new Uint16Array(16), /* -------------------- * * -- initialization -- * * -------------------- */ /* build fixed huffman trees */t=A,e=m,n=0;n<7;++n)t.table[n]=0;for(t.table[7]=24,t.table[8]=152,t.table[9]=112,n=0;n<24;++n)t.trans[n]=256+n;for(n=0;n<144;++n)t.trans[24+n]=n;for(n=0;n<8;++n)t.trans[168+n]=280+n;for(n=0;n<112;++n)t.trans[176+n]=144+n; /* build fixed distance tree */for(n=0;n<5;++n)e.table[n]=0;for(e.table[5]=32,n=0;n<32;++n)e.trans[n]=n; /* build extra bits and base tables */s(o,u,4,3),s(f,c,2,1), /* fix a special case */o[28]=0,u[28]=258,i= /* inflate stream from source to dest */function(t,e){var n,r,s,i=new C(t,e);do{ /* decompress block */switch(s=void 0, /* check if tag is empty */(r=i).bitcount--||( /* load next tag */r.tag=r.source[r.sourceIndex++],r.bitcount=7) /* shift bit out of tag */,s=1&r.tag,r.tag>>>=1, /* read final block flag */r=s,X(i,2,0)){case 0: /* decompress uncompressed block */n=( /* inflate an uncompressed block of data */t=>{ /* unread from bitbuffer */for(var e,n;8<t.bitcount;)t.sourceIndex--,t.bitcount-=8; /* get length */ /* check length */if((e=256*t.source[t.sourceIndex+1]+t.source[t.sourceIndex])!==(65535&~(256*t.source[t.sourceIndex+3]+t.source[t.sourceIndex+2])))return w; /* copy block */for(t.sourceIndex+=4,n=e;n;--n)t.dest[t.destLen++]=t.source[t.sourceIndex++]; /* make sure we start next block on a byte boundary */return t.bitcount=0,y})(i);break;case 1: /* decompress block with fixed huffman trees */n=U(i,A,m);break;case 2:v=b=g=p=a=d=h=l=c=f=u=o=void 0;for( /* decompress block with dynamic huffman trees */var a,o=i,u=i.ltree,f=i.dtree, /* get 5 bits HLIT (257-286) */c=X(o,5,257), /* get 5 bits HDIST (1-32) */l=X(o,5,1), /* get 4 bits HCLEN (4-19) */h=X(o,4,4),d=0;d<19;++d)x[d]=0; /* read code lengths for code length alphabet */for(d=0;d<h;++d){ /* get 3 bits code length (0-7) */var g=X(o,3,0);x[P[d]]=g} /* build code length tree */ /* decode code lengths for the dynamic trees */for(z(L,x,0,19),a=0;a<c+l;){var b=H(o,L);switch(b){case 16:for( /* copy previous code length 3-6 times (read 2 bits) */var v=x[a-1],p=X(o,2,3);p;--p)x[a++]=v;break;case 17: /* repeat code length 0 for 3-10 times (read 3 bits) */for(p=X(o,3,3);p;--p)x[a++]=0;break;case 18: /* repeat code length 0 for 11-138 times (read 7 bits) */for(p=X(o,7,11);p;--p)x[a++]=0;break;default: /* values 0-15 represent the actual code lengths */x[a++]=b}} /* build dynamic trees */z(u,x,0,c),z(f,x,c,l),n=U(i,i.ltree,i.dtree);break;default:n=w}if(n!==y)throw new Error("Data error")}while(!r);return i.destLen<i.dest.length?"function"==typeof i.dest.slice?i.dest.slice(0,i.destLen):i.dest.subarray(0,i.destLen):i.dest}}return i;function r(){this.table=new Uint16Array(16),/* table of code length counts */ this.trans=new Uint16Array(288)}function C(t,e){this.source=t,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=e,this.destLen=0,this.ltree=new r,/* dynamic length/symbol tree */ this.dtree=new r} /* --------------------------------------------------- * * -- uninitialized global data (static structures) -- * * --------------------------------------------------- */ /* ----------------------- * * -- utility functions -- * * ----------------------- */ /* build extra bits and base tables */function s(t,e,n,r){ /* build bits table */for(var s,i=0;i<n;++i)t[i]=0;for(i=0;i<30-n;++i)t[i+n]=i/n|0; /* build base table */for(s=r,i=0;i<30;++i)e[i]=s,s+=1<<t[i]} /* build the fixed huffman trees */function z(t,e,n,r){ /* clear code length count table */for(var s,i=0;i<16;++i)t.table[i]=0; /* scan symbol lengths, and sum code length counts */for(i=0;i<r;++i)t.table[e[n+i]]++; /* compute offset table for distribution sort */for(i=s=t.table[0]=0;i<16;++i)a[i]=s,s+=t.table[i]; /* create code->symbol translation table (symbols sorted by code) */for(i=0;i<r;++i)e[n+i]&&(t.trans[a[e[n+i]]++]=i)} /* ---------------------- * * -- decode functions -- * * ---------------------- */ /* get one bit from source stream */ /* read a num bit value from a stream and add base */function X(t,e,n){if(!e)return n;for(;t.bitcount<24;)t.tag|=t.source[t.sourceIndex++]<<t.bitcount,t.bitcount+=8;var r=t.tag&65535>>>16-e;return t.tag>>>=e,t.bitcount-=e,r+n} /* given a data stream and a tree, decode a symbol */function H(t,e){for(;t.bitcount<24;)t.tag|=t.source[t.sourceIndex++]<<t.bitcount,t.bitcount+=8; /* get more bits while code value is above sum */for(var n=0,r=0,s=0,i=t.tag;r=2*r+(1&i),i>>>=1,n+=e.table[++s],0<=(r-=e.table[s]););return t.tag=i,t.bitcount-=s,e.trans[n+r]} /* given a data stream, decode dynamic trees from it */ /* ----------------------------- * * -- block inflate functions -- * * ----------------------------- */ /* given a stream and two trees, inflate a block of data */function U(t,e,n){for(;;){var r=H(t,e); /* check for end of block */if(256===r)return y;if(r<256)t.dest[t.destLen++]=r;else /* copy match */for(var s, /* possibly get more bits from length code */i=X(t,o[r-=257],u[r]),r=H(t,n),a= /* possibly get more bits from distance code */s=t.destLen-X(t,f[r],c[r]);a<s+i;++a)t.dest[t.destLen++]=t.dest[a]}}}function f(){if(!s){s=1;let e=18===new Uint8Array(new Uint32Array([305419896]).buffer)[0],r=(t,e,n)=>{var r=t[e];t[e]=t[n],t[n]=r};n={swap32LE:t=>{e&&(e=>{var n=e.length;for(let t=0;t<n;t+=4)r(e,t,t+3),r(e,t+1,t+2)})(t)}}}return n}var c,h,d,g,b,v,p,y,w,m=r((()=>{if(!a){a=1;let r=u(),s=f().swap32LE;e=class{get(t){let e;return t<0||1114111<t?this.errorValue:t<55296||56319<t&&t<=65535?( // Ordinary BMP code point, excluding leading surrogates. // BMP uses a single level lookup. BMP index starts at offset 0 in the index. // data is stored in the index array itself. e=(this.data[t>>5]<<2)+(31&t),this.data[e]):t<=65535?( // Lead Surrogate Code Point. A Separate index section is stored for // lead surrogate code units and code points. // The main index has the code unit data. // For this function, we need the code point data. e=(this.data[2048+(t-55296>>5)]<<2)+(31&t),this.data[e]):t<this.highStart?( // Supplemental code point, use two-level lookup. e=this.data[2080+(t>>11)],e=((e=this.data[e+(t>>5&63)])<<2)+(31&t),this.data[e]):this.data[this.data.length-4]}constructor(e){var n="function"==typeof e.readUInt32BE&&"function"==typeof e.slice;if(n||e instanceof Uint8Array){ // read binary format let t;e=n?(this.highStart=e.readUInt32LE(0),this.errorValue=e.readUInt32LE(4),t=e.readUInt32LE(8),e.slice(12)):(n=new DataView(e.buffer),this.highStart=n.getUint32(0,!0),this.errorValue=n.getUint32(4,!0),t=n.getUint32(8,!0),e.subarray(12)), // double inflate the actual trie data e=r(e,new Uint8Array(t)),e=r(e,new Uint8Array(t)), // swap bytes from little-endian s(e),this.data=new Uint32Array(e.buffer)}else // pre-parsed data ({data:this.data,highStart:this.highStart,errorValue:this.errorValue}=e)}}}return e})()),P={};function L(t){t=t.charCodeAt(0);return t===h||t===p?62:t===d||t===y?63:t<g?-1:t<g+10?t-g+26+26:t<v+26?t-v:t<b+26?t-b+26:void 0}S||(S=1,w="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",S=P,c="undefined"!=typeof Uint8Array?Uint8Array:Array,h="+".charCodeAt(0),d="/".charCodeAt(0),g="0".charCodeAt(0),b="a".charCodeAt(0),v="A".charCodeAt(0),p="-".charCodeAt(0),y="_".charCodeAt(0),S.toByteArray=function(t){var e,n;if(0<t.length%4)throw new Error("Invalid string. Length must be a multiple of 4"); // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice var r="="===t.charAt((r=t.length)-2)?2:"="===t.charAt(r-1)?1:0, // base64 is 4/3 + up to two characters of the original data s=new c(3*t.length/4-r), // if there are placeholders, only get up to the last complete 4 chars i=0<r?t.length-4:t.length,a=0;function o(t){s[a++]=t}for(e=0;e<i;e+=4,0)o((16711680&(n=L(t.charAt(e))<<18|L(t.charAt(e+1))<<12|L(t.charAt(e+2))<<6|L(t.charAt(e+3))))>>16),o((65280&n)>>8),o(255&n);return 2==r?o(255&(n=L(t.charAt(e))<<2|L(t.charAt(e+1))>>4)):1==r&&(o((n=L(t.charAt(e))<<10|L(t.charAt(e+1))<<4|L(t.charAt(e+2))>>2)>>8&255),o(255&n)),s},S.fromByteArray=function(t){var e,n,r,s,i=t.length%3,a="";function o(t){return w.charAt(t)} // go through the array every three bytes, we'll deal with trailing stuff later for(e=0,r=t.length-i;e<r;e+=3)n=(t[e]<<16)+(t[e+1]<<8)+t[e+2],a+=o((s=n)>>18&63)+o(s>>12&63)+o(s>>6&63)+o(63&s); // pad the end with zeros, but make sure to not forget the extra bytes switch(i){case 1:a=(a+=o((n=t[t.length-1])>>2))+o(n<<4&63)+"==";break;case 2:a=(a=(a+=o((n=(t[t.length-2]<<8)+t[t.length-1])>>10))+o(n>>4&63))+o(n<<2&63)+"="}return a});var x={};function C(t){switch(t){case 33:return 12;case 39:case 40:case 42:return 12;case 35:return 5;default:return t}}function z(t){switch(t){case 37:case 38:return 34;case 41:return 22;default:return t}}// Prohibited break let X=[ //OP , CL , CP , QU , GL , NS , EX , SY , IS , PR , PO , NU , AL , HL , ID , IN , HY , BA , BB , B2 , ZW , CM , WJ , H2 , H3 , JL , JV , JT , RI , EB , EM , ZWJ , CB [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,4,4,4,4,4,4,4,4,4,4,4],[0,4,4,1,1,4,4,4,4,1,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,1,4,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[4,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,1],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,1],[0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,0,1,0,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,0,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[1,4,4,1,1,1,4,4,4,0,0,1,1,1,1,1,1,1,0,0,4,2,4,1,1,1,1,1,0,1,1,1,0],[1,4,4,1,1,1,4,4,4,0,0,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,0,1,4,4,4,0,0,1,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,0,1,4,4,4,0,0,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,0],[0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,1,1,1,0,4,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,1,1,1,1,1,1,4,2,4,1,1,1,1,1,1,1,1,1,1],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,1,1,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,1,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,1,1,1,1,0,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,1,1,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,1,0,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,0,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,1,0,0,1,0],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,1,1,0],[0,4,4,1,1,1,4,4,4,0,1,0,0,0,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[1,4,4,1,1,1,4,4,4,1,1,1,1,1,0,1,1,1,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0],[0,4,4,1,1,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,4,2,4,0,0,0,0,0,0,0,0,1,0]],H=new m(r(P).toByteArray("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"));class U{constructor(t,e=!1){this.position=t,this.required=e}} /** @function textSplit @desc Splits a given sentence into an array of words. @param {String} sentence */function V(t){var e=new x(t);let n,r,s=[];for(;n=e.nextBreak();){var i=t.slice(r,n.position);s.push(i),r=n.position}return s} /** * Strips HTML and "un-escapes" escape characters. * @param {String} input */function W(t){var e;return""!==t.replace(/\s+/g,"")&&(e=(new DOMParser).parseFromString(t.replace(/<[^>]+>/g,""),"text/html")).documentElement?e.documentElement.textContent:t} /** @function textWidth @desc Given a text string, returns the predicted pixel width of the string when placed into DOM. @param {String|Array} text Can be either a single string or an array of strings to analyze. @param {Object} [style] An object of CSS font styles to apply. Accepts any of the valid [CSS font property](http://www.w3schools.com/cssref/pr_font_font.asp) values. */function N(t,e){e=Object.assign({"font-size":10,"font-family":"sans-serif","font-style":"normal","font-weight":400,"font-variant":"normal"},e);var n=document.createElement("canvas").getContext("2d"),r=[];return r.push(e["font-style"]),r.push(e["font-variant"]),r.push(e["font-weight"]),r.push("string"==typeof e["font-size"]?e["font-size"]:"".concat(e["font-size"],"px")),r.push(e["font-family"]),n.font=r.join(" "),e=t,(null!=(r=Array)&&"undefined"!=typeof Symbol&&r[Symbol.hasInstance]?r[Symbol.hasInstance](e):e instanceof r)?t.map(function(t){return n.measureText(W(t)).width}):n.measureText(W(t)).width} /** @function trim @desc Cross-browser implementation of [trim](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim). @param {String} str */ /** @function trimRight @desc Cross-browser implementation of [trimRight](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight). @param {String} str */function O(t){return t.toString().replace(/\s+$/,"")} /** @function textWrap @desc Based on the defined styles and dimensions, breaks a string into an array of strings for each line of text. */x=class{nextCodePoint(){var t=this.string.charCodeAt(this.pos++),e=this.string.charCodeAt(this.pos); // If a surrogate pair return 55296<=t&&t<=56319&&56320<=e&&e<=57343?(this.pos++,1024*(t-55296)+(e-56320)+65536):t}nextCharClass(){return C(H.get(this.nextCodePoint()))}getSimpleBreak(){ // handle classes not handled by the pair table switch(this.nextClass){case 41:return!1;case 34:case 37:case 38:return!(this.curClass=34);case 36:return!(this.curClass=36)}return null}getPairTableBreak(t){ // if not handled already, use the pair table let e=!1;switch(X[this.curClass][this.nextClass]){case 0:e=!0;break;case 1:e=41===t;break;case 2:if(e=41===t)break;return e=!1;case 3:if(41!==t)return e}return this.LB8a&&(e=!1), // Rule LB21a !this.LB21a||16!==this.curClass&&17!==this.curClass?this.LB21a=13===this.curClass:(e=!1,this.LB21a=!1), // Rule LB30a 28===this.curClass?(this.LB30a++,2==this.LB30a&&28===this.nextClass&&(e=!0,this.LB30a=0)):this.LB30a=0,this.curClass=this.nextClass,e}nextBreak(){ // get the first char if we're at the beginning of the string var t;for(null==this.curClass&&(t=this.nextCharClass(),this.curClass=z(t),this.nextClass=t,this.LB8a=31===t,this.LB30a=0);this.pos<this.string.length;){this.lastPos=this.pos;var e=this.nextClass; // explicit newline if(this.nextClass=this.nextCharClass(),34===this.curClass||36===this.curClass&&37!==this.nextClass)return this.curClass=z(C(this.nextClass)),new U(this.lastPos,!0);let t=this.getSimpleBreak();if(null===t&&(t=this.getPairTableBreak(e)), // Rule LB8a this.LB8a=31===this.nextClass,t)return new U(this.lastPos)}return this.lastPos<this.string.length?(this.lastPos=this.string.length,new U(this.string.length)):null}constructor(t){this.string=t,this.pos=0,this.lastPos=0,this.curClass=null,this.nextClass=null,this.LB8a=!1,this.LB21a=!1,this.LB30a=0}};let B=["a","an","and","as","at","but","by","for","from","if","in","into","near","nor","of","on","onto","or","per","that","the","to","with","via","vs","vs."];var S=["CEO","CFO","CNC","COO","CPU","GDP","HVAC","ID","IT","R&D","TV","UI"];let T=S.reduce((t,e)=>(t.push(e+"s"),t),S.map(t=>t.toLowerCase())); /** @function titleCase @desc Capitalizes the first letter of each word in a phrase/sentence, accounting for words in English that should be kept lowercase such as "and" or "of", as well as acronym that should be kept uppercase such as "CEO" or "TVs". @param {String} str The string to apply the title case logic. */t.fontFamily=["Inter","Helvetica Neue","HelveticaNeue","Helvetica","Arial","sans-serif"],t.fontFamilyStringify=t=>("string"==typeof t?[t]:t).map(t=>t.match(/^[a-z-_]{1,}$/)?t:`'${t}'`).join(", "),t.stringify=A,t.strip=function(t,r="-"){return(""+t).replace(/[^A-Za-z0-9\-_\u0621-\u064A]/g,e=>{if(" "===e)return r;let n=!1;for(let t=0;t<o.length;t++)if(new RegExp(o[t][0]).test(e)){n=o[t][1];break}return n||""})},t.textSplit=V,t.textWrap=function(){let l="sans-serif",h=10,d=400,g=200,b,v=null,p=!1,y=V,w=200; /** The inner return object and wraps the text and returns the line data array. @private */function e(t){t=A(t),void 0===b&&(b=Math.ceil(1.4*h));var e=y(t),n={"font-family":l,"font-size":h,"font-weight":d,"line-height":b};let r=1,s="",i=!1,a=0;var o=[],u=N(e,n);for(let t=0;t<e.length;t++){var f=e[t],c=u[e.indexOf(f)]; // newline if breaking character or not enough width if("\n"===s.slice(-1)||a+c>w){if(!t&&!p){i=!0;break}if(o.length>=r&&(o[r-1]=O(o[r-1])),r++,b*r>g||c>w&&!p||v&&r>v){i=!0;break}a=0,o.push(f)}else t?o[r-1]+=f:o[0]=f;s+=f,a+=c}return{lines:o,sentence:t,truncated:i,widths:N(o,n),words:e}} /** @memberof textWrap @desc If *value* is specified, sets the font family accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current font family. @param {Function|String} [*value* = "sans-serif"] */return e.fontFamily=function(t){return arguments.length?(l=t,e):l}, /** @memberof textWrap @desc If *value* is specified, sets the font size accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current font size. @param {Function|Number} [*value* = 10] */e.fontSize=function(t){return arguments.length?(h=t,e):h}, /** @memberof textWrap @desc If *value* is specified, sets the font weight accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current font weight. @param {Function|Number|String} [*value* = 400] */e.fontWeight=function(t){return arguments.length?(d=t,e):d}, /** @memberof textWrap @desc If *value* is specified, sets height limit to the specified value and returns this generator. If *value* is not specified, returns the current value. @param {Number} [*value* = 200] */e.height=function(t){return arguments.length?(g=t,e):g}, /** @memberof textWrap @desc If *value* is specified, sets the line height accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current line height accessor, which is 1.1 times the [font size](#textWrap.fontSize) by default. @param {Function|Number} [*value*] */e.lineHeight=function(t){return arguments.length?(b=t,e):b}, /** @memberof textWrap @desc If *value* is specified, sets the maximum number of lines allowed when wrapping. @param {Function|Number} [*value*] */e.maxLines=function(t){return arguments.length?(v=t,e):v}, /** @memberof textWrap @desc If *value* is specified, sets the overflow to the specified boolean and returns this generator. If *value* is not specified, returns the current overflow value. @param {Boolean} [*value* = false] */e.overflow=function(t){return arguments.length?(p=t,e):p}, /** @memberof textWrap @desc If *value* is specified, sets the word split function to the specified function and returns this generator. If *value* is not specified, returns the current word split function. @param {Function} [*value*] A function that, when passed a string, is expected to return that string split into an array of words to textWrap. The default split function splits strings on the following characters: `-`, `/`, `;`, `:`, `&` */e.split=function(t){return arguments.length?(y=t,e):y}, /** @memberof textWrap @desc If *value* is specified, sets width limit to the specified value and returns this generator. If *value* is not specified, returns the current value. @param {Number} [*value* = 200] */e.width=function(t){return arguments.length?(w=t,e):w},e},t.titleCase=function(t){return void 0===t?"":V(t).reduce((t,e,n)=>{let r=e;var s=e.toLowerCase().slice(0,-1),n=T.includes(s)||B.includes(s)&&0!==n&&e.toLowerCase()!==s;return t+(r=n?r:e.charAt(0).toUpperCase()+e.slice(1))},"")},t.trim=function(t){return t.toString().replace(/^\s+|\s+$/g,"")} /** @function trimLeft @desc Cross-browser implementation of [trimLeft](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimLeft). @param {String} str */,t.trimLeft=function(t){return t.toString().replace(/^\s+/,"")},t.trimRight=O}); //# sourceMappingURL=d3plus-text.full.js.map