deghost 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/categories.ts","../src/detect.ts","../src/replace.ts","../src/summary.ts","../src/chain.ts","../src/cleaner.ts","../src/presets.ts","../src/highlight.ts","../src/index.ts"],"names":["categories"],"mappings":";;;AASO,IAAM,QAAA,GAAqC;AAAA;AAAA,EAEhD,MAAA,EAAQ,UAAA;AAAA;AAAA,EAGR,OAAA,EAAS,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,MAAA,EAAQ,oBAAA;AAAA;AAAA,EAGR,GAAA,EAAK,yBAAA;AAAA;AAAA,EAGL,GAAA,EAAK,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWL,OAAA,EAAS,sDAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,IAAA,EAAM;AACR;AAGO,IAAM,aAAkC,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAe;AAGzF,IAAM,YAAA,GAAyC;AAAA,EACpD,MAAA,EAAQ,yEAAA;AAAA,EACR,OAAA,EAAS,qCAAA;AAAA,EACT,MAAA,EAAQ,qEAAA;AAAA,EACR,GAAA,EAAK,wBAAA;AAAA,EACL,GAAA,EAAK,iBAAA;AAAA,EACL,OAAA,EAAS,qEAAA;AAAA,EACT,IAAA,EAAM;AACR;AAQO,IAAM,SAAA,GAAoC;AAAA,EAC/C,GAAA,EAAQ,aAAA;AAAA,EACR,GAAA,EAAQ,2BAAA;AAAA,EACR,IAAA,EAAQ,oBAAA;AAAA,EACR,GAAA,EAAQ,gBAAA;AAAA,EACR,IAAA,EAAQ,kBAAA;AAAA,EACR,IAAA,EAAQ,SAAA;AAAA,EACR,IAAA,EAAQ,SAAA;AAAA,EACR,IAAA,EAAQ,UAAA;AAAA,EACR,IAAA,EAAQ,UAAA;AAAA,EACR,IAAA,EAAQ,oBAAA;AAAA,EACR,IAAA,EAAQ,mBAAA;AAAA,EACR,IAAA,EAAQ,kBAAA;AAAA,EACR,IAAA,EAAQ,cAAA;AAAA,EACR,IAAA,EAAQ,mBAAA;AAAA,EACR,IAAA,EAAQ,YAAA;AAAA,EACR,IAAA,EAAQ,YAAA;AAAA,EACR,IAAA,EAAQ,kBAAA;AAAA,EACR,IAAA,EAAQ,uBAAA;AAAA,EACR,IAAA,EAAQ,mBAAA;AAAA,EACR,IAAA,EAAQ,oBAAA;AAAA,EACR,IAAA,EAAQ,oBAAA;AAAA,EACR,IAAA,EAAQ,gBAAA;AAAA,EACR,IAAA,EAAQ,qBAAA;AAAA,EACR,IAAA,EAAQ,yBAAA;AAAA,EACR,IAAA,EAAQ,yBAAA;AAAA,EACR,IAAA,EAAQ,4BAAA;AAAA,EACR,IAAA,EAAQ,wBAAA;AAAA,EACR,IAAA,EAAQ,wBAAA;AAAA,EACR,IAAA,EAAQ,uBAAA;AAAA,EACR,IAAA,EAAQ,2BAAA;AAAA,EACR,IAAA,EAAQ,aAAA;AAAA,EACR,IAAA,EAAQ,sBAAA;AAAA,EACR,IAAA,EAAQ,iBAAA;AAAA,EACR,IAAA,EAAQ,qBAAA;AAAA,EACR,IAAA,EAAQ,gBAAA;AAAA,EACR,IAAA,EAAQ,uBAAA;AAAA,EACR,IAAA,EAAQ,uBAAA;AAAA,EACR,IAAA,EAAQ,sBAAA;AAAA,EACR,IAAA,EAAQ,yBAAA;AAAA,EACR,KAAA,EAAQ,mBAAA;AAAA,EACR,KAAA,EAAQ,eAAA;AAAA,EACR,KAAA,EAAQ,2BAAA;AAAA,EACR,KAAA,EAAQ,yBAAA;AAAA,EACR,IAAA,EAAQ,wBAAA;AAAA,EACR,IAAA,EAAQ,yBAAA;AAAA,EACR,IAAA,EAAQ,yBAAA;AAAA,EACR,IAAA,EAAQ,yBAAA;AAAA,EACR,IAAA,EAAQ;AACV;AAEA,IAAM,SAAA,mBAAY,IAAI,GAAA,CAAI,CAAC,IAAA,EAAQ,IAAA,EAAQ,KAAA,EAAQ,KAAA,EAAQ,IAAA,EAAQ,IAAA,EAAQ,IAAA,EAAQ,IAAM,CAAC,CAAA;AAC1F,IAAM,IAAA,GAAO,WAAA;AACb,IAAM,IAAA,GAAO,WAAA;AACb,IAAM,IAAA,GAAO,WAAA;AAGN,SAAS,WAAW,SAAA,EAAyC;AAClE,EAAA,IAAI,SAAA,KAAc,OAAQ,OAAO,KAAA;AACjC,EAAA,IAAI,SAAA,IAAa,MAAA,IAAW,SAAA,IAAa,MAAA,EAAS,OAAO,KAAA;AACzD,EAAA,IAAI,SAAA,IAAa,IAAA,IAAU,SAAA,IAAa,IAAA,EAAQ,OAAO,MAAA;AACvD,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,SAAS,CAAA,EAAG,OAAO,SAAA;AAErC,EAAA,IAAI,SAAA,KAAc,IAAQ,OAAO,MAAA;AACjC,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,aAAA,CAAc,SAAS,CAAA;AAC3C,EAAA,IAAI,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,QAAA;AAC5B,EAAA,IAAI,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,QAAA;AAC5B,EAAA,IAAI,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,SAAA;AAE5B,EAAA,OAAO,MAAA;AACT;;;ACxIA,IAAM,SAAA,GAAY,CAAC,EAAA,KAAuB,CAAA,EAAA,EAAK,EAAA,CAAG,QAAA,CAAS,EAAE,CAAA,CAAE,WAAA,EAAY,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AAE7F,IAAM,UAAA,uBAAiB,GAAA,EAAoB;AAE3C,SAAS,SAASA,WAAAA,EAAiC;AACjD,EAAA,MAAM,IAAA,GAAOA,WAAAA,IAAe,MAAA,CAAO,IAAA,CAAK,QAAQ,CAAA;AAChD,EAAA,MAAM,GAAA,GAAM,CAAC,GAAG,IAAI,EAAE,IAAA,EAAK,CAAE,KAAK,GAAG,CAAA;AACrC,EAAA,IAAI,MAAA,GAAS,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AAC/B,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAA,GAAS,IAAI,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,QAAA,CAAS,CAAC,CAAA,CAAE,MAAM,CAAA,CAAE,IAAA,CAAK,GAAG,GAAG,IAAI,CAAA;AACvE,IAAA,UAAA,CAAW,GAAA,CAAI,KAAK,MAAM,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,MAAA;AACT;AAsBO,UAAU,IAAA,CAAK,OAAeA,WAAAA,EAA+C;AAClF,EAAA,MAAM,KAAA,GAAQ,SAASA,WAAU,CAAA;AACjC,EAAA,KAAA,CAAM,SAAA,GAAY,CAAA;AAElB,EAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,QAAA,CAAS,KAAK,CAAA,EAAG;AACzC,IAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,WAAA,CAAY,CAAC,CAAA;AAC7B,IAAA,MAAM,QAAA,GAAW,WAAW,EAAE,CAAA;AAE9B,IAAA,IAAI,aAAa,MAAA,EAAW;AAE5B,IAAA,MAAM,GAAA,GAAM,UAAU,EAAE,CAAA;AACxB,IAAA,MAAM;AAAA,MACJ,IAAA;AAAA,MACA,SAAA,EAAW,GAAA;AAAA,MACX,IAAA,EAAM,SAAA,CAAU,EAAE,CAAA,IAAK,GAAA;AAAA,MACvB,QAAA;AAAA,MACA,QAAQ,KAAA,CAAM;AAAA,KAChB;AAAA,EACF;AACF;AAEO,SAAS,MAAA,CAAO,OAAeA,WAAAA,EAAsC;AAC1E,EAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,EAAOA,WAAU,CAAC,CAAA;AACpC;AAOO,SAAS,KAAA,CAAM,OAAeA,WAAAA,EAAgD;AACnF,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,KAAA,EAAOA,WAAU,GAAG,OAAO,CAAA;AAChD,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,SAAA,CAAU,OAAeA,WAAAA,EAAkC;AACzE,EAAA,MAAM,KAAA,GAAQ,SAASA,WAAU,CAAA;AACjC,EAAA,KAAA,CAAM,SAAA,GAAY,CAAA;AAClB,EAAA,OAAO,KAAA,CAAM,KAAK,KAAK,CAAA;AACzB;AAOO,SAAS,OAAA,CAAQ,OAAeA,WAAAA,EAAkC;AACvE,EAAA,OAAO,CAAC,SAAA,CAAU,KAAA,EAAOA,WAAU,CAAA;AACrC;AAWO,SAAS,KAAA,CAAM,OAAeA,WAAAA,EAA4D;AAC/F,EAAA,MAAM,SAA4C,EAAC;AAEnD,EAAA,KAAA,MAAW,CAAA,IAAK,MAAA,CAAO,KAAA,EAAOA,WAAU,CAAA,EAAG;AACzC,IAAA,MAAA,CAAO,EAAE,QAAQ,CAAA,GAAA,CAAK,OAAO,CAAA,CAAE,QAAQ,KAAK,CAAA,IAAK,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,MAAA;AACT;AAsBO,SAAS,SAAS,KAAA,EAA8C;AACrE,EAAA,MAAM,KAAK,OAAO,KAAA,KAAU,WAAW,KAAA,GAAQ,KAAA,CAAM,YAAY,CAAC,CAAA;AAClE,EAAA,MAAM,QAAA,GAAW,WAAW,EAAE,CAAA;AAE9B,EAAA,IAAI,QAAA,KAAa,QAAW,OAAO,MAAA;AAEnC,EAAA,MAAM,GAAA,GAAM,UAAU,EAAE,CAAA;AAExB,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,GAAA;AAAA,IACX,IAAA,EAAM,SAAA,CAAU,EAAE,CAAA,IAAK,GAAA;AAAA,IACvB;AAAA,GACF;AACF;;;AC/IO,IAAM,gBAAA,GAAmB,CAAC,CAAA,KAAyB,CAAA,CAAA,EAAI,EAAE,SAAS,CAAA,CAAA,CAAA;AAGlE,SAAS,iBAAA,CACd,KAAA,EACA,UAAA,EACA,MAAA,EACQ;AACR,EAAA,IAAI,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AAEpC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,MAAA,GAAS,CAAA;AAEb,EAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,IAAA,KAAA,CAAM,KAAK,KAAA,CAAM,KAAA,CAAM,MAAA,EAAQ,CAAA,CAAE,MAAM,CAAC,CAAA;AACxC,IAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,CAAC,CAAC,CAAA;AACpB,IAAA,MAAA,GAAS,CAAA,CAAE,MAAA,GAAS,CAAA,CAAE,IAAA,CAAK,MAAA;AAAA,EAC7B;AAEA,EAAA,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,MAAM,CAAC,CAAA;AAE9B,EAAA,OAAO,KAAA,CAAM,KAAK,EAAE,CAAA;AACtB;;;ACbO,SAAS,OAAA,CAAQ,OAAeA,WAAAA,EAAiC;AACtE,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,KAAA,EAAOA,WAAU,CAAA;AAE3C,EAAA,IAAI,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG,OAAO,gCAAA;AAEpC,EAAA,MAAM,SAA4C,EAAC;AACnD,EAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,IAAA,MAAA,CAAO,EAAE,QAAQ,CAAA,GAAA,CAAK,OAAO,CAAA,CAAE,QAAQ,KAAK,CAAA,IAAK,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAA;AACzB,EAAA,MAAM,SAAS,CAAA,EAAG,KAAK,uBAAuB,KAAA,KAAU,CAAA,GAAI,KAAK,GAAG,CAAA,OAAA,CAAA;AAEpE,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CACrC,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAC,MAAM,CAAA,CAAE,aAAA,CAAc,CAAC,CAAC,CAAA,CACrC,GAAA,CAAI,CAAC,CAAC,KAAK,CAAC,CAAA,KAAM,CAAA,EAAA,EAAK,GAAG,CAAA,EAAA,EAAK,CAAC,CAAA,CAAE,CAAA,CAClC,KAAK,IAAI,CAAA;AAEZ,EAAA,MAAM,OAAA,GAAU,WACb,GAAA,CAAI,CAAC,MAAM,CAAA,EAAA,EAAK,CAAA,CAAE,SAAS,CAAA,EAAA,EAAK,CAAA,CAAE,IAAI,CAAA,GAAA,EAAM,CAAA,CAAE,QAAQ,CAAA,SAAA,EAAY,CAAA,CAAE,MAAM,CAAA,CAAA,CAAG,CAAA,CAC7E,KAAK,IAAI,CAAA;AAEZ,EAAA,OAAO,GAAG,MAAM;;AAAA;AAAA,EAAqB,UAAU;;AAAA;AAAA,EAAiB,OAAO,CAAA,CAAA;AACzE;;;ACbO,IAAM,YAAA,GAAN,MAAM,aAAA,CAAa;AAAA,EACf,MAAA;AAAA,EAET,YAAY,KAAA,EAAe;AACzB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,QAAA,EAAkC;AACtC,IAAA,OAAO,IAAI,cAAa,IAAA,CAAK,MAAA,CAAO,QAAQ,QAAA,CAAS,QAAQ,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,EACrE;AAAA;AAAA,EAGA,SAAA,CAAU,QAAA,EAAoB,WAAA,GAAsB,GAAA,EAAmB;AACrE,IAAA,OAAO,IAAI,cAAa,IAAA,CAAK,MAAA,CAAO,QAAQ,QAAA,CAAS,QAAQ,CAAA,EAAG,WAAW,CAAC,CAAA;AAAA,EAC9E;AAAA;AAAA,EAGA,OAAA,CAAQ,UAAoB,MAAA,EAAwD;AAClF,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,IAAA,CAAK,MAAA,EAAkB,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,CAAC,QAAQ,CAAC,CAAA,EAAG,MAAM,CAAA;AAC/F,IAAA,OAAO,WAAW,IAAA,CAAK,MAAA,GAAS,IAAA,GAAO,IAAI,cAAa,MAAM,CAAA;AAAA,EAChE;AAAA;AAAA,EAGA,SAAA,CACE,QAAA,EACA,SAAA,GAA8C,gBAAA,EAChC;AACd,IAAA,MAAMA,WAAAA,GAAa,QAAA,GAAW,CAAC,QAAQ,CAAA,GAAI,MAAA;AAC3C,IAAA,MAAM,MAAA,GAAS,iBAAA;AAAA,MACb,IAAA,CAAK,MAAA;AAAA,MACK,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQA,WAAU,CAAA;AAAA,MACxC;AAAA,KACF;AACA,IAAA,OAAO,WAAW,IAAA,CAAK,MAAA,GAAS,IAAA,GAAO,IAAI,cAAa,MAAM,CAAA;AAAA,EAChE;AAAA;AAAA,EAGA,OAAOA,WAAAA,EAAsC;AAC3C,IAAA,OAAiB,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQA,WAAU,CAAA;AAAA,EACjD;AAAA;AAAA,EAGA,UAAUA,WAAAA,EAAkC;AAC1C,IAAA,OAAiB,SAAA,CAAU,IAAA,CAAK,MAAA,EAAQA,WAAU,CAAA;AAAA,EACpD;AAAA;AAAA,EAGA,MAAMA,WAAAA,EAA4D;AAChE,IAAA,OAAiB,KAAA,CAAM,IAAA,CAAK,MAAA,EAAQA,WAAU,CAAA;AAAA,EAChD;AAAA;AAAA,EAGA,QAAQA,WAAAA,EAAkC;AACxC,IAAA,OAAiB,OAAA,CAAQ,IAAA,CAAK,MAAA,EAAQA,WAAU,CAAA;AAAA,EAClD;AAAA;AAAA,EAGA,QAAQA,WAAAA,EAAiC;AACvC,IAAA,OAAO,OAAA,CAAU,IAAA,CAAK,MAAA,EAAQA,WAAU,CAAA;AAAA,EAC1C;AAAA;AAAA,EAGA,QAAA,GAAyB;AACvB,IAAA,OAAO,IAAI,aAAA,CAAa,IAAA,CAAK,OAAO,OAAA,CAAQ,QAAA,EAAU,GAAG,CAAC,CAAA;AAAA,EAC5D;AAAA;AAAA,EAGA,IAAA,GAAqB;AACnB,IAAA,OAAO,IAAI,aAAA,CAAa,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAAA,EAC5C;AAAA;AAAA,EAGA,KAAA,GAAsB;AACpB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,CAAE,MAAM,SAAS,CAAA,CAAE,KAAA,CAAM,KAAK,EAAE,SAAA,CAAU,QAAQ,CAAA,CAAE,QAAA,GAAW,IAAA,EAAK;AAAA,EAChG;AAAA;AAAA,EAGA,QAAA,GAAmB;AACjB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA,EAGA,OAAA,GAAkB;AAChB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA,EAGA,MAAA,GAAiB;AACf,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AACF;;;AC1FO,IAAM,iBAAN,MAAqB;AAAA,EACjB,SAAiB,EAAC;AAAA,EAC3B,KAAA,GAAQ,KAAA;AAAA,EACR,SAAA,GAAY,KAAA;AAAA;AAAA,EAGZ,MAAM,QAAA,EAA0B;AAC9B,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,EAAE,QAAA,EAAU,MAAA,EAAQ,SAAS,CAAA;AAC9C,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,SAAA,CAAU,QAAA,EAAoB,WAAA,GAAsB,GAAA,EAAW;AAC7D,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,EAAE,UAAU,MAAA,EAAQ,WAAA,EAAa,aAAa,CAAA;AAC/D,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,OAAA,CAAQ,UAAoB,MAAA,EAAgD;AAC1E,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,EAAE,UAAU,MAAA,EAAQ,SAAA,EAAW,QAAQ,CAAA;AACxD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,SAAA,CACE,QAAA,EACA,SAAA,GAA8C,gBAAA,EACxC;AACN,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,EAAE,QAAA,EAAU,QAAQ,SAAA,EAAW,MAAA,EAAQ,WAAW,CAAA;AACnE,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,IAAA,GAAa;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,QAAA,GAAiB;AACf,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,KAAA,GAAmB;AACjB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,CAAC,IAAA,KAAS;AACtC,MAAA,IAAI,IAAA,CAAK,WAAW,SAAA,EAAW;AAC7B,QAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAS,GAAI,IAAA;AAC7B,QAAA,OAAO,CAAC,CAAA,KAAc,iBAAA,CAAkB,CAAA,EAAG,MAAA,CAAO,GAAG,CAAC,QAAQ,CAAC,CAAA,EAAG,MAAM,CAAA;AAAA,MAC1E;AACA,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,IAAA,CAAK,QAAQ,CAAA;AACtC,MAAA,IAAI,IAAA,CAAK,WAAW,OAAA,EAAS;AAC3B,QAAA,OAAO,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,SAAS,EAAE,CAAA;AAAA,MAC7C;AACA,MAAA,MAAM,WAAA,GAAc,KAAK,WAAA,IAAe,GAAA;AACxC,MAAA,OAAO,CAAC,CAAA,KAAc,CAAA,CAAE,OAAA,CAAQ,SAAS,WAAW,CAAA;AAAA,IACtD,CAAC,CAAA;AAED,IAAA,MAAM,aAAa,IAAA,CAAK,SAAA;AACxB,IAAA,MAAM,SAAS,IAAA,CAAK,KAAA;AAEpB,IAAA,OAAO,CAAC,KAAA,KAA0B;AAChC,MAAA,IAAI,MAAA,GAAS,KAAA;AACb,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,MAAA,GAAS,KAAK,MAAM,CAAA;AAAA,MACtB;AACA,MAAA,IAAI,UAAA,EAAY,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,UAAU,GAAG,CAAA;AACrD,MAAA,IAAI,MAAA,EAAQ,MAAA,GAAS,MAAA,CAAO,IAAA,EAAK;AACjC,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,EACF;AACF;AAGO,SAAS,OAAA,GAA0B;AACxC,EAAA,OAAO,IAAI,cAAA,EAAe;AAC5B;;;ACtFO,IAAM,OAAA,GAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrB,OAAO,OAAA,EAAQ,CACZ,MAAM,QAAQ,CAAA,CACd,MAAM,SAAS,CAAA,CACf,MAAM,KAAK,CAAA,CACX,UAAU,QAAQ,CAAA,CAClB,UAAS,CACT,IAAA,GACA,KAAA,EAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,UAAA,EAAY,OAAA,EAAQ,CACjB,KAAA,CAAM,QAAQ,CAAA,CACd,KAAA,CAAM,SAAS,CAAA,CACf,KAAA,CAAM,KAAK,CAAA,CACX,KAAA,CAAM,KAAK,CAAA,CACX,KAAA,CAAM,SAAS,CAAA,CACf,KAAA,CAAM,MAAM,CAAA,CACZ,SAAA,CAAU,QAAQ,CAAA,CAClB,QAAA,EAAS,CACT,IAAA,EAAK,CACL,KAAA,EAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQT,MAAA,EAAQ,OAAA,EAAQ,CAAE,SAAA,CAAU,QAAQ,EAAE,QAAA,EAAS,CAAE,IAAA,EAAK,CAAE,KAAA;AAC1D;;;AC9BO,SAAS,SAAA,CACd,OACA,OAAA,EACQ;AACR,EAAA,MAAM,YACJ,OAAO,OAAA,KAAY,UAAA,GAAa,OAAA,GAAW,SAAS,SAAA,IAAa,gBAAA;AACnE,EAAA,MAAMA,WAAAA,GAAa,OAAO,OAAA,KAAY,QAAA,GAAW,QAAQ,UAAA,GAAa,MAAA;AAEtE,EAAA,OAAO,kBAAkB,KAAA,EAAO,MAAA,CAAO,KAAA,EAAOA,WAAU,GAAG,SAAS,CAAA;AACtE;;;ACcO,SAAS,OAAA,CACd,UACG,IAAA,EACoB;AACvB,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,GAAA,GAAM,KAAA;AAAA,EACR,CAAA,MAAO;AACL,IAAA,GAAA,GAAM,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AAClB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACpC,MAAA,GAAA,IAAO,MAAA,CAAO,KAAK,CAAC,CAAC,KAAK,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA,CAAA;AAAA,IAC5C;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GACJ,OAAO,KAAA,KAAU,QAAA,IAAY,KAAK,MAAA,IAAU,CAAA,GACvC,IAAA,CAAK,CAAC,CAAA,GACP,MAAA;AACN,EAAA,MAAM,KAAA,GAAQ,IAAI,YAAA,CAAa,GAAG,CAAA;AAClC,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA;AACjC,EAAA,MAAM,UAAW,OAAA,EAAS,IAAA,IAAQ,IAAA,GAAQ,OAAA,CAAQ,MAAK,GAAI,OAAA;AAG3D,EAAA,OAAO,IAAI,MAAM,KAAA,EAAO;AAAA,IACtB,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,QAAA,EAAU;AAC1B,MAAA,IAAI,IAAA,KAAS,MAAA,CAAO,WAAA,EAAa,OAAO,MAAM,OAAA;AAC9C,MAAA,IAAI,IAAA,KAAS,QAAA,EAAU,OAAO,OAAA,CAAQ,MAAA;AACtC,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,QAAQ,CAAA;AAAA,IAC3C;AAAA,GACD,CAAA;AACH","file":"index.cjs","sourcesContent":["import type { Category } from './types'\n\n/**\n * Regex patterns for each invisible character category.\n *\n * Uses ES2018 Unicode property escapes where possible (\\p{Cf}, \\p{Cc}, \\p{Zs}).\n * Falls back to explicit codepoint ranges for categories not covered by a\n * single Unicode general category.\n */\nexport const patterns: Record<Category, RegExp> = {\n /** Format characters: zero-width joiners, directional marks, soft hyphens, etc. */\n format: /\\p{Cf}/gu,\n\n /** Control characters: C0 (0x00–0x1F) and C1 (0x7F–0x9F) controls. */\n control: /\\p{Cc}/gu,\n\n /**\n * Space separators: NBSP, en/em/thin/hair/ideographic space, etc.\n * Excludes U+0020 (regular ASCII space) — that's not a ghost.\n */\n spaces: /(?!\\u0020)\\p{Zs}/gu,\n\n /** Tag characters: deprecated Unicode tag block (U+E0001–U+E007F). */\n tag: /[\\u{E0001}-\\u{E007F}]/gu,\n\n /** Byte order mark / zero-width no-break space. */\n bom: /\\uFEFF/gu,\n\n /**\n * Script-specific filler characters:\n * - U+115F, U+1160: Hangul Choseong/Jungseong fillers\n * - U+3164: Hangul filler\n * - U+FFA0: Halfwidth Hangul filler\n * - U+17B4, U+17B5: Khmer vowel inherent\n * - U+180E: Mongolian vowel separator\n * - U+1680: Ogham space mark\n */\n fillers: /[\\u115F\\u1160\\u3164\\uFFA0\\u17B4\\u17B5\\u180E\\u1680]/gu,\n\n /**\n * Invisible math operators:\n * - U+2061: Function application\n * - U+2062: Invisible times\n * - U+2063: Invisible separator\n * - U+2064: Invisible plus\n */\n math: /[\\u2061-\\u2064]/gu,\n}\n\n/** All category names as a readonly array. */\nexport const categories: readonly Category[] = Object.freeze(Object.keys(patterns) as Category[])\n\n/** Human-readable descriptions for each category. */\nexport const descriptions: Record<Category, string> = {\n format: 'Format characters (zero-width joiners, directional marks, soft hyphens)',\n control: 'Control characters (C0/C1 controls)',\n spaces: 'Space separators (NBSP, en/em space, thin space, ideographic space)',\n tag: 'Unicode tag characters',\n bom: 'Byte order mark',\n fillers: 'Script-specific filler characters (Hangul, Khmer, Mongolian, Ogham)',\n math: 'Invisible math operators',\n}\n\n/**\n * Unicode character names for well-known invisible codepoints.\n *\n * This is not exhaustive — \\p{Cf} alone covers 170+ characters.\n * We map the ~40 most commonly encountered ones for the detect() API.\n */\nexport const charNames: Record<number, string> = {\n 0x00ad: 'SOFT HYPHEN',\n 0x034f: 'COMBINING GRAPHEME JOINER',\n 0x061c: 'ARABIC LETTER MARK',\n 0x00a0: 'NO-BREAK SPACE',\n 0x1680: 'OGHAM SPACE MARK',\n 0x2000: 'EN QUAD',\n 0x2001: 'EM QUAD',\n 0x2002: 'EN SPACE',\n 0x2003: 'EM SPACE',\n 0x2004: 'THREE-PER-EM SPACE',\n 0x2005: 'FOUR-PER-EM SPACE',\n 0x2006: 'SIX-PER-EM SPACE',\n 0x2007: 'FIGURE SPACE',\n 0x2008: 'PUNCTUATION SPACE',\n 0x2009: 'THIN SPACE',\n 0x200a: 'HAIR SPACE',\n 0x200b: 'ZERO WIDTH SPACE',\n 0x200c: 'ZERO WIDTH NON-JOINER',\n 0x200d: 'ZERO WIDTH JOINER',\n 0x200e: 'LEFT-TO-RIGHT MARK',\n 0x200f: 'RIGHT-TO-LEFT MARK',\n 0x2028: 'LINE SEPARATOR',\n 0x2029: 'PARAGRAPH SEPARATOR',\n 0x202a: 'LEFT-TO-RIGHT EMBEDDING',\n 0x202b: 'RIGHT-TO-LEFT EMBEDDING',\n 0x202c: 'POP DIRECTIONAL FORMATTING',\n 0x202d: 'LEFT-TO-RIGHT OVERRIDE',\n 0x202e: 'RIGHT-TO-LEFT OVERRIDE',\n 0x202f: 'NARROW NO-BREAK SPACE',\n 0x205f: 'MEDIUM MATHEMATICAL SPACE',\n 0x2060: 'WORD JOINER',\n 0x2061: 'FUNCTION APPLICATION',\n 0x2062: 'INVISIBLE TIMES',\n 0x2063: 'INVISIBLE SEPARATOR',\n 0x2064: 'INVISIBLE PLUS',\n 0x2066: 'LEFT-TO-RIGHT ISOLATE',\n 0x2067: 'RIGHT-TO-LEFT ISOLATE',\n 0x2068: 'FIRST STRONG ISOLATE',\n 0x2069: 'POP DIRECTIONAL ISOLATE',\n 0x3000: 'IDEOGRAPHIC SPACE',\n 0x3164: 'HANGUL FILLER',\n 0xfeff: 'ZERO WIDTH NO-BREAK SPACE',\n 0xffa0: 'HALFWIDTH HANGUL FILLER',\n 0x115f: 'HANGUL CHOSEONG FILLER',\n 0x1160: 'HANGUL JUNGSEONG FILLER',\n 0x17b4: 'KHMER VOWEL INHERENT AQ',\n 0x17b5: 'KHMER VOWEL INHERENT AA',\n 0x180e: 'MONGOLIAN VOWEL SEPARATOR',\n}\n\nconst fillerSet = new Set([0x115f, 0x1160, 0x3164, 0xffa0, 0x17b4, 0x17b5, 0x180e, 0x1680])\nconst isZs = /^\\p{Zs}$/u\nconst isCf = /^\\p{Cf}$/u\nconst isCc = /^\\p{Cc}$/u\n\n/** Resolve the deghost category for a given codepoint. */\nexport function categorize(codepoint: number): Category | undefined {\n if (codepoint === 0xfeff) return 'bom'\n if (codepoint >= 0xe0001 && codepoint <= 0xe007f) return 'tag'\n if (codepoint >= 0x2061 && codepoint <= 0x2064) return 'math'\n if (fillerSet.has(codepoint)) return 'fillers'\n\n if (codepoint === 0x0020) return undefined\n const char = String.fromCodePoint(codepoint)\n if (isZs.test(char)) return 'spaces'\n if (isCf.test(char)) return 'format'\n if (isCc.test(char)) return 'control'\n\n return undefined\n}\n","import { categorize, charNames, patterns } from './categories'\nimport type { Category, Detection } from './types'\n\nconst formatHex = (cp: number): string => `U+${cp.toString(16).toUpperCase().padStart(4, '0')}`\n\nconst regexCache = new Map<string, RegExp>()\n\nfunction getRegex(categories?: Category[]): RegExp {\n const cats = categories ?? (Object.keys(patterns) as Category[])\n const key = [...cats].sort().join(',')\n let cached = regexCache.get(key)\n if (!cached) {\n cached = new RegExp(cats.map((c) => patterns[c].source).join('|'), 'gu')\n regexCache.set(key, cached)\n }\n return cached\n}\n\n/**\n * Scan a string for invisible Unicode characters and return metadata for each.\n *\n * Optionally pass a list of categories to restrict detection.\n *\n * @example\n * ```ts\n * detect('hello\\u200Bworld')\n * // [{ char: '\\u200B', codepoint: 'U+200B', name: 'ZERO WIDTH SPACE', category: 'format', offset: 5 }]\n *\n * detect('a\\u00a0b\\u200Bc', ['format'])\n * // [{ char: '\\u200B', ..., category: 'format' }]\n * ```\n */\n/**\n * Lazily scan a string for invisible Unicode characters, yielding metadata for each.\n *\n * Like `detect()` but returns a generator — useful for large strings where you\n * may not need all results, or want to break early.\n */\nexport function* scan(input: string, categories?: Category[]): Generator<Detection> {\n const regex = getRegex(categories)\n regex.lastIndex = 0\n\n for (const match of input.matchAll(regex)) {\n const char = match[0]!\n const cp = char.codePointAt(0)!\n const category = categorize(cp)\n\n if (category === undefined) continue\n\n const hex = formatHex(cp)\n yield {\n char,\n codepoint: hex,\n name: charNames[cp] ?? hex,\n category,\n offset: match.index,\n }\n }\n}\n\nexport function detect(input: string, categories?: Category[]): Detection[] {\n return [...scan(input, categories)]\n}\n\n/**\n * Return the first invisible character detected, or `undefined` if clean.\n *\n * Uses `scan()` internally — stops at the first match.\n */\nexport function first(input: string, categories?: Category[]): Detection | undefined {\n for (const d of scan(input, categories)) return d\n return undefined\n}\n\n/**\n * Returns true if the string contains any invisible Unicode characters.\n *\n * Faster than `detect()` when you don't need metadata.\n */\nexport function hasGhosts(input: string, categories?: Category[]): boolean {\n const regex = getRegex(categories)\n regex.lastIndex = 0\n return regex.test(input)\n}\n\n/**\n * Returns true if the string contains no invisible Unicode characters.\n *\n * Inverse of `hasGhosts()`.\n */\nexport function isClean(input: string, categories?: Category[]): boolean {\n return !hasGhosts(input, categories)\n}\n\n/**\n * Count invisible characters by category.\n *\n * @example\n * ```ts\n * count('a\\u00A0b\\u200Bc')\n * // { spaces: 1, format: 1 }\n * ```\n */\nexport function count(input: string, categories?: Category[]): Partial<Record<Category, number>> {\n const result: Partial<Record<Category, number>> = {}\n\n for (const d of detect(input, categories)) {\n result[d.category] = (result[d.category] ?? 0) + 1\n }\n\n return result\n}\n\n/** Result of identifying a single character. */\nexport interface CharInfo {\n codepoint: string\n name: string\n category: Category\n}\n\n/**\n * Identify a single character or codepoint — returns its category and name,\n * or `undefined` if it's not an invisible character deghost tracks.\n *\n * @example\n * ```ts\n * identify('\\u200B')\n * // { codepoint: 'U+200B', name: 'ZERO WIDTH SPACE', category: 'format' }\n *\n * identify(0x00A0)\n * // { codepoint: 'U+00A0', name: 'NO-BREAK SPACE', category: 'spaces' }\n * ```\n */\nexport function identify(input: string | number): CharInfo | undefined {\n const cp = typeof input === 'number' ? input : input.codePointAt(0)!\n const category = categorize(cp)\n\n if (category === undefined) return undefined\n\n const hex = formatHex(cp)\n\n return {\n codepoint: hex,\n name: charNames[cp] ?? hex,\n category,\n }\n}\n","import type { Detection } from './types'\n\n/** Format a detection as `[U+XXXX]`. */\nexport const defaultFormatter = (d: Detection): string => `[${d.codepoint}]`\n\n/** Walk detections and replace each matched character using a mapper. */\nexport function replaceDetections(\n input: string,\n detections: Detection[],\n mapper: (detection: Detection) => string,\n): string {\n if (detections.length === 0) return input\n\n const parts: string[] = []\n let cursor = 0\n\n for (const d of detections) {\n parts.push(input.slice(cursor, d.offset))\n parts.push(mapper(d))\n cursor = d.offset + d.char.length\n }\n\n parts.push(input.slice(cursor))\n\n return parts.join('')\n}\n","import { detect } from './detect'\nimport type { Category } from './types'\n\n/**\n * Return a human-readable report of all invisible characters in a string.\n *\n * @example\n * ```ts\n * summary('hello\\u200Bworld')\n * // \"1 invisible character found.\\n\\nBy category:\\n format: 1\\n\\nDetails:\\n U+200B ZERO WIDTH SPACE (format, offset 5)\"\n * ```\n */\nexport function summary(input: string, categories?: Category[]): string {\n const detections = detect(input, categories)\n\n if (detections.length === 0) return 'No invisible characters found.'\n\n const counts: Partial<Record<Category, number>> = {}\n for (const d of detections) {\n counts[d.category] = (counts[d.category] ?? 0) + 1\n }\n\n const total = detections.length\n const header = `${total} invisible character${total === 1 ? '' : 's'} found.`\n\n const byCategory = Object.entries(counts)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([cat, n]) => ` ${cat}: ${n}`)\n .join('\\n')\n\n const details = detections\n .map((d) => ` ${d.codepoint} ${d.name} (${d.category}, offset ${d.offset})`)\n .join('\\n')\n\n return `${header}\\n\\nBy category:\\n${byCategory}\\n\\nDetails:\\n${details}`\n}\n","import { patterns } from './categories'\nimport * as detection from './detect'\nimport { defaultFormatter, replaceDetections } from './replace'\nimport { summary as summarize } from './summary'\nimport type { Category, Detection } from './types'\n\n/**\n * Fluent chain for composing text cleaning operations.\n *\n * Each method returns a new DeghostChain (immutable), so you can\n * branch chains without side effects.\n *\n * @example\n * ```ts\n * new DeghostChain('text\\u00A0with\\u200Bghosts')\n * .strip('format')\n * .normalize('spaces')\n * .trim()\n * .toString()\n * // 'text with ghosts'\n * ```\n */\nexport class DeghostChain {\n readonly #value: string\n\n constructor(value: string) {\n this.#value = value\n }\n\n /** Remove all characters in the given category. */\n strip(category: Category): DeghostChain {\n return new DeghostChain(this.#value.replace(patterns[category], ''))\n }\n\n /** Replace all characters in the given category with a substitute. */\n normalize(category: Category, replacement: string = ' '): DeghostChain {\n return new DeghostChain(this.#value.replace(patterns[category], replacement))\n }\n\n /** Replace matched ghosts in a category using a mapper function. */\n replace(category: Category, mapper: (detection: Detection) => string): DeghostChain {\n const result = replaceDetections(this.#value, detection.detect(this.#value, [category]), mapper)\n return result === this.#value ? this : new DeghostChain(result)\n }\n\n /** Replace ghosts with visible markers like `[U+200B]`. */\n highlight(\n category?: Category,\n formatter: (detection: Detection) => string = defaultFormatter,\n ): DeghostChain {\n const categories = category ? [category] : undefined\n const result = replaceDetections(\n this.#value,\n detection.detect(this.#value, categories),\n formatter,\n )\n return result === this.#value ? this : new DeghostChain(result)\n }\n\n /** Return detections for the current chain value. */\n detect(categories?: Category[]): Detection[] {\n return detection.detect(this.#value, categories)\n }\n\n /** Check if the current chain value contains invisible characters. */\n hasGhosts(categories?: Category[]): boolean {\n return detection.hasGhosts(this.#value, categories)\n }\n\n /** Count invisible characters by category in the current chain value. */\n count(categories?: Category[]): Partial<Record<Category, number>> {\n return detection.count(this.#value, categories)\n }\n\n /** Returns true if the current chain value has no invisible characters. */\n isClean(categories?: Category[]): boolean {\n return detection.isClean(this.#value, categories)\n }\n\n /** Return a human-readable report of ghosts in the current chain value. */\n summary(categories?: Category[]): string {\n return summarize(this.#value, categories)\n }\n\n /** Collapse runs of whitespace into a single space. */\n collapse(): DeghostChain {\n return new DeghostChain(this.#value.replace(/ {2,}/g, ' '))\n }\n\n /** Trim leading and trailing whitespace. */\n trim(): DeghostChain {\n return new DeghostChain(this.#value.trim())\n }\n\n /** Apply the default cleaning preset: strip format + control, normalize spaces, trim. */\n clean(): DeghostChain {\n return this.strip('format').strip('control').strip('bom').normalize('spaces').collapse().trim()\n }\n\n /** Extract the cleaned string. */\n toString(): string {\n return this.#value\n }\n\n /** Extract the cleaned string (alias for toString). */\n valueOf(): string {\n return this.#value\n }\n\n /** Support JSON.stringify. */\n toJSON(): string {\n return this.#value\n }\n}\n","import { patterns } from './categories'\nimport { detect } from './detect'\nimport { defaultFormatter, replaceDetections } from './replace'\nimport type { Category, CleanerFn, Detection, Rule } from './types'\n\n/**\n * Builder for creating reusable cleaning functions.\n *\n * Compile a cleaning pipeline once, apply it to many strings.\n *\n * @example\n * ```ts\n * const clean = cleaner()\n * .strip('format')\n * .strip('control')\n * .normalize('spaces')\n * .trim()\n * .build()\n *\n * clean('dirty\\u00A0string') // 'dirty string'\n * clean('another\\u200Bone') // 'anotherone'\n * ```\n */\nexport class CleanerBuilder {\n readonly #rules: Rule[] = []\n #trim = false\n #collapse = false\n\n /** Add a strip rule — remove all characters in this category. */\n strip(category: Category): this {\n this.#rules.push({ category, action: 'strip' })\n return this\n }\n\n /** Add a normalize rule — replace characters in this category. */\n normalize(category: Category, replacement: string = ' '): this {\n this.#rules.push({ category, action: 'normalize', replacement })\n return this\n }\n\n /** Add a replace rule — transform characters using detection metadata. */\n replace(category: Category, mapper: (detection: Detection) => string): this {\n this.#rules.push({ category, action: 'replace', mapper })\n return this\n }\n\n /** Add a highlight step — annotate characters with visible markers. */\n highlight(\n category: Category,\n formatter: (detection: Detection) => string = defaultFormatter,\n ): this {\n this.#rules.push({ category, action: 'replace', mapper: formatter })\n return this\n }\n\n /** Enable whitespace trimming as a final step. */\n trim(): this {\n this.#trim = true\n return this\n }\n\n /** Enable collapsing runs of whitespace as a final step. */\n collapse(): this {\n this.#collapse = true\n return this\n }\n\n /** Compile the pipeline into a reusable function. */\n build(): CleanerFn {\n const steps = this.#rules.map((rule) => {\n if (rule.action === 'replace') {\n const { mapper, category } = rule\n return (s: string) => replaceDetections(s, detect(s, [category]), mapper)\n }\n const pattern = patterns[rule.category]\n if (rule.action === 'strip') {\n return (s: string) => s.replace(pattern, '')\n }\n const replacement = rule.replacement ?? ' '\n return (s: string) => s.replace(pattern, replacement)\n })\n\n const doCollapse = this.#collapse\n const doTrim = this.#trim\n\n return (input: string): string => {\n let result = input\n for (const step of steps) {\n result = step(result)\n }\n if (doCollapse) result = result.replace(/ {2,}/g, ' ')\n if (doTrim) result = result.trim()\n return result\n }\n }\n}\n\n/** Create a new cleaner builder. */\nexport function cleaner(): CleanerBuilder {\n return new CleanerBuilder()\n}\n","import { cleaner } from './cleaner'\nimport type { CleanerFn } from './types'\n\n/**\n * Pre-built cleaning functions for common use cases.\n *\n * @example\n * ```ts\n * import { presets } from 'deghost'\n *\n * presets.clean('text\\u00A0with\\u200Bghosts')\n * // 'text with ghosts'\n * ```\n */\nexport const presets = {\n /**\n * Default clean: strip format + control + BOM, normalize spaces, collapse, trim.\n *\n * The right choice for most text processing — catches invisible chars from\n * binary formats (Garmin FIT, PDFs), APIs, and copy-paste while preserving\n * word boundaries.\n */\n clean: cleaner()\n .strip('format')\n .strip('control')\n .strip('bom')\n .normalize('spaces')\n .collapse()\n .trim()\n .build(),\n\n /**\n * Aggressive: strip everything invisible, including fillers, math operators, and tags.\n *\n * Use when you want maximally clean output and don't need to preserve any\n * invisible Unicode semantics (ligature joiners, bidi marks, etc.).\n */\n aggressive: cleaner()\n .strip('format')\n .strip('control')\n .strip('bom')\n .strip('tag')\n .strip('fillers')\n .strip('math')\n .normalize('spaces')\n .collapse()\n .trim()\n .build(),\n\n /**\n * Spaces only: normalize Unicode whitespace to ASCII space.\n *\n * Leaves format/control characters alone. Useful when you only care about\n * NBSP and exotic spaces (common in data from Garmin, Strava, etc.).\n */\n spaces: cleaner().normalize('spaces').collapse().trim().build(),\n} satisfies Record<string, CleanerFn>\n","import { detect } from './detect'\nimport { defaultFormatter, replaceDetections } from './replace'\nimport type { Detection, HighlightOptions } from './types'\n\n/**\n * Replace invisible characters with visible markers for debugging.\n *\n * By default each ghost is replaced with its codepoint in brackets,\n * e.g. `[U+200B]`. Pass a custom formatter or an options object to\n * filter by category.\n *\n * @example\n * ```ts\n * highlight('hello\\u200Bworld')\n * // 'hello[U+200B]world'\n *\n * highlight('a\\u200Bb', (d) => `{${d.name}}`)\n * // 'a{ZERO WIDTH SPACE}b'\n *\n * highlight('a\\u00a0b\\u200Bc', { categories: ['format'] })\n * // 'a\\u00a0b[U+200B]c'\n * ```\n */\nexport function highlight(input: string): string\nexport function highlight(input: string, formatter: (detection: Detection) => string): string\nexport function highlight(input: string, options: HighlightOptions): string\nexport function highlight(\n input: string,\n options?: ((detection: Detection) => string) | HighlightOptions,\n): string {\n const formatter =\n typeof options === 'function' ? options : (options?.formatter ?? defaultFormatter)\n const categories = typeof options === 'object' ? options.categories : undefined\n\n return replaceDetections(input, detect(input, categories), formatter)\n}\n","import { DeghostChain } from './chain'\nimport type { DeghostOptions } from './types'\nimport { presets } from './presets'\n\nexport { DeghostChain } from './chain'\nexport { CleanerBuilder, cleaner } from './cleaner'\nexport { scan, detect, first, hasGhosts, isClean, count, identify } from './detect'\nexport { highlight } from './highlight'\nexport { summary } from './summary'\nexport { presets } from './presets'\nexport { patterns, descriptions, charNames, categories, categorize } from './categories'\n\nexport type {\n Category,\n Action,\n Detection,\n HighlightOptions,\n Rule,\n CleanerFn,\n DeghostOptions,\n} from './types'\nexport type { CharInfo } from './detect'\n\n/**\n * Clean a string of invisible Unicode characters.\n *\n * With no chaining, applies the default preset (strip format + control + BOM,\n * normalize spaces, collapse, trim). Chain methods for fine-grained control.\n *\n * @example\n * ```ts\n * // Quick clean — sensible defaults\n * deghost('Plant\\u00a064\\u00a0-\\u00a0Woodbridge')\n * // → 'Plant 64 - Woodbridge'\n *\n * // Tagged template literal\n * deghost`text\\u200B\\u00a0here`\n * // → 'text here'\n *\n * // Chainable — pick what to handle\n * deghost('text\\u200B\\u00a0here')\n * .strip('format')\n * .normalize('spaces')\n * .trim()\n * .toString()\n * ```\n */\nexport function deghost(strings: TemplateStringsArray, ...values: unknown[]): DeghostChain & string\nexport function deghost(input: string, options?: DeghostOptions): DeghostChain & string\nexport function deghost(\n input: string | TemplateStringsArray,\n ...rest: unknown[]\n): DeghostChain & string {\n let raw: string\n if (typeof input === 'string') {\n raw = input\n } else {\n raw = input[0] ?? ''\n for (let i = 0; i < rest.length; i++) {\n raw += String(rest[i]) + (input[i + 1] ?? '')\n }\n }\n\n const options =\n typeof input === 'string' && rest.length <= 1\n ? (rest[0] as DeghostOptions | undefined)\n : undefined\n const chain = new DeghostChain(raw)\n const cleaned = presets.clean(raw)\n const trimmed = (options?.trim ?? true) ? cleaned.trim() : cleaned\n\n // Return a chain that also coerces to the default-cleaned string\n return new Proxy(chain, {\n get(target, prop, receiver) {\n if (prop === Symbol.toPrimitive) return () => trimmed\n if (prop === 'length') return trimmed.length\n return Reflect.get(target, prop, receiver)\n },\n }) as DeghostChain & string\n}\n"]}
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Unicode character categories that deghost can target.
3
+ *
4
+ * Each maps to a Unicode general category or a curated set of codepoints:
5
+ * - `format` — \p{Cf}: zero-width joiners, directional marks, soft hyphens
6
+ * - `control` — \p{Cc}: C0/C1 control characters (NULL through DELETE, 0x80–0x9F)
7
+ * - `spaces` — \p{Zs}: space separators (NBSP, en/em space, thin space, ideographic space)
8
+ * - `tag` — U+E0001–U+E007F: Unicode tag characters (deprecated, used in flag sequences)
9
+ * - `bom` — U+FEFF: byte order mark / zero-width no-break space
10
+ * - `fillers` — Script-specific fillers (Hangul, Khmer, Mongolian, Ogham)
11
+ * - `math` — Invisible math operators (U+2061–U+2064)
12
+ */
13
+ type Category = 'format' | 'control' | 'spaces' | 'tag' | 'bom' | 'fillers' | 'math';
14
+ /** Action to take on matched characters. */
15
+ type Action = 'strip' | 'normalize' | 'replace';
16
+ /** A single detected invisible character with metadata. */
17
+ interface Detection {
18
+ /** The invisible character itself. */
19
+ char: string;
20
+ /** Unicode codepoint as hex string (e.g., "U+200B"). */
21
+ codepoint: string;
22
+ /** Unicode character name (e.g., "ZERO WIDTH SPACE"). */
23
+ name: string;
24
+ /** Which deghost category this character belongs to. */
25
+ category: Category;
26
+ /** Zero-based offset in the input string. */
27
+ offset: number;
28
+ }
29
+ /** Configuration for a single rule in a cleaner pipeline. */
30
+ type Rule = {
31
+ category: Category;
32
+ action: 'strip';
33
+ } | {
34
+ category: Category;
35
+ action: 'normalize';
36
+ replacement?: string;
37
+ } | {
38
+ category: Category;
39
+ action: 'replace';
40
+ mapper: (detection: Detection) => string;
41
+ };
42
+ /** A reusable cleaning function built from a set of rules. */
43
+ type CleanerFn = (input: string) => string;
44
+ /** Options for highlight(). */
45
+ interface HighlightOptions {
46
+ /** Only highlight characters in these categories. Defaults to all. */
47
+ categories?: Category[];
48
+ /** Custom formatter for each detection. Defaults to `[U+XXXX]`. */
49
+ formatter?: (detection: Detection) => string;
50
+ }
51
+ /** Options for the deghost() entry point. */
52
+ interface DeghostOptions {
53
+ /** Trim leading/trailing whitespace from the result. Default: true */
54
+ trim?: boolean;
55
+ }
56
+
57
+ /**
58
+ * Fluent chain for composing text cleaning operations.
59
+ *
60
+ * Each method returns a new DeghostChain (immutable), so you can
61
+ * branch chains without side effects.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * new DeghostChain('text\u00A0with\u200Bghosts')
66
+ * .strip('format')
67
+ * .normalize('spaces')
68
+ * .trim()
69
+ * .toString()
70
+ * // 'text with ghosts'
71
+ * ```
72
+ */
73
+ declare class DeghostChain {
74
+ #private;
75
+ constructor(value: string);
76
+ /** Remove all characters in the given category. */
77
+ strip(category: Category): DeghostChain;
78
+ /** Replace all characters in the given category with a substitute. */
79
+ normalize(category: Category, replacement?: string): DeghostChain;
80
+ /** Replace matched ghosts in a category using a mapper function. */
81
+ replace(category: Category, mapper: (detection: Detection) => string): DeghostChain;
82
+ /** Replace ghosts with visible markers like `[U+200B]`. */
83
+ highlight(category?: Category, formatter?: (detection: Detection) => string): DeghostChain;
84
+ /** Return detections for the current chain value. */
85
+ detect(categories?: Category[]): Detection[];
86
+ /** Check if the current chain value contains invisible characters. */
87
+ hasGhosts(categories?: Category[]): boolean;
88
+ /** Count invisible characters by category in the current chain value. */
89
+ count(categories?: Category[]): Partial<Record<Category, number>>;
90
+ /** Returns true if the current chain value has no invisible characters. */
91
+ isClean(categories?: Category[]): boolean;
92
+ /** Return a human-readable report of ghosts in the current chain value. */
93
+ summary(categories?: Category[]): string;
94
+ /** Collapse runs of whitespace into a single space. */
95
+ collapse(): DeghostChain;
96
+ /** Trim leading and trailing whitespace. */
97
+ trim(): DeghostChain;
98
+ /** Apply the default cleaning preset: strip format + control, normalize spaces, trim. */
99
+ clean(): DeghostChain;
100
+ /** Extract the cleaned string. */
101
+ toString(): string;
102
+ /** Extract the cleaned string (alias for toString). */
103
+ valueOf(): string;
104
+ /** Support JSON.stringify. */
105
+ toJSON(): string;
106
+ }
107
+
108
+ /**
109
+ * Builder for creating reusable cleaning functions.
110
+ *
111
+ * Compile a cleaning pipeline once, apply it to many strings.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * const clean = cleaner()
116
+ * .strip('format')
117
+ * .strip('control')
118
+ * .normalize('spaces')
119
+ * .trim()
120
+ * .build()
121
+ *
122
+ * clean('dirty\u00A0string') // 'dirty string'
123
+ * clean('another\u200Bone') // 'anotherone'
124
+ * ```
125
+ */
126
+ declare class CleanerBuilder {
127
+ #private;
128
+ /** Add a strip rule — remove all characters in this category. */
129
+ strip(category: Category): this;
130
+ /** Add a normalize rule — replace characters in this category. */
131
+ normalize(category: Category, replacement?: string): this;
132
+ /** Add a replace rule — transform characters using detection metadata. */
133
+ replace(category: Category, mapper: (detection: Detection) => string): this;
134
+ /** Add a highlight step — annotate characters with visible markers. */
135
+ highlight(category: Category, formatter?: (detection: Detection) => string): this;
136
+ /** Enable whitespace trimming as a final step. */
137
+ trim(): this;
138
+ /** Enable collapsing runs of whitespace as a final step. */
139
+ collapse(): this;
140
+ /** Compile the pipeline into a reusable function. */
141
+ build(): CleanerFn;
142
+ }
143
+ /** Create a new cleaner builder. */
144
+ declare function cleaner(): CleanerBuilder;
145
+
146
+ /**
147
+ * Scan a string for invisible Unicode characters and return metadata for each.
148
+ *
149
+ * Optionally pass a list of categories to restrict detection.
150
+ *
151
+ * @example
152
+ * ```ts
153
+ * detect('hello\u200Bworld')
154
+ * // [{ char: '\u200B', codepoint: 'U+200B', name: 'ZERO WIDTH SPACE', category: 'format', offset: 5 }]
155
+ *
156
+ * detect('a\u00a0b\u200Bc', ['format'])
157
+ * // [{ char: '\u200B', ..., category: 'format' }]
158
+ * ```
159
+ */
160
+ /**
161
+ * Lazily scan a string for invisible Unicode characters, yielding metadata for each.
162
+ *
163
+ * Like `detect()` but returns a generator — useful for large strings where you
164
+ * may not need all results, or want to break early.
165
+ */
166
+ declare function scan(input: string, categories?: Category[]): Generator<Detection>;
167
+ declare function detect(input: string, categories?: Category[]): Detection[];
168
+ /**
169
+ * Return the first invisible character detected, or `undefined` if clean.
170
+ *
171
+ * Uses `scan()` internally — stops at the first match.
172
+ */
173
+ declare function first(input: string, categories?: Category[]): Detection | undefined;
174
+ /**
175
+ * Returns true if the string contains any invisible Unicode characters.
176
+ *
177
+ * Faster than `detect()` when you don't need metadata.
178
+ */
179
+ declare function hasGhosts(input: string, categories?: Category[]): boolean;
180
+ /**
181
+ * Returns true if the string contains no invisible Unicode characters.
182
+ *
183
+ * Inverse of `hasGhosts()`.
184
+ */
185
+ declare function isClean(input: string, categories?: Category[]): boolean;
186
+ /**
187
+ * Count invisible characters by category.
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * count('a\u00A0b\u200Bc')
192
+ * // { spaces: 1, format: 1 }
193
+ * ```
194
+ */
195
+ declare function count(input: string, categories?: Category[]): Partial<Record<Category, number>>;
196
+ /** Result of identifying a single character. */
197
+ interface CharInfo {
198
+ codepoint: string;
199
+ name: string;
200
+ category: Category;
201
+ }
202
+ /**
203
+ * Identify a single character or codepoint — returns its category and name,
204
+ * or `undefined` if it's not an invisible character deghost tracks.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * identify('\u200B')
209
+ * // { codepoint: 'U+200B', name: 'ZERO WIDTH SPACE', category: 'format' }
210
+ *
211
+ * identify(0x00A0)
212
+ * // { codepoint: 'U+00A0', name: 'NO-BREAK SPACE', category: 'spaces' }
213
+ * ```
214
+ */
215
+ declare function identify(input: string | number): CharInfo | undefined;
216
+
217
+ /**
218
+ * Replace invisible characters with visible markers for debugging.
219
+ *
220
+ * By default each ghost is replaced with its codepoint in brackets,
221
+ * e.g. `[U+200B]`. Pass a custom formatter or an options object to
222
+ * filter by category.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * highlight('hello\u200Bworld')
227
+ * // 'hello[U+200B]world'
228
+ *
229
+ * highlight('a\u200Bb', (d) => `{${d.name}}`)
230
+ * // 'a{ZERO WIDTH SPACE}b'
231
+ *
232
+ * highlight('a\u00a0b\u200Bc', { categories: ['format'] })
233
+ * // 'a\u00a0b[U+200B]c'
234
+ * ```
235
+ */
236
+ declare function highlight(input: string): string;
237
+ declare function highlight(input: string, formatter: (detection: Detection) => string): string;
238
+ declare function highlight(input: string, options: HighlightOptions): string;
239
+
240
+ /**
241
+ * Return a human-readable report of all invisible characters in a string.
242
+ *
243
+ * @example
244
+ * ```ts
245
+ * summary('hello\u200Bworld')
246
+ * // "1 invisible character found.\n\nBy category:\n format: 1\n\nDetails:\n U+200B ZERO WIDTH SPACE (format, offset 5)"
247
+ * ```
248
+ */
249
+ declare function summary(input: string, categories?: Category[]): string;
250
+
251
+ /**
252
+ * Pre-built cleaning functions for common use cases.
253
+ *
254
+ * @example
255
+ * ```ts
256
+ * import { presets } from 'deghost'
257
+ *
258
+ * presets.clean('text\u00A0with\u200Bghosts')
259
+ * // 'text with ghosts'
260
+ * ```
261
+ */
262
+ declare const presets: {
263
+ /**
264
+ * Default clean: strip format + control + BOM, normalize spaces, collapse, trim.
265
+ *
266
+ * The right choice for most text processing — catches invisible chars from
267
+ * binary formats (Garmin FIT, PDFs), APIs, and copy-paste while preserving
268
+ * word boundaries.
269
+ */
270
+ clean: CleanerFn;
271
+ /**
272
+ * Aggressive: strip everything invisible, including fillers, math operators, and tags.
273
+ *
274
+ * Use when you want maximally clean output and don't need to preserve any
275
+ * invisible Unicode semantics (ligature joiners, bidi marks, etc.).
276
+ */
277
+ aggressive: CleanerFn;
278
+ /**
279
+ * Spaces only: normalize Unicode whitespace to ASCII space.
280
+ *
281
+ * Leaves format/control characters alone. Useful when you only care about
282
+ * NBSP and exotic spaces (common in data from Garmin, Strava, etc.).
283
+ */
284
+ spaces: CleanerFn;
285
+ };
286
+
287
+ /**
288
+ * Regex patterns for each invisible character category.
289
+ *
290
+ * Uses ES2018 Unicode property escapes where possible (\p{Cf}, \p{Cc}, \p{Zs}).
291
+ * Falls back to explicit codepoint ranges for categories not covered by a
292
+ * single Unicode general category.
293
+ */
294
+ declare const patterns: Record<Category, RegExp>;
295
+ /** All category names as a readonly array. */
296
+ declare const categories: readonly Category[];
297
+ /** Human-readable descriptions for each category. */
298
+ declare const descriptions: Record<Category, string>;
299
+ /**
300
+ * Unicode character names for well-known invisible codepoints.
301
+ *
302
+ * This is not exhaustive — \p{Cf} alone covers 170+ characters.
303
+ * We map the ~40 most commonly encountered ones for the detect() API.
304
+ */
305
+ declare const charNames: Record<number, string>;
306
+ /** Resolve the deghost category for a given codepoint. */
307
+ declare function categorize(codepoint: number): Category | undefined;
308
+
309
+ /**
310
+ * Clean a string of invisible Unicode characters.
311
+ *
312
+ * With no chaining, applies the default preset (strip format + control + BOM,
313
+ * normalize spaces, collapse, trim). Chain methods for fine-grained control.
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * // Quick clean — sensible defaults
318
+ * deghost('Plant\u00a064\u00a0-\u00a0Woodbridge')
319
+ * // → 'Plant 64 - Woodbridge'
320
+ *
321
+ * // Tagged template literal
322
+ * deghost`text\u200B\u00a0here`
323
+ * // → 'text here'
324
+ *
325
+ * // Chainable — pick what to handle
326
+ * deghost('text\u200B\u00a0here')
327
+ * .strip('format')
328
+ * .normalize('spaces')
329
+ * .trim()
330
+ * .toString()
331
+ * ```
332
+ */
333
+ declare function deghost(strings: TemplateStringsArray, ...values: unknown[]): DeghostChain & string;
334
+ declare function deghost(input: string, options?: DeghostOptions): DeghostChain & string;
335
+
336
+ export { type Action, type Category, type CharInfo, CleanerBuilder, type CleanerFn, DeghostChain, type DeghostOptions, type Detection, type HighlightOptions, type Rule, categories, categorize, charNames, cleaner, count, deghost, descriptions, detect, first, hasGhosts, highlight, identify, isClean, patterns, presets, scan, summary };