@mlightcad/mtext-parser
Version:
AutoCAD MText parser written in TypeScript
4 lines (3 loc) • 15.6 kB
JavaScript
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});var _=(s=>(s[s.NONE=0]="NONE",s[s.WORD=1]="WORD",s[s.STACK=2]="STACK",s[s.SPACE=3]="SPACE",s[s.NBSP=4]="NBSP",s[s.TABULATOR=5]="TABULATOR",s[s.NEW_PARAGRAPH=6]="NEW_PARAGRAPH",s[s.NEW_COLUMN=7]="NEW_COLUMN",s[s.WRAP_AT_DIMLINE=8]="WRAP_AT_DIMLINE",s[s.PROPERTIES_CHANGED=9]="PROPERTIES_CHANGED",s))(_||{}),S=(s=>(s[s.BOTTOM=0]="BOTTOM",s[s.MIDDLE=1]="MIDDLE",s[s.TOP=2]="TOP",s))(S||{}),F=(s=>(s[s.DEFAULT=0]="DEFAULT",s[s.LEFT=1]="LEFT",s[s.RIGHT=2]="RIGHT",s[s.CENTER=3]="CENTER",s[s.JUSTIFIED=4]="JUSTIFIED",s[s.DISTRIBUTED=5]="DISTRIBUTED",s))(F||{}),E=(s=>(s[s.NONE=0]="NONE",s[s.UNDERLINE=1]="UNDERLINE",s[s.OVERLINE=2]="OVERLINE",s[s.STRIKE_THROUGH=4]="STRIKE_THROUGH",s))(E||{});const v={c:"Ø",d:"°",p:"±"},y={l:1,r:2,c:3,j:4,d:5};function O(s){const[t,e,r]=s;return r<<16|e<<8|t}function I(s){const t=s&255,e=s>>8&255,r=s>>16&255;return[t,e,r]}function N(s){return s.replace(/\r\n|\r|\n/g,"\\P")}function x(s){return s.replace(/\\P/g,"").replace(/\\~/g,"").includes("\\")}function T(s,t=!1){const e=new Set,r=/\\[fF](.*?)[;|]/g;return[...s.matchAll(r)].forEach(a=>{let l=a[1].toLowerCase();t&&(l=l.replace(/\.(ttf|otf|woff|shx)$/,"")),e.add(l)}),e}class P{constructor(t){this.stack=[],this.stack.push(t)}push(t){this.stack.push(t)}pop(){if(this.stack.length<=1)return;const t=this.stack.pop(),e=this.stack[this.stack.length-1];return JSON.stringify(e.paragraph)!==JSON.stringify(t.paragraph)&&(e.paragraph={...t.paragraph}),t}get current(){return this.stack[this.stack.length-1]}get depth(){return this.stack.length-1}get root(){return this.stack[0]}setCurrent(t){this.stack[this.stack.length-1]=t}}class w{constructor(t,e,r={}){this.continueStroke=!1,this.inStackContext=!1,this.scanner=new f(t);const a=e??new b;this.ctxStack=new P(a),this.yieldPropertyCommands=r.yieldPropertyCommands??!1,this.resetParagraphParameters=r.resetParagraphParameters??!1}decodeMultiByteChar(t){try{const e=new Uint8Array([parseInt(t.substr(0,2),16),parseInt(t.substr(2,2),16)]),a=new TextDecoder("gbk").decode(e);if(a!=="▯")return a;const i=new TextDecoder("big5").decode(e);return i!=="▯"?i:"▯"}catch{return"▯"}}pushCtx(){this.ctxStack.push(this.ctxStack.current)}popCtx(){this.ctxStack.pop()}parseStacking(){const t=new f(this.extractExpression(!0));let e="",r="",a="";const l=()=>{let c=t.peek(),n=!1;return c.charCodeAt(0)<32&&(c=" "),c==="\\"&&(n=!0,t.consume(1),c=t.peek()),t.consume(1),[c,n]},i=()=>{let c="";for(;t.hasData;){const[n,p]=l();if(!p&&(n==="/"||n==="#"||n==="^"))return[c,n];c+=n}return[c,""]},u=c=>{let n="",p=c;for(;t.hasData;){const[h,o]=l();if(!(p&&h===" ")){if(p=!1,!o&&h===";")break;n+=h}}return n};return[e,a]=i(),a&&(r=u(a==="^")),e===""&&r.includes("I/")?[2,[" "," ","/"]]:a==="^"?[2,[e,r,"^"]]:[2,[e,r,a]]}parseProperties(t){const e=this.ctxStack.current.copy(),r=this.ctxStack.current.copy();switch(t){case"L":r.underline=!0,this.continueStroke=!0;break;case"l":r.underline=!1,r.hasAnyStroke||(this.continueStroke=!1);break;case"O":r.overline=!0,this.continueStroke=!0;break;case"o":r.overline=!1,r.hasAnyStroke||(this.continueStroke=!1);break;case"K":r.strikeThrough=!0,this.continueStroke=!0;break;case"k":r.strikeThrough=!1,r.hasAnyStroke||(this.continueStroke=!1);break;case"A":this.parseAlign(r);break;case"C":this.parseAciColor(r);break;case"c":this.parseRgbColor(r);break;case"H":this.parseHeight(r);break;case"W":this.parseWidth(r);break;case"Q":this.parseOblique(r);break;case"T":this.parseCharTracking(r);break;case"p":this.parseParagraphProperties(r);break;case"f":case"F":this.parseFontProperties(r);break;default:throw new Error(`Unknown command: ${t}`)}if(this.continueStroke=r.hasAnyStroke,r.continueStroke=this.continueStroke,this.ctxStack.setCurrent(r),this.yieldPropertyCommands){const a=this.getPropertyChanges(e,r);if(Object.keys(a).length>0)return{command:t,changes:a,depth:this.ctxStack.depth}}}getPropertyChanges(t,e){const r={};if(t.underline!==e.underline&&(r.underline=e.underline),t.overline!==e.overline&&(r.overline=e.overline),t.strikeThrough!==e.strikeThrough&&(r.strikeThrough=e.strikeThrough),t.color.aci!==e.color.aci&&(r.aci=e.color.aci),t.color.rgbValue!==e.color.rgbValue&&(r.rgb=e.color.rgb),t.align!==e.align&&(r.align=e.align),JSON.stringify(t.fontFace)!==JSON.stringify(e.fontFace)&&(r.fontFace=e.fontFace),(t.capHeight.value!==e.capHeight.value||t.capHeight.isRelative!==e.capHeight.isRelative)&&(r.capHeight=e.capHeight),(t.widthFactor.value!==e.widthFactor.value||t.widthFactor.isRelative!==e.widthFactor.isRelative)&&(r.widthFactor=e.widthFactor),(t.charTrackingFactor.value!==e.charTrackingFactor.value||t.charTrackingFactor.isRelative!==e.charTrackingFactor.isRelative)&&(r.charTrackingFactor=e.charTrackingFactor),t.oblique!==e.oblique&&(r.oblique=e.oblique),JSON.stringify(t.paragraph)!==JSON.stringify(e.paragraph)){const a={};t.paragraph.indent!==e.paragraph.indent&&(a.indent=e.paragraph.indent),t.paragraph.align!==e.paragraph.align&&(a.align=e.paragraph.align),t.paragraph.left!==e.paragraph.left&&(a.left=e.paragraph.left),t.paragraph.right!==e.paragraph.right&&(a.right=e.paragraph.right),JSON.stringify(t.paragraph.tabs)!==JSON.stringify(e.paragraph.tabs)&&(a.tabs=e.paragraph.tabs),Object.keys(a).length>0&&(r.paragraph=a)}return r}parseAlign(t){const e=this.scanner.get();"012".includes(e)?t.align=parseInt(e):t.align=0,this.consumeOptionalTerminator()}parseHeight(t){const e=this.extractFloatExpression(!0);if(e)try{e.endsWith("x")?t.capHeight={value:parseFloat(e.slice(0,-1)),isRelative:!0}:t.capHeight={value:parseFloat(e),isRelative:!1}}catch{this.scanner.consume(-e.length);return}this.consumeOptionalTerminator()}parseWidth(t){const e=this.extractFloatExpression(!0);if(e)try{e.endsWith("x")?t.widthFactor={value:parseFloat(e.slice(0,-1)),isRelative:!0}:t.widthFactor={value:parseFloat(e),isRelative:!1}}catch{this.scanner.consume(-e.length);return}this.consumeOptionalTerminator()}parseCharTracking(t){const e=this.extractFloatExpression(!0);if(e)try{e.endsWith("x")?t.charTrackingFactor={value:Math.abs(parseFloat(e.slice(0,-1))),isRelative:!0}:t.charTrackingFactor={value:Math.abs(parseFloat(e)),isRelative:!1}}catch{this.scanner.consume(-e.length);return}this.consumeOptionalTerminator()}parseFloatValueOrFactor(t){const e=this.extractFloatExpression(!0);if(e)if(e.endsWith("x")){const r=parseFloat(e.slice(0,-1));t*=r}else t=parseFloat(e);return t}parseOblique(t){const e=this.extractFloatExpression(!1);e&&(t.oblique=parseFloat(e)),this.consumeOptionalTerminator()}parseAciColor(t){const e=this.extractIntExpression();if(e){const r=parseInt(e);r<257&&(t.color.aci=r)}this.consumeOptionalTerminator()}parseRgbColor(t){const e=this.extractIntExpression();if(e){const r=parseInt(e)&16777215;t.color.rgbValue=r}this.consumeOptionalTerminator()}extractFloatExpression(t=!1){const e=t?/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?x?/:/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/,r=this.scanner.tail.match(e);if(r){const a=r[0];return this.scanner.consume(a.length),a}return""}extractIntExpression(){const t=this.scanner.tail.match(/^\d+/);if(t){const e=t[0];return this.scanner.consume(e.length),e}return""}extractExpression(t=!1){const e=this.scanner.find(";",t);if(e<0){const i=this.scanner.tail;return this.scanner.consume(i.length),i}const a=this.scanner.peek(e-this.scanner.currentIndex-1)==="\\",l=this.scanner.tail.slice(0,e-this.scanner.currentIndex+(a?1:0));return this.scanner.consume(l.length+1),l}parseFontProperties(t){const e=this.extractExpression().split("|");if(e.length>0&&e[0]){const r=e[0];let a="Regular",l=400;for(const i of e.slice(1))i.startsWith("b1")?l=700:i==="i"||i.startsWith("i1")?a="Italic":(i==="i0"||i.startsWith("i0"))&&(a="Regular");t.fontFace={family:r,style:a,weight:l}}}parseParagraphProperties(t){const e=new f(this.extractExpression());let r=t.paragraph.indent,a=t.paragraph.left,l=t.paragraph.right,i=t.paragraph.align,u=[];const c=()=>{const n=e.tail.match(/^[+-]?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/);if(n){const p=parseFloat(n[0]);for(e.consume(n[0].length);e.peek()===",";)e.consume(1);return p}return 0};for(;e.hasData;)switch(e.get()){case"i":r=c();break;case"l":a=c();break;case"r":l=c();break;case"x":break;case"q":{const p=e.get();for(i=y[p]||0;e.peek()===",";)e.consume(1);break}case"t":for(u=[];e.hasData;){const p=e.peek();if(p==="r"||p==="c"){e.consume(1);const h=c();u.push(p+h.toString())}else{const h=c();isNaN(h)?e.consume(1):u.push(h)}}break}t.paragraph={indent:r,left:a,right:l,align:i,tabs:u}}consumeOptionalTerminator(){this.scanner.peek()===";"&&this.scanner.consume(1)}*parse(){let r=null;function a(i){const u={...i.paragraph};i.paragraph={indent:0,left:0,right:0,align:0,tabs:[]};const c={};return u.indent!==0&&(c.indent=0),u.left!==0&&(c.left=0),u.right!==0&&(c.right=0),u.align!==0&&(c.align=0),JSON.stringify(u.tabs)!==JSON.stringify([])&&(c.tabs=[]),c}const l=()=>{var u;let i="";for(;this.scanner.hasData;){let c=!1,n=this.scanner.peek();const p=this.scanner.currentIndex;if(n.charCodeAt(0)<32){if(this.scanner.consume(1),n===" ")return[5,null];if(n===`
`)return[6,null];n=" "}if(n==="\\")if("\\{}".includes(this.scanner.peek(1)))c=!0,this.scanner.consume(1),n=this.scanner.peek();else{if(i)return[1,i];this.scanner.consume(1);const h=this.scanner.get();switch(h){case"~":return[4,null];case"P":return[6,null];case"N":return[7,null];case"X":return[8,null];case"S":{this.inStackContext=!0;const o=this.parseStacking();return this.inStackContext=!1,o}case"m":case"M":if(this.scanner.peek()==="+"){this.scanner.consume(1);const o=(u=this.scanner.tail.match(/^[0-9A-Fa-f]{4}/))==null?void 0:u[0];if(o){this.scanner.consume(4);const g=this.decodeMultiByteChar(o);return i?[1,i]:[1,g]}this.scanner.consume(-1)}i+="\\M";continue;case"U":if(this.scanner.peek()==="+"){this.scanner.consume(1);const o=this.scanner.tail.match(/^[0-9A-Fa-f]{4,8}/);if(o){const g=o[0];this.scanner.consume(g.length);const R=parseInt(g,16);let m="";try{m=String.fromCodePoint(R)}catch{m="▯"}return i?[1,i]:[1,m]}this.scanner.consume(-1)}i+="\\U";continue;default:if(h)try{const o=this.parseProperties(h);if(this.yieldPropertyCommands&&o)return[9,o];continue}catch{const o=this.scanner.tail.slice(p,this.scanner.currentIndex);i+=o}}continue}if(n==="%"&&this.scanner.peek(1)==="%"){const h=this.scanner.peek(2).toLowerCase(),o=v[h];if(o){this.scanner.consume(3),i+=o;continue}else{this.scanner.consume(3);continue}}if(n===" ")return i?(this.scanner.consume(1),r=3,[1,i]):(this.scanner.consume(1),[3,null]);if(!c){if(n==="{"){if(i)return[1,i];this.scanner.consume(1),this.pushCtx();continue}else if(n==="}"){if(i)return[1,i];if(this.scanner.consume(1),this.yieldPropertyCommands){const h=this.ctxStack.current;this.popCtx();const o=this.getPropertyChanges(h,this.ctxStack.current);if(Object.keys(o).length>0)return[9,{command:void 0,changes:o,depth:this.ctxStack.depth}]}else this.popCtx();continue}}if(!this.inStackContext&&n==="^"){const h=this.scanner.peek(1);if(h){const o=h.charCodeAt(0);if(this.scanner.consume(2),o===32)i+="^";else{if(o===73)return i?[1,i]:[5,null];if(o===74)return i?[1,i]:[6,null];if(o===77)continue;i+="▯"}continue}}this.scanner.consume(1),n.charCodeAt(0)>=32&&(i+=n)}return i?[1,i]:[0,null]};for(;;){const[i,u]=l.call(this);if(i){if(yield new d(i,this.ctxStack.current.copy(),u),i===6&&this.resetParagraphParameters){const c=this.ctxStack.current,n=a(c);this.yieldPropertyCommands&&Object.keys(n).length>0&&(yield new d(9,c.copy(),{command:void 0,changes:{paragraph:n},depth:this.ctxStack.depth}))}r&&(yield new d(r,this.ctxStack.current.copy(),null),r=null)}else break}}}class f{constructor(t){this.text=t,this.textLen=t.length,this._index=0}get currentIndex(){return this._index}get isEmpty(){return this._index>=this.textLen}get hasData(){return this._index<this.textLen}get(){if(this.isEmpty)return"";const t=this.text[this._index];return this._index++,t}consume(t=1){this._index=Math.max(0,Math.min(this._index+t,this.textLen))}peek(t=0){const e=this._index+t;return e>=this.textLen||e<0?"":this.text[e]}find(t,e=!1){let r=this._index;for(;r<this.textLen;){if(e&&this.text[r]==="\\"){if(r+1<this.textLen){if(this.text[r+1]===t)return r+1;r+=2;continue}r++;continue}if(this.text[r]===t)return r;r++}return-1}get tail(){return this.text.slice(this._index)}isNextSpace(){return this.peek()===" "}consumeSpaces(){let t=0;for(;this.isNextSpace();)this.consume(),t++;return t}}class k{constructor(t){this._aci=256,this._rgbValue=null,Array.isArray(t)?this.rgb=t:typeof t=="number"?this.aci=t:this.aci=256}get aci(){return this._aci}set aci(t){if(t===null)this._aci=null;else if(t>=0&&t<=256)this._aci=t,this._rgbValue=null;else throw new Error("ACI not in range [0, 256]")}get rgb(){if(this._rgbValue===null)return null;const t=this._rgbValue>>16&255,e=this._rgbValue>>8&255,r=this._rgbValue&255;return[t,e,r]}set rgb(t){if(t){const[e,r,a]=t;this._rgbValue=(e&255)<<16|(r&255)<<8|a&255,this._aci=null}else this._rgbValue=null}get isRgb(){return this._rgbValue!==null}get isAci(){return this._rgbValue===null&&this._aci!==null}get rgbValue(){return this._rgbValue}set rgbValue(t){t===null?this._rgbValue=null:(this._rgbValue=t&16777215,this._aci=null)}copy(){const t=new k;return t._aci=this._aci,t._rgbValue=this._rgbValue,t}toObject(){return{aci:this._aci,rgb:this.rgb,rgbValue:this._rgbValue}}equals(t){return this._aci===t._aci&&this._rgbValue===t._rgbValue}}class b{constructor(){this._stroke=0,this.continueStroke=!1,this.color=new k,this.align=0,this.fontFace={family:"",style:"Regular",weight:400},this._capHeight={value:1,isRelative:!1},this._widthFactor={value:1,isRelative:!1},this._charTrackingFactor={value:1,isRelative:!1},this.oblique=0,this.paragraph={indent:0,left:0,right:0,align:0,tabs:[]}}get capHeight(){return this._capHeight}set capHeight(t){this._capHeight={value:Math.abs(t.value),isRelative:t.isRelative}}get widthFactor(){return this._widthFactor}set widthFactor(t){this._widthFactor={value:Math.abs(t.value),isRelative:t.isRelative}}get charTrackingFactor(){return this._charTrackingFactor}set charTrackingFactor(t){this._charTrackingFactor={value:Math.abs(t.value),isRelative:t.isRelative}}get aci(){return this.color.aci}set aci(t){this.color.aci=t}get rgb(){return this.color.rgb}set rgb(t){this.color.rgb=t}get italic(){return this.fontFace.style==="Italic"}set italic(t){this.fontFace.style=t?"Italic":"Regular"}get bold(){return(this.fontFace.weight||400)>=700}set bold(t){this.fontFace.weight=t?700:400}get underline(){return!!(this._stroke&1)}set underline(t){this._setStrokeState(1,t)}get strikeThrough(){return!!(this._stroke&4)}set strikeThrough(t){this._setStrokeState(4,t)}get overline(){return!!(this._stroke&2)}set overline(t){this._setStrokeState(2,t)}get hasAnyStroke(){return!!this._stroke}_setStrokeState(t,e=!0){e?this._stroke|=t:this._stroke&=~t}copy(){const t=new b;return t._stroke=this._stroke,t.continueStroke=this.continueStroke,t.color=this.color.copy(),t.align=this.align,t.fontFace={...this.fontFace},t._capHeight={...this._capHeight},t._widthFactor={...this._widthFactor},t._charTrackingFactor={...this._charTrackingFactor},t.oblique=this.oblique,t.paragraph={...this.paragraph},t}}class d{constructor(t,e,r){this.type=t,this.ctx=e,this.data=r}}exports.MTextColor=k;exports.MTextContext=b;exports.MTextLineAlignment=S;exports.MTextParagraphAlignment=F;exports.MTextParser=w;exports.MTextStroke=E;exports.MTextToken=d;exports.TextScanner=f;exports.TokenType=_;exports.escapeDxfLineEndings=N;exports.getFonts=T;exports.hasInlineFormattingCodes=x;exports.int2rgb=I;exports.rgb2int=O;
//# sourceMappingURL=parser.cjs.js.map