UNPKG

@sutton-signwriting/core

Version:

a javascript package for node and browsers that supports general processing of the Sutton SignWriting script

3 lines (2 loc) 9.58 kB
/* Sutton SignWriting Core Module v2.0.0 (https://github.com/sutton-signwriting/core), author: Steve Slevinski (https://SteveSlevinski.me), license: MIT */ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).ssw=e.ssw||{},e.ssw.fsw={}))}(this,(function(e){"use strict";let t={null:"S00000",symbol:"S[123][0-9a-f]{2}[0-5][0-9a-f]",coord:"[0-9]{3}x[0-9]{3}",sort:"A",box:"[BLMR]"};t.nullorsymbol=`(?:${t.null}|${t.symbol})`,t.prefix=`(?:${t.sort}${t.nullorsymbol}+)`,t.spatial=`${t.symbol}${t.coord}`,t.signbox=`${t.box}${t.coord}(?:${t.spatial})*`,t.sign=`${t.prefix}?${t.signbox}`,t.sortable=`${t.prefix}${t.signbox}`;let o={colorize:"C",colorhex:"(?:[0-9a-fA-F]{3}){1,2}",colorname:"[a-zA-Z]+",padding:"P[0-9]{2}",zoom:"Z(?:[0-9]+(?:\\.[0-9]+)?|x)",classbase:"-?[_a-zA-Z][_a-zA-Z0-9-]{0,100}",id:"[a-zA-Z][_a-zA-Z0-9-]{0,100}"};o.colorbase=`(?:${o.colorhex}|${o.colorname})`,o.color=`_${o.colorbase}_`,o.colors=`_${o.colorbase}(?:,${o.colorbase})?_`,o.background=`G${o.color}`,o.detail=`D${o.colors}`,o.detailsym=`D[0-9]{2}${o.colors}`,o.classes=`${o.classbase}(?: ${o.classbase})*`,o.full=`-(${o.colorize})?(${o.padding})?(${o.background})?(${o.detail})?(${o.zoom})?(?:-((?:${o.detailsym})*))?(?:-(${o.classes})?!(?:(${o.id})!)?)?`;const n=e=>(new RegExp(`^${o.colorhex}$`).test(e)?"#":"")+e,s=e=>{const t=`^${o.full}`,s=("string"==typeof e?e.match(new RegExp(t)):[])||[];return a={colorize:s[1]?!!s[1]:void 0,padding:s[2]?parseInt(s[2].slice(1)):void 0,background:s[3]?n(s[3].slice(2,-1)):void 0,detail:s[4]?s[4].slice(2,-1).split(",").map(n):void 0,zoom:s[5]?"Zx"===s[5]?"x":parseFloat(s[5].slice(1)):void 0,detailsym:s[6]?s[6].match(new RegExp(o.detailsym,"g")).map((e=>{const t=e.split("_"),o=t[1].split(",").map(n);return{index:parseInt(t[0].slice(1)),detail:o}})):void 0,classes:s[7]?s[7]:void 0,id:s[8]?s[8]:void 0},Object.fromEntries(Object.entries(a).filter((([e,t])=>void 0!==t)));var a},a=e=>e.split("x").map((e=>parseInt(e))),l={symbol:e=>{const n=`^(${t.symbol})(${t.coord})?(${o.full})?`,s="string"==typeof e?e.match(new RegExp(n)):void 0;return{symbol:s?s[1]:void 0,coord:s&&s[2]?a(s[2]):void 0,style:s?s[3]:void 0}},sign:e=>{const n=`^(${t.prefix})?(${t.signbox})(${o.full})?`,s="string"==typeof e?e.match(new RegExp(n)):void 0;return s?{sequence:s[1]?s[1].slice(1).match(/.{6}/g):void 0,box:s[2][0],max:a(s[2].slice(1,8)),spatials:s[2].length<9?void 0:s[2].slice(8).match(/(.{13})/g).map((e=>({symbol:e.slice(0,6),coord:[parseInt(e.slice(6,9)),parseInt(e.slice(10,13))]}))),style:s[3]}:{}},text:e=>{if("string"!=typeof e)return[];const n=`(${t.sign}(${o.full})?|${t.spatial}(${o.full})?)`,s=e.match(new RegExp(n,"g"));return s?[...s]:[]}},i={symbol:e=>{if("string"==typeof e.symbol){const n=(e.symbol.match(t.symbol)||[""])[0];if(n){return n+((((e.coord&&e.coord[0]||"").toString()+"x"+(e.coord&&e.coord[1]||"").toString()).match(t.coord)||[""])[0]||"")+("string"==typeof e.style&&(e.style.match(o.full)||[""])[0]||"")}}},sign:e=>{let n="string"!=typeof e.box?"M":(e.box+"M").match(t.box);const s=(((e.max&&e.max[0]||"").toString()+"x"+(e.max&&e.max[1]||"").toString()).match(t.coord)||[""])[0]||"";if(!s)return;let a="";e.sequence&&Array.isArray(e.sequence)&&(a=e.sequence.map((e=>(e.match(t.nullorsymbol)||[""])[0])).join(""),a=a?"A"+a:"");let l="";e.spatials&&Array.isArray(e.spatials)&&(l=e.spatials.map((e=>{if("string"==typeof e.symbol){const o=(e.symbol.match(t.symbol)||[""])[0];if(o){const n=(((e.coord&&e.coord[0]||"").toString()+"x"+(e.coord&&e.coord[1]||"").toString()).match(t.coord)||[""])[0]||"";if(n)return o+n}}return""})).join(""));return a+n+s+l+("string"==typeof e.style&&(e.style.match(o.full)||[""])[0]||"")}},r=e=>{let t,o,n,a,i,r,c,d,p=l.sign(e);p.spatials?(a=Math.min(...p.spatials.map((e=>e.coord[0]))),i=p.max[0],t=i-a,r=Math.min(...p.spatials.map((e=>e.coord[1]))),c=p.max[1],o=c-r,n="sign",d=p.box):(p=l.symbol(e),d="M",p.coord?(a=p.coord[0],t=2*(500-a),r=p.coord[1],o=2*(500-r),n="symbol"):(a=490,t=20,r=490,o=20,n="none"));let m=s(p.style),u=m.zoom||1,g=m.padding||0;return{minX:a,minY:r,width:t,height:o,segment:n,lane:{B:0,L:-1,M:0,R:1}[d],padding:g,zoom:u}},c=[{index:0,name:"UNK",value:"[UNK]"},{index:1,name:"PAD",value:"[PAD]"},{index:2,name:"CLS",value:"[CLS]"},{index:3,name:"SEP",value:"[SEP]"}],d=(e,{sequence:t=!0,signbox:o=!0,sep:n="[SEP]"}={})=>{const s=e=>[e.slice(0,4),`c${e.charAt(4)}`,`r${e.charAt(5)}`],a=e=>e.map((e=>`p${e}`));return l.text(e).map((e=>{if(/[BLMR]/.test(e)){const i=l.sign(e),r=[];return i.sequence&&t&&r.push("A",...i.sequence.map((e=>s(e))).flat()),o&&r.push(i.box,...a(i.max),...i.spatials.flatMap((e=>[...s(e.symbol),...a(e.coord)]))),n?[...r,n]:r}{const i=l.symbol(e);if(!o&&!t)return[];let r=[];return r=!o&&t?["A",...s(i.symbol)]:["M",...a(i.coord.map((e=>1e3-e))),...s(i.symbol),...a(i.coord)],r.length>0&&n?[...r,n]:r}})).flatMap((e=>e))},p=(e,t=c)=>{const o=new Set(t.map((e=>e.value)));return e.filter((e=>!o.has(e))).join(" ").replace(/\bp(\d{3})\s+p(\d{3})/g,"$1x$2").replace(/ c(\d)\d? r(.)/g,"$1$2").replace(/ c(\d)\d?/g,"$10").replace(/ r(.)/g,"0$1").replace(/ /g,"").replace(/(\d)([BLMR])/g,"$1 $2").replace(/(\d)(AS)/g,"$1 $2").replace(/(A(?:S00000|S[123][0-9a-f]{2}[0-5][0-9a-f])+)( )([BLMR])/g,"$1$3")},m={height:500,width:150,offset:50,pad:20,margin:5,dynamic:!1,background:void 0,punctuation:{spacing:!0,pad:30,pull:!0},style:{detail:["black","white"],zoom:1}},u=e=>("object"!=typeof e&&(e={}),{...m,...e,punctuation:{...m.punctuation,...e.punctuation},style:{...m.style,...e.style}}),g=[256,517,759,767,877,895,903],f={all:[256,907],writing:[256,894],hand:[256,516],movement:[517,758],dynamic:[759,766],head:[767,876],hcenter:[767,876],vcenter:[767,885],trunk:[877,885],limb:[886,894],location:[895,902],punctuation:[903,907]},y=["#0000CC","#CC0000","#FF0099","#006600","#000000","#884411","#FF9900"];e.category=g,e.colorize=e=>{const t=l.symbol(e);let o="#000000";if(t.symbol){const e=parseInt(t.symbol.slice(1,4),16),n=g.findIndex((t=>t>e));o=y[n<0?6:n-1]}return o},e.colors=y,e.columnDefaults=m,e.columnDefaultsMerge=u,e.columns=(e,t)=>{if("string"!=typeof e)return{};const o=u(t);let n=l.text(e),s=0,a=[],i=[],c=0,d=parseInt(o.width/2),p=o.height-o.margin,m=!0,g=!1;for(let e of n){let t=r(e);s+=c,o.punctuation.spacing?s+="sign"==t.segment?o.pad:0:s+=o.pad,g=s+t.height>p,g&&"symbol"==t.segment&&o.punctuation.pull&&m&&(g=!1,m=!1),0==i.length&&(g=!1),g&&(s=o.pad,a.push(i),i=[],m=!0),i.push(Object.assign(t,{x:d+o.offset*t.lane-(500-t.minX)*t.zoom*o.style.zoom,y:s,text:e})),s+=t.height*t.zoom*o.style.zoom,c=o.punctuation.spacing?"sign"==t.segment?o.pad:o.punctuation.pad:o.pad}if(i.length&&a.push(i),o.punctuation.pull)for(let e of a){let t=e[e.length-1],n=t.y+t.height-(o.height-o.margin);if(n>0){let t=parseInt(n/e.length)+1;for(let o in e)e[o].y-=t*o+t}}let f=[];for(let e of a){let t=[d-o.offset-o.pad],n=[d+o.offset+o.pad];for(let s of e)t.push(s.x-o.pad),n.push(s.x+s.width+o.pad);t=Math.min(...t),n=Math.max(...n);let s=o.width,a=0;o.dynamic?(s=n-t,a=-t):a=d-parseInt((t+n)/2);for(let t of e)t.x+=a;f.push(s)}return{options:o,widths:f,columns:a}},e.compose=i,e.createTokenizer=(e=c,t=null)=>{const o=(e=>{const t={},o={},n={},s=new Set;return e.forEach((e=>{if(s.has(e.index))throw new Error(`Duplicate token index: ${e.index}`);s.add(e.index),t[e.index]=e,o[e.name]=e,n[e.value]=e})),{byIndex:t,byName:o,byValue:n,getByIndex:o=>t[o]||t[e.find((e=>"UNK"===e.name)).index],getByName:e=>o[e]||o.UNK,getByValue:e=>n[e]||o.UNK,getAllValues:()=>e.map((e=>e.value)),getAllIndices:()=>e.map((e=>e.index))}})(e),n=t??(o.getAllIndices().length>0?Math.max(...o.getAllIndices())+1:0),s=(()=>{const e=(e,t)=>Array.from({length:t-e},((t,o)=>e+o)),t=(t,o)=>e(t,o+1).map((e=>e.toString(16)));return["A","B","L","M","R","S000",...e(256,908).map((e=>`S${e.toString(16)}`)),...t(0,15).map((e=>`r${e}`)),...t(0,5).map((e=>`c${e}`)),...e(250,750).map((e=>`p${e}`))]})(),{i2s:a,s2i:l}=((e,t,o)=>{const n={},s={};return Object.values(t.byIndex).forEach((e=>{n[e.index]=e.value,s[e.value]=e.index})),e.forEach(((e,t)=>{const a=o+t;n[a]=e,s[e]=a})),{i2s:n,s2i:s}})(s,o,n),i={i2s:a,s2i:l,specialTokens:o,length:Object.keys(a).length,vocab:()=>Object.values(a),encodeTokens:e=>e.map((e=>void 0!==l[e]?l[e]:o.getByValue(e).index)),decodeTokens:e=>e.map((e=>a[e]||o.getByName("UNK").value)),encode:(e,t={})=>{const n=d(e,{...t,sep:o.getByName("SEP").value});return i.encodeTokens(n)},decode:t=>{if(0===t.length)return"";if(Array.isArray(t[0])){const o=t.map((e=>i.decodeTokens(e)));return p(o.flat(),e)}const o=i.decodeTokens(t);return p(o,e)},chunk:(e,t)=>((e,t,{cls:o="[CLS]",sep:n="[SEP]",pad:s="[PAD]"}={})=>{if(t<60)throw new Error("Chunk size must be at least 60 tokens to accommodate a typical sign");const a=[];let l=[],i=0;for(;i<e.length;){for(l=[o];i<e.length;){e[i];let o=i;for(;o<e.length&&e[o]!==n;)o++;const s=o-i+1;if(l.length+s>t-1)break;for(;i<=o;)l.push(e[i]),i++}for(;l.length<t;)l.push(s);a.push(l)}return a})(e,t,{cls:o.getByName("CLS").value,sep:o.getByName("SEP").value,pad:o.getByName("PAD").value})};return i},e.detokenize=p,e.group=[256,270,286,324,332,390,420,442,461,501,517,534,554,597,613,648,678,695,725,739,759,767,778,810,827,857,877,886,895,903],e.info=r,e.isType=(e,t)=>{const o=l.symbol(e);if(o.symbol){const e=parseInt(o.symbol.slice(1,4),16),n=f[t];if(n)return n[0]<=e&&n[1]>=e}return!1},e.kind=[256,895,903],e.parse=l,e.ranges=f,e.re=t,e.tokenize=d,Object.defineProperty(e,"__esModule",{value:!0})}));