index.js 122 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828
  1. (function webpackUniversalModuleDefinition(root, factory) {
  2. if(typeof exports === 'object' && typeof module === 'object')
  3. module.exports = factory();
  4. else if(typeof define === 'function' && define.amd)
  5. define("TableEditor", [], factory);
  6. else if(typeof exports === 'object')
  7. exports["TableEditor"] = factory();
  8. else
  9. root["TableEditor"] = factory();
  10. })(typeof self !== 'undefined' ? self : this, function() {
  11. return /******/ (function(modules) { // webpackBootstrap
  12. /******/ // The module cache
  13. /******/ var installedModules = {};
  14. /******/
  15. /******/ // The require function
  16. /******/ function __webpack_require__(moduleId) {
  17. /******/
  18. /******/ // Check if module is in cache
  19. /******/ if(installedModules[moduleId]) {
  20. /******/ return installedModules[moduleId].exports;
  21. /******/ }
  22. /******/ // Create a new module (and put it into the cache)
  23. /******/ var module = installedModules[moduleId] = {
  24. /******/ i: moduleId,
  25. /******/ l: false,
  26. /******/ exports: {}
  27. /******/ };
  28. /******/
  29. /******/ // Execute the module function
  30. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  31. /******/
  32. /******/ // Flag the module as loaded
  33. /******/ module.l = true;
  34. /******/
  35. /******/ // Return the exports of the module
  36. /******/ return module.exports;
  37. /******/ }
  38. /******/
  39. /******/
  40. /******/ // expose the modules object (__webpack_modules__)
  41. /******/ __webpack_require__.m = modules;
  42. /******/
  43. /******/ // expose the module cache
  44. /******/ __webpack_require__.c = installedModules;
  45. /******/
  46. /******/ // define getter function for harmony exports
  47. /******/ __webpack_require__.d = function(exports, name, getter) {
  48. /******/ if(!__webpack_require__.o(exports, name)) {
  49. /******/ Object.defineProperty(exports, name, {
  50. /******/ configurable: false,
  51. /******/ enumerable: true,
  52. /******/ get: getter
  53. /******/ });
  54. /******/ }
  55. /******/ };
  56. /******/
  57. /******/ // getDefaultExport function for compatibility with non-harmony modules
  58. /******/ __webpack_require__.n = function(module) {
  59. /******/ var getter = module && module.__esModule ?
  60. /******/ function getDefault() { return module['default']; } :
  61. /******/ function getModuleExports() { return module; };
  62. /******/ __webpack_require__.d(getter, 'a', getter);
  63. /******/ return getter;
  64. /******/ };
  65. /******/
  66. /******/ // Object.prototype.hasOwnProperty.call
  67. /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  68. /******/
  69. /******/ // __webpack_public_path__
  70. /******/ __webpack_require__.p = "";
  71. /******/
  72. /******/ // Load entry module and return exports
  73. /******/ return __webpack_require__(__webpack_require__.s = 0);
  74. /******/ })
  75. /************************************************************************/
  76. /******/ ([
  77. /* 0 */
  78. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  79. "use strict";
  80. Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
  81. /* harmony export (immutable) */ __webpack_exports__["initTableEditor"] = initTableEditor;
  82. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__ = __webpack_require__(1);
  83. /* global CodeMirror, $ */
  84. // port of the code from: https://github.com/susisu/mte-demo/blob/master/src/main.js
  85. // text editor interface
  86. // see https://doc.esdoc.org/github.com/susisu/mte-kernel/class/lib/text-editor.js~ITextEditor.html
  87. class TextEditorInterface {
  88. constructor (editor) {
  89. this.editor = editor
  90. this.doc = editor.getDoc()
  91. this.transaction = false
  92. this.onDidFinishTransaction = null
  93. }
  94. getCursorPosition () {
  95. const { line, ch } = this.doc.getCursor()
  96. return new __WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["c" /* Point */](line, ch)
  97. }
  98. setCursorPosition (pos) {
  99. this.doc.setCursor({ line: pos.row, ch: pos.column })
  100. }
  101. setSelectionRange (range) {
  102. this.doc.setSelection(
  103. { line: range.start.row, ch: range.start.column },
  104. { line: range.end.row, ch: range.end.column }
  105. )
  106. }
  107. getLastRow () {
  108. return this.doc.lineCount() - 1
  109. }
  110. acceptsTableEdit () {
  111. return true
  112. }
  113. getLine (row) {
  114. return this.doc.getLine(row)
  115. }
  116. insertLine (row, line) {
  117. const lastRow = this.getLastRow()
  118. if (row > lastRow) {
  119. const lastLine = this.getLine(lastRow)
  120. this.doc.replaceRange(
  121. '\n' + line,
  122. { line: lastRow, ch: lastLine.length },
  123. { line: lastRow, ch: lastLine.length }
  124. )
  125. } else {
  126. this.doc.replaceRange(
  127. line + '\n',
  128. { line: row, ch: 0 },
  129. { line: row, ch: 0 }
  130. )
  131. }
  132. }
  133. deleteLine (row) {
  134. const lastRow = this.getLastRow()
  135. if (row >= lastRow) {
  136. if (lastRow > 0) {
  137. const preLastLine = this.getLine(lastRow - 1)
  138. const lastLine = this.getLine(lastRow)
  139. this.doc.replaceRange(
  140. '',
  141. { line: lastRow - 1, ch: preLastLine.length },
  142. { line: lastRow, ch: lastLine.length }
  143. )
  144. } else {
  145. const lastLine = this.getLine(lastRow)
  146. this.doc.replaceRange(
  147. '',
  148. { line: lastRow, ch: 0 },
  149. { line: lastRow, ch: lastLine.length }
  150. )
  151. }
  152. } else {
  153. this.doc.replaceRange(
  154. '',
  155. { line: row, ch: 0 },
  156. { line: row + 1, ch: 0 }
  157. )
  158. }
  159. }
  160. replaceLines (startRow, endRow, lines) {
  161. const lastRow = this.getLastRow()
  162. if (endRow > lastRow) {
  163. const lastLine = this.getLine(lastRow)
  164. this.doc.replaceRange(
  165. lines.join('\n'),
  166. { line: startRow, ch: 0 },
  167. { line: lastRow, ch: lastLine.length }
  168. )
  169. } else {
  170. this.doc.replaceRange(
  171. lines.join('\n') + '\n',
  172. { line: startRow, ch: 0 },
  173. { line: endRow, ch: 0 }
  174. )
  175. }
  176. }
  177. transact (func) {
  178. this.transaction = true
  179. func()
  180. this.transaction = false
  181. if (this.onDidFinishTransaction) {
  182. this.onDidFinishTransaction.call(undefined)
  183. }
  184. }
  185. }
  186. function initTableEditor (editor) {
  187. // create an interface to the text editor
  188. const editorIntf = new TextEditorInterface(editor)
  189. // create a table editor object
  190. const tableEditor = new __WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["d" /* TableEditor */](editorIntf)
  191. // options for the table editor
  192. const opts = Object(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["e" /* options */])({
  193. smartCursor: true,
  194. formatType: __WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["b" /* FormatType */].NORMAL
  195. })
  196. // keymap of the commands
  197. // from https://github.com/susisu/mte-demo/blob/master/src/main.js
  198. const keyMap = CodeMirror.normalizeKeyMap({
  199. Tab: () => { tableEditor.nextCell(opts) },
  200. 'Shift-Tab': () => { tableEditor.previousCell(opts) },
  201. Enter: () => { tableEditor.nextRow(opts) },
  202. 'Ctrl-Enter': () => { tableEditor.escape(opts) },
  203. 'Cmd-Enter': () => { tableEditor.escape(opts) },
  204. 'Shift-Ctrl-Left': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].LEFT, opts) },
  205. 'Shift-Cmd-Left': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].LEFT, opts) },
  206. 'Shift-Ctrl-Right': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].RIGHT, opts) },
  207. 'Shift-Cmd-Right': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].RIGHT, opts) },
  208. 'Shift-Ctrl-Up': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].CENTER, opts) },
  209. 'Shift-Cmd-Up': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].CENTER, opts) },
  210. 'Shift-Ctrl-Down': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].NONE, opts) },
  211. 'Shift-Cmd-Down': () => { tableEditor.alignColumn(__WEBPACK_IMPORTED_MODULE_0__susisu_mte_kernel__["a" /* Alignment */].NONE, opts) },
  212. 'Ctrl-Left': () => { tableEditor.moveFocus(0, -1, opts) },
  213. 'Cmd-Left': () => { tableEditor.moveFocus(0, -1, opts) },
  214. 'Ctrl-Right': () => { tableEditor.moveFocus(0, 1, opts) },
  215. 'Cmd-Right': () => { tableEditor.moveFocus(0, 1, opts) },
  216. 'Ctrl-Up': () => { tableEditor.moveFocus(-1, 0, opts) },
  217. 'Cmd-Up': () => { tableEditor.moveFocus(-1, 0, opts) },
  218. 'Ctrl-Down': () => { tableEditor.moveFocus(1, 0, opts) },
  219. 'Cmd-Down': () => { tableEditor.moveFocus(1, 0, opts) },
  220. 'Ctrl-K Ctrl-I': () => { tableEditor.insertRow(opts) },
  221. 'Cmd-K Cmd-I': () => { tableEditor.insertRow(opts) },
  222. 'Ctrl-L Ctrl-I': () => { tableEditor.deleteRow(opts) },
  223. 'Cmd-L Cmd-I': () => { tableEditor.deleteRow(opts) },
  224. 'Ctrl-K Ctrl-J': () => { tableEditor.insertColumn(opts) },
  225. 'Cmd-K Cmd-J': () => { tableEditor.insertColumn(opts) },
  226. 'Ctrl-L Ctrl-J': () => { tableEditor.deleteColumn(opts) },
  227. 'Cmd-L Cmd-J': () => { tableEditor.deleteColumn(opts) },
  228. 'Alt-Shift-Ctrl-Left': () => { tableEditor.moveColumn(-1, opts) },
  229. 'Alt-Shift-Cmd-Left': () => { tableEditor.moveColumn(-1, opts) },
  230. 'Alt-Shift-Ctrl-Right': () => { tableEditor.moveColumn(1, opts) },
  231. 'Alt-Shift-Cmd-Right': () => { tableEditor.moveColumn(1, opts) },
  232. 'Alt-Shift-Ctrl-Up': () => { tableEditor.moveRow(-1, opts) },
  233. 'Alt-Shift-Cmd-Up': () => { tableEditor.moveRow(-1, opts) },
  234. 'Alt-Shift-Ctrl-Down': () => { tableEditor.moveRow(1, opts) },
  235. 'Alt-Shift-Cmd-Down': () => { tableEditor.moveRow(1, opts) }
  236. })
  237. // enable keymap if the cursor is in a table
  238. function updateActiveState() {
  239. const active = tableEditor.cursorIsInTable();
  240. if (active) {
  241. editor.setOption("extraKeys", keyMap);
  242. }
  243. else {
  244. editor.setOption("extraKeys", null);
  245. tableEditor.resetSmartCursor();
  246. }
  247. }
  248. // event subscriptions
  249. editor.on("cursorActivity", () => {
  250. if (!editorIntf.transaction) {
  251. updateActiveState();
  252. }
  253. });
  254. editor.on("changes", () => {
  255. if (!editorIntf.transaction) {
  256. updateActiveState();
  257. }
  258. });
  259. editorIntf.onDidFinishTransaction = () => {
  260. updateActiveState();
  261. };
  262. return tableEditor
  263. }
  264. /***/ }),
  265. /* 1 */
  266. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  267. "use strict";
  268. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return Point; });
  269. /* unused harmony export Range */
  270. /* unused harmony export Focus */
  271. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Alignment; });
  272. /* unused harmony export DefaultAlignment */
  273. /* unused harmony export HeaderAlignment */
  274. /* unused harmony export TableCell */
  275. /* unused harmony export TableRow */
  276. /* unused harmony export Table */
  277. /* unused harmony export readTable */
  278. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return FormatType; });
  279. /* unused harmony export completeTable */
  280. /* unused harmony export formatTable */
  281. /* unused harmony export alterAlignment */
  282. /* unused harmony export insertRow */
  283. /* unused harmony export deleteRow */
  284. /* unused harmony export moveRow */
  285. /* unused harmony export insertColumn */
  286. /* unused harmony export deleteColumn */
  287. /* unused harmony export moveColumn */
  288. /* unused harmony export Insert */
  289. /* unused harmony export Delete */
  290. /* unused harmony export applyEditScript */
  291. /* unused harmony export shortestEditScript */
  292. /* unused harmony export ITextEditor */
  293. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return options; });
  294. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return TableEditor; });
  295. /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_meaw__ = __webpack_require__(2);
  296. /**
  297. * A `Point` represents a point in the text editor.
  298. */
  299. class Point {
  300. /**
  301. * Creates a new `Point` object.
  302. *
  303. * @param {number} row - Row of the point, starts from 0.
  304. * @param {number} column - Column of the point, starts from 0.
  305. */
  306. constructor(row, column) {
  307. /** @private */
  308. this._row = row;
  309. /** @private */
  310. this._column = column;
  311. }
  312. /**
  313. * Row of the point.
  314. *
  315. * @type {number}
  316. */
  317. get row() {
  318. return this._row;
  319. }
  320. /**
  321. * Column of the point.
  322. *
  323. * @type {number}
  324. */
  325. get column() {
  326. return this._column;
  327. }
  328. /**
  329. * Checks if the point is equal to another point.
  330. *
  331. * @param {Point} point - A point object.
  332. * @returns {boolean} `true` if two points are equal.
  333. */
  334. equals(point) {
  335. return this.row === point.row && this.column === point.column;
  336. }
  337. }
  338. /**
  339. * A `Range` object represents a range in the text editor.
  340. */
  341. class Range {
  342. /**
  343. * Creates a new `Range` object.
  344. *
  345. * @param {Point} start - The start point of the range.
  346. * @param {Point} end - The end point of the range.
  347. */
  348. constructor(start, end) {
  349. /** @private */
  350. this._start = start;
  351. /** @private */
  352. this._end = end;
  353. }
  354. /**
  355. * The start point of the range.
  356. *
  357. * @type {Point}
  358. */
  359. get start() {
  360. return this._start;
  361. }
  362. /**
  363. * The end point of the range.
  364. *
  365. * @type {Point}
  366. */
  367. get end() {
  368. return this._end;
  369. }
  370. }
  371. /**
  372. * A `Focus` object represents which cell is focused in the table.
  373. *
  374. * Note that `row` and `column` properties specifiy a cell's position in the table, not the cursor's
  375. * position in the text editor as {@link Point} class.
  376. *
  377. * @private
  378. */
  379. class Focus {
  380. /**
  381. * Creates a new `Focus` object.
  382. *
  383. * @param {number} row - Row of the focused cell.
  384. * @param {number} column - Column of the focused cell.
  385. * @param {number} offset - Raw offset in the cell.
  386. */
  387. constructor(row, column, offset) {
  388. /** @private */
  389. this._row = row;
  390. /** @private */
  391. this._column = column;
  392. /** @private */
  393. this._offset = offset;
  394. }
  395. /**
  396. * Row of the focused cell.
  397. *
  398. * @type {number}
  399. */
  400. get row() {
  401. return this._row;
  402. }
  403. /**
  404. * Column of the focused cell.
  405. *
  406. * @type {number}
  407. */
  408. get column() {
  409. return this._column;
  410. }
  411. /**
  412. * Raw offset in the cell.
  413. *
  414. * @type {number}
  415. */
  416. get offset() {
  417. return this._offset;
  418. }
  419. /**
  420. * Checks if two focuses point the same cell.
  421. * Offsets are ignored.
  422. *
  423. * @param {Focus} focus - A focus object.
  424. * @returns {boolean}
  425. */
  426. posEquals(focus) {
  427. return this.row === focus.row && this.column === focus.column;
  428. }
  429. /**
  430. * Creates a copy of the focus object by setting its row to the specified value.
  431. *
  432. * @param {number} row - Row of the focused cell.
  433. * @returns {Focus} A new focus object with the specified row.
  434. */
  435. setRow(row) {
  436. return new Focus(row, this.column, this.offset);
  437. }
  438. /**
  439. * Creates a copy of the focus object by setting its column to the specified value.
  440. *
  441. * @param {number} column - Column of the focused cell.
  442. * @returns {Focus} A new focus object with the specified column.
  443. */
  444. setColumn(column) {
  445. return new Focus(this.row, column, this.offset);
  446. }
  447. /**
  448. * Creates a copy of the focus object by setting its offset to the specified value.
  449. *
  450. * @param {number} offset - Offset in the focused cell.
  451. * @returns {Focus} A new focus object with the specified offset.
  452. */
  453. setOffset(offset) {
  454. return new Focus(this.row, this.column, offset);
  455. }
  456. }
  457. /**
  458. * Represents column alignment.
  459. *
  460. * - `Alignment.NONE` - Use default alignment.
  461. * - `Alignment.LEFT` - Align left.
  462. * - `Alignment.RIGHT` - Align right.
  463. * - `Alignment.CENTER` - Align center.
  464. *
  465. * @type {Object}
  466. */
  467. const Alignment = Object.freeze({
  468. NONE : "none",
  469. LEFT : "left",
  470. RIGHT : "right",
  471. CENTER: "center"
  472. });
  473. /**
  474. * Represents default column alignment
  475. *
  476. * - `DefaultAlignment.LEFT` - Align left.
  477. * - `DefaultAlignment.RIGHT` - Align right.
  478. * - `DefaultAlignment.CENTER` - Align center.
  479. *
  480. * @type {Object}
  481. */
  482. const DefaultAlignment = Object.freeze({
  483. LEFT : Alignment.LEFT,
  484. RIGHT : Alignment.RIGHT,
  485. CENTER: Alignment.CENTER
  486. });
  487. /**
  488. * Represents alignment of header cells.
  489. *
  490. * - `HeaderAlignment.FOLLOW` - Follow column's alignment.
  491. * - `HeaderAlignment.LEFT` - Align left.
  492. * - `HeaderAlignment.RIGHT` - Align right.
  493. * - `HeaderAlignment.CENTER` - Align center.
  494. *
  495. * @type {Object}
  496. */
  497. const HeaderAlignment = Object.freeze({
  498. FOLLOW: "follow",
  499. LEFT : Alignment.LEFT,
  500. RIGHT : Alignment.RIGHT,
  501. CENTER: Alignment.CENTER
  502. });
  503. /**
  504. * A `TableCell` object represents a table cell.
  505. *
  506. * @private
  507. */
  508. class TableCell {
  509. /**
  510. * Creates a new `TableCell` object.
  511. *
  512. * @param {string} rawContent - Raw content of the cell.
  513. */
  514. constructor(rawContent) {
  515. /** @private */
  516. this._rawContent = rawContent;
  517. /** @private */
  518. this._content = rawContent.trim();
  519. /** @private */
  520. this._paddingLeft = this._content === ""
  521. ? (this._rawContent === "" ? 0 : 1)
  522. : this._rawContent.length - this._rawContent.trimLeft().length;
  523. /** @private */
  524. this._paddingRight = this._rawContent.length - this._content.length - this._paddingLeft;
  525. }
  526. /**
  527. * Raw content of the cell.
  528. *
  529. * @type {string}
  530. */
  531. get rawContent() {
  532. return this._rawContent;
  533. }
  534. /**
  535. * Trimmed content of the cell.
  536. *
  537. * @type {string}
  538. */
  539. get content() {
  540. return this._content;
  541. }
  542. /**
  543. * Width of the left padding of the cell.
  544. *
  545. * @type {number}
  546. */
  547. get paddingLeft() {
  548. return this._paddingLeft;
  549. }
  550. /**
  551. * Width of the right padding of the cell.
  552. *
  553. * @type {number}
  554. */
  555. get paddingRight() {
  556. return this._paddingRight;
  557. }
  558. /**
  559. * Convers the cell to a text representation.
  560. *
  561. * @returns {string} The raw content of the cell.
  562. */
  563. toText() {
  564. return this.rawContent;
  565. }
  566. /**
  567. * Checks if the cell is a delimiter i.e. it only contains hyphens `-` with optional one
  568. * leading and trailing colons `:`.
  569. *
  570. * @returns {boolean} `true` if the cell is a delimiter.
  571. */
  572. isDelimiter() {
  573. return /^\s*:?-+:?\s*$/.test(this.rawContent);
  574. }
  575. /**
  576. * Returns the alignment the cell represents.
  577. *
  578. * @returns {Alignment|undefined} The alignment the cell represents;
  579. * `undefined` if the cell is not a delimiter.
  580. */
  581. getAlignment() {
  582. if (!this.isDelimiter()) {
  583. return undefined;
  584. }
  585. if (this.content[0] === ":") {
  586. if (this.content[this.content.length - 1] === ":") {
  587. return Alignment.CENTER;
  588. }
  589. else {
  590. return Alignment.LEFT;
  591. }
  592. }
  593. else {
  594. if (this.content[this.content.length - 1] === ":") {
  595. return Alignment.RIGHT;
  596. }
  597. else {
  598. return Alignment.NONE;
  599. }
  600. }
  601. }
  602. /**
  603. * Computes a relative position in the trimmed content from that in the raw content.
  604. *
  605. * @param {number} rawOffset - Relative position in the raw content.
  606. * @returns {number} - Relative position in the trimmed content.
  607. */
  608. computeContentOffset(rawOffset) {
  609. if (this.content === "") {
  610. return 0;
  611. }
  612. if (rawOffset < this.paddingLeft) {
  613. return 0;
  614. }
  615. if (rawOffset < this.paddingLeft + this.content.length) {
  616. return rawOffset - this.paddingLeft;
  617. }
  618. else {
  619. return this.content.length;
  620. }
  621. }
  622. /**
  623. * Computes a relative position in the raw content from that in the trimmed content.
  624. *
  625. * @param {number} contentOffset - Relative position in the trimmed content.
  626. * @returns {number} - Relative position in the raw content.
  627. */
  628. computeRawOffset(contentOffset) {
  629. return contentOffset + this.paddingLeft;
  630. }
  631. }
  632. /**
  633. * A `TableRow` object represents a table row.
  634. *
  635. * @private
  636. */
  637. class TableRow {
  638. /**
  639. * Creates a new `TableRow` objec.
  640. *
  641. * @param {Array<TableCell>} cells - Cells that the row contains.
  642. * @param {string} marginLeft - Margin string at the left of the row.
  643. * @param {string} marginRight - Margin string at the right of the row.
  644. */
  645. constructor(cells, marginLeft, marginRight) {
  646. /** @private */
  647. this._cells = cells.slice();
  648. /** @private */
  649. this._marginLeft = marginLeft;
  650. /** @private */
  651. this._marginRight = marginRight;
  652. }
  653. /**
  654. * Margin string at the left of the row.
  655. *
  656. * @type {string}
  657. */
  658. get marginLeft() {
  659. return this._marginLeft;
  660. }
  661. /**
  662. * Margin string at the right of the row.
  663. *
  664. * @type {string}
  665. */
  666. get marginRight() {
  667. return this._marginRight;
  668. }
  669. /**
  670. * Gets the number of the cells in the row.
  671. *
  672. * @returns {number} Number of the cells.
  673. */
  674. getWidth() {
  675. return this._cells.length;
  676. }
  677. /**
  678. * Returns the cells that the row contains.
  679. *
  680. * @returns {Array<TableCell>} An array of cells that the row contains.
  681. */
  682. getCells() {
  683. return this._cells.slice();
  684. }
  685. /**
  686. * Gets a cell at the specified index.
  687. *
  688. * @param {number} index - Index.
  689. * @returns {TableCell|undefined} The cell at the specified index if exists;
  690. * `undefined` if no cell is found.
  691. */
  692. getCellAt(index) {
  693. return this._cells[index];
  694. }
  695. /**
  696. * Convers the row to a text representation.
  697. *
  698. * @returns {string} A text representation of the row.
  699. */
  700. toText() {
  701. if (this._cells.length === 0) {
  702. return this.marginLeft;
  703. }
  704. else {
  705. const cells = this._cells.map(cell => cell.toText()).join("|");
  706. return `${this.marginLeft}|${cells}|${this.marginRight}`;
  707. }
  708. }
  709. /**
  710. * Checks if the row is a delimiter or not.
  711. *
  712. * @returns {boolean} `true` if the row is a delimiter i.e. all the cells contained are delimiters.
  713. */
  714. isDelimiter() {
  715. return this._cells.every(cell => cell.isDelimiter());
  716. }
  717. }
  718. /**
  719. * A `Table` object represents a table.
  720. *
  721. * @private
  722. */
  723. class Table {
  724. /**
  725. * Creates a new `Table` object.
  726. *
  727. * @param {Array<TableRow>} rows - An array of rows that the table contains.
  728. */
  729. constructor(rows) {
  730. /** @private */
  731. this._rows = rows.slice();
  732. }
  733. /**
  734. * Gets the number of rows in the table.
  735. *
  736. * @returns {number} The number of rows.
  737. */
  738. getHeight() {
  739. return this._rows.length;
  740. }
  741. /**
  742. * Gets the maximum width of the rows in the table.
  743. *
  744. * @returns {number} The maximum width of the rows.
  745. */
  746. getWidth() {
  747. return this._rows.map(row => row.getWidth())
  748. .reduce((x, y) => Math.max(x, y), 0);
  749. }
  750. /**
  751. * Gets the width of the header row.
  752. *
  753. * @returns {number|undefined} The width of the header row;
  754. * `undefined` if there is no header row.
  755. */
  756. getHeaderWidth() {
  757. if (this._rows.length === 0) {
  758. return undefined;
  759. }
  760. return this._rows[0].getWidth();
  761. }
  762. /**
  763. * Gets the rows that the table contains.
  764. *
  765. * @returns {Array<TableRow>} An array of the rows.
  766. */
  767. getRows() {
  768. return this._rows.slice();
  769. }
  770. /**
  771. * Gets a row at the specified index.
  772. *
  773. * @param {number} index - Row index.
  774. * @returns {TableRow|undefined} The row at the specified index;
  775. * `undefined` if not found.
  776. */
  777. getRowAt(index) {
  778. return this._rows[index];
  779. }
  780. /**
  781. * Gets the delimiter row of the table.
  782. *
  783. * @returns {TableRow|undefined} The delimiter row;
  784. * `undefined` if there is not delimiter row.
  785. */
  786. getDelimiterRow() {
  787. const row = this._rows[1];
  788. if (row === undefined) {
  789. return undefined;
  790. }
  791. if (row.isDelimiter()) {
  792. return row;
  793. }
  794. else {
  795. return undefined;
  796. }
  797. }
  798. /**
  799. * Gets a cell at the specified index.
  800. *
  801. * @param {number} rowIndex - Row index of the cell.
  802. * @param {number} columnIndex - Column index of the cell.
  803. * @returns {TableCell|undefined} The cell at the specified index;
  804. * `undefined` if not found.
  805. */
  806. getCellAt(rowIndex, columnIndex) {
  807. const row = this._rows[rowIndex];
  808. if (row === undefined) {
  809. return undefined;
  810. }
  811. return row.getCellAt(columnIndex);
  812. }
  813. /**
  814. * Gets the cell at the focus.
  815. *
  816. * @param {Focus} focus - Focus object.
  817. * @returns {TableCell|undefined} The cell at the focus;
  818. * `undefined` if not found.
  819. */
  820. getFocusedCell(focus) {
  821. return this.getCellAt(focus.row, focus.column);
  822. }
  823. /**
  824. * Converts the table to an array of text representations of the rows.
  825. *
  826. * @returns {Array<string>} An array of text representations of the rows.
  827. */
  828. toLines() {
  829. return this._rows.map(row => row.toText());
  830. }
  831. /**
  832. * Computes a focus from a point in the text editor.
  833. *
  834. * @param {Point} pos - A point in the text editor.
  835. * @param {number} rowOffset - The row index where the table starts in the text editor.
  836. * @returns {Focus|undefined} A focus object that corresponds to the specified point;
  837. * `undefined` if the row index is out of bounds.
  838. */
  839. focusOfPosition(pos, rowOffset) {
  840. const rowIndex = pos.row - rowOffset;
  841. const row = this._rows[rowIndex];
  842. if (row === undefined) {
  843. return undefined;
  844. }
  845. if (pos.column < row.marginLeft.length + 1) {
  846. return new Focus(rowIndex, -1, pos.column);
  847. }
  848. else {
  849. const cellWidths = row.getCells().map(cell => cell.rawContent.length);
  850. let columnPos = row.marginLeft.length + 1; // left margin + a pipe
  851. let columnIndex = 0;
  852. for (; columnIndex < cellWidths.length; columnIndex++) {
  853. if (columnPos + cellWidths[columnIndex] + 1 > pos.column) {
  854. break;
  855. }
  856. columnPos += cellWidths[columnIndex] + 1;
  857. }
  858. const offset = pos.column - columnPos;
  859. return new Focus(rowIndex, columnIndex, offset);
  860. }
  861. }
  862. /**
  863. * Computes a position in the text editor from a focus.
  864. *
  865. * @param {Focus} focus - A focus object.
  866. * @param {number} rowOffset - The row index where the table starts in the text editor.
  867. * @returns {Point|undefined} A position in the text editor that corresponds to the focus;
  868. * `undefined` if the focused row is out of the table.
  869. */
  870. positionOfFocus(focus, rowOffset) {
  871. const row = this._rows[focus.row];
  872. if (row === undefined) {
  873. return undefined;
  874. }
  875. const rowPos = focus.row + rowOffset;
  876. if (focus.column < 0) {
  877. return new Point(rowPos, focus.offset);
  878. }
  879. const cellWidths = row.getCells().map(cell => cell.rawContent.length);
  880. const maxIndex = Math.min(focus.column, cellWidths.length);
  881. let columnPos = row.marginLeft.length + 1;
  882. for (let columnIndex = 0; columnIndex < maxIndex; columnIndex++) {
  883. columnPos += cellWidths[columnIndex] + 1;
  884. }
  885. return new Point(rowPos, columnPos + focus.offset);
  886. }
  887. /**
  888. * Computes a selection range from a focus.
  889. *
  890. * @param {Focus} focus - A focus object.
  891. * @param {number} rowOffset - The row index where the table starts in the text editor.
  892. * @returns {Range|undefined} A range to be selected that corresponds to the focus;
  893. * `undefined` if the focus does not specify any cell or the specified cell is empty.
  894. */
  895. selectionRangeOfFocus(focus, rowOffset) {
  896. const row = this._rows[focus.row];
  897. if (row === undefined) {
  898. return undefined;
  899. }
  900. const cell = row.getCellAt(focus.column);
  901. if (cell === undefined) {
  902. return undefined;
  903. }
  904. if (cell.content === "") {
  905. return undefined;
  906. }
  907. const rowPos = focus.row + rowOffset;
  908. const cellWidths = row.getCells().map(cell => cell.rawContent.length);
  909. let columnPos = row.marginLeft.length + 1;
  910. for (let columnIndex = 0; columnIndex < focus.column; columnIndex++) {
  911. columnPos += cellWidths[columnIndex] + 1;
  912. }
  913. columnPos += cell.paddingLeft;
  914. return new Range(
  915. new Point(rowPos, columnPos),
  916. new Point(rowPos, columnPos + cell.content.length)
  917. );
  918. }
  919. }
  920. /**
  921. * Splits a text into cells.
  922. *
  923. * @private
  924. * @param {string} text
  925. * @returns {Array<string>}
  926. */
  927. function _splitCells(text) {
  928. const cells = [];
  929. let buf = "";
  930. let rest = text;
  931. while (rest !== "") {
  932. switch (rest[0]) {
  933. case "`":
  934. // read code span
  935. {
  936. const start = rest.match(/^`*/)[0];
  937. let buf1 = start;
  938. let rest1 = rest.substr(start.length);
  939. let closed = false;
  940. while (rest1 !== "") {
  941. if (rest1[0] === "`") {
  942. const end = rest1.match(/^`*/)[0];
  943. buf1 += end;
  944. rest1 = rest1.substr(end.length);
  945. if (end.length === start.length) {
  946. closed = true;
  947. break;
  948. }
  949. }
  950. else {
  951. buf1 += rest1[0];
  952. rest1 = rest1.substr(1);
  953. }
  954. }
  955. if (closed) {
  956. buf += buf1;
  957. rest = rest1;
  958. }
  959. else {
  960. buf += "`";
  961. rest = rest.substr(1);
  962. }
  963. }
  964. break;
  965. case "\\":
  966. // escape next character
  967. if (rest.length >= 2) {
  968. buf += rest.substr(0, 2);
  969. rest = rest.substr(2);
  970. }
  971. else {
  972. buf += "\\";
  973. rest = rest.substr(1);
  974. }
  975. break;
  976. case "|":
  977. // flush buffer
  978. cells.push(buf);
  979. buf = "";
  980. rest = rest.substr(1);
  981. break;
  982. default:
  983. buf += rest[0];
  984. rest = rest.substr(1);
  985. }
  986. }
  987. cells.push(buf);
  988. return cells;
  989. }
  990. /**
  991. * Reads a table row.
  992. *
  993. * @private
  994. * @param {string} text - A text
  995. * @returns {TableRow}
  996. */
  997. function _readRow(text) {
  998. let cells = _splitCells(text);
  999. let marginLeft;
  1000. if (cells.length > 0 && /^\s*$/.test(cells[0])) {
  1001. marginLeft = cells[0];
  1002. cells = cells.slice(1);
  1003. }
  1004. else {
  1005. marginLeft = "";
  1006. }
  1007. let marginRight;
  1008. if (cells.length > 1 && /^\s*$/.test(cells[cells.length - 1])) {
  1009. marginRight = cells[cells.length - 1];
  1010. cells = cells.slice(0, cells.length - 1);
  1011. }
  1012. else {
  1013. marginRight = "";
  1014. }
  1015. return new TableRow(cells.map(cell => new TableCell(cell)), marginLeft, marginRight);
  1016. }
  1017. /**
  1018. * Reads a table from lines.
  1019. *
  1020. * @private
  1021. * @param {Array<string>} lines - An array of texts, each text represents a row.
  1022. * @returns {Table} The table red from the lines.
  1023. */
  1024. function readTable(lines) {
  1025. return new Table(lines.map(_readRow));
  1026. }
  1027. /**
  1028. * Creates a delimiter text.
  1029. *
  1030. * @private
  1031. * @param {Alignment} alignment
  1032. * @param {number} width - Width of the horizontal bar of delimiter.
  1033. * @returns {string}
  1034. * @throws {Error} Unknown alignment.
  1035. */
  1036. function _delimiterText(alignment, width) {
  1037. const bar = "-".repeat(width);
  1038. switch (alignment) {
  1039. case Alignment.NONE:
  1040. return ` ${bar} `;
  1041. case Alignment.LEFT:
  1042. return `:${bar} `;
  1043. case Alignment.RIGHT:
  1044. return ` ${bar}:`;
  1045. case Alignment.CENTER:
  1046. return `:${bar}:`;
  1047. default:
  1048. throw new Error("Unknown alignment: " + alignment);
  1049. }
  1050. }
  1051. /**
  1052. * Extends array size.
  1053. *
  1054. * @private
  1055. * @param {Array} arr
  1056. * @param {number} size
  1057. * @param {Function} callback - Callback function to fill newly created cells.
  1058. * @returns {Array} Extended array.
  1059. */
  1060. function _extendArray(arr, size, callback) {
  1061. const extended = arr.slice();
  1062. for (let i = arr.length; i < size; i++) {
  1063. extended.push(callback(i, arr));
  1064. }
  1065. return extended;
  1066. }
  1067. /**
  1068. * Completes a table by adding missing delimiter and cells.
  1069. * After completion, all rows in the table have the same width.
  1070. *
  1071. * @private
  1072. * @param {Table} table - A table object.
  1073. * @param {Object} options - An object containing options for completion.
  1074. *
  1075. * | property name | type | description |
  1076. * | ------------------- | -------------- | --------------------------------------------------------- |
  1077. * | `minDelimiterWidth` | {@link number} | Width of delimiters used when completing delimiter cells. |
  1078. *
  1079. * @returns {Object} An object that represents the result of the completion.
  1080. *
  1081. * | property name | type | description |
  1082. * | ------------------- | --------------- | -------------------------------------- |
  1083. * | `table` | {@link Table} | A completed table object. |
  1084. * | `delimiterInserted` | {@link boolean} | `true` if a delimiter row is inserted. |
  1085. *
  1086. * @throws {Error} Empty table.
  1087. */
  1088. function completeTable(table, options) {
  1089. const tableHeight = table.getHeight();
  1090. const tableWidth = table.getWidth();
  1091. if (tableHeight === 0) {
  1092. throw new Error("Empty table");
  1093. }
  1094. const rows = table.getRows();
  1095. const newRows = [];
  1096. // header
  1097. const headerRow = rows[0];
  1098. const headerCells = headerRow.getCells();
  1099. newRows.push(new TableRow(
  1100. _extendArray(headerCells, tableWidth, j => new TableCell(
  1101. j === headerCells.length ? headerRow.marginRight : ""
  1102. )),
  1103. headerRow.marginLeft,
  1104. headerCells.length < tableWidth ? "" : headerRow.marginRight
  1105. ));
  1106. // delimiter
  1107. const delimiterRow = table.getDelimiterRow();
  1108. if (delimiterRow !== undefined) {
  1109. const delimiterCells = delimiterRow.getCells();
  1110. newRows.push(new TableRow(
  1111. _extendArray(delimiterCells, tableWidth, j => new TableCell(
  1112. _delimiterText(
  1113. Alignment.NONE,
  1114. j === delimiterCells.length
  1115. ? Math.max(options.minDelimiterWidth, delimiterRow.marginRight.length - 2)
  1116. : options.minDelimiterWidth
  1117. )
  1118. )),
  1119. delimiterRow.marginLeft,
  1120. delimiterCells.length < tableWidth ? "" : delimiterRow.marginRight
  1121. ));
  1122. }
  1123. else {
  1124. newRows.push(new TableRow(
  1125. _extendArray([], tableWidth, () => new TableCell(
  1126. _delimiterText(Alignment.NONE, options.minDelimiterWidth)
  1127. )),
  1128. "",
  1129. ""
  1130. ));
  1131. }
  1132. // body
  1133. for (let i = delimiterRow !== undefined ? 2 : 1; i < tableHeight; i++) {
  1134. const row = rows[i];
  1135. const cells = row.getCells();
  1136. newRows.push(new TableRow(
  1137. _extendArray(cells, tableWidth, j => new TableCell(
  1138. j === cells.length ? row.marginRight : ""
  1139. )),
  1140. row.marginLeft,
  1141. cells.length < tableWidth ? "" : row.marginRight
  1142. ));
  1143. }
  1144. return {
  1145. table : new Table(newRows),
  1146. delimiterInserted: delimiterRow === undefined
  1147. };
  1148. }
  1149. /**
  1150. * Calculates the width of a text based on characters' EAW properties.
  1151. *
  1152. * @private
  1153. * @param {string} text
  1154. * @param {Object} options -
  1155. *
  1156. * | property name | type |
  1157. * | ----------------- | ---------------------------------- |
  1158. * | `normalize` | {@link boolean} |
  1159. * | `wideChars` | {@link Set}&lt;{@link string} &gt; |
  1160. * | `narrowChars` | {@link Set}&lt;{@link string} &gt; |
  1161. * | `ambiguousAsWide` | {@link boolean} |
  1162. *
  1163. * @returns {number} Calculated width of the text.
  1164. */
  1165. function _computeTextWidth(text, options) {
  1166. const normalized = options.normalize ? text.normalize("NFC") : text;
  1167. let w = 0;
  1168. for (const char of normalized) {
  1169. if (options.wideChars.has(char)) {
  1170. w += 2;
  1171. continue;
  1172. }
  1173. if (options.narrowChars.has(char)) {
  1174. w += 1;
  1175. continue;
  1176. }
  1177. switch (Object(__WEBPACK_IMPORTED_MODULE_0_meaw__["a" /* getEAW */])(char)) {
  1178. case "F":
  1179. case "W":
  1180. w += 2;
  1181. break;
  1182. case "A":
  1183. w += options.ambiguousAsWide ? 2 : 1;
  1184. break;
  1185. default:
  1186. w += 1;
  1187. }
  1188. }
  1189. return w;
  1190. }
  1191. /**
  1192. * Returns a aligned cell content.
  1193. *
  1194. * @private
  1195. * @param {string} text
  1196. * @param {number} width
  1197. * @param {Alignment} alignment
  1198. * @param {Object} options - Options for computing text width.
  1199. * @returns {string}
  1200. * @throws {Error} Unknown alignment.
  1201. * @throws {Error} Unexpected default alignment.
  1202. */
  1203. function _alignText(text, width, alignment, options) {
  1204. const space = width - _computeTextWidth(text, options);
  1205. if (space < 0) {
  1206. return text;
  1207. }
  1208. switch (alignment) {
  1209. case Alignment.NONE:
  1210. throw new Error("Unexpected default alignment");
  1211. case Alignment.LEFT:
  1212. return text + " ".repeat(space);
  1213. case Alignment.RIGHT:
  1214. return " ".repeat(space) + text;
  1215. case Alignment.CENTER:
  1216. return " ".repeat(Math.floor(space / 2))
  1217. + text
  1218. + " ".repeat(Math.ceil(space / 2));
  1219. default:
  1220. throw new Error("Unknown alignment: " + alignment);
  1221. }
  1222. }
  1223. /**
  1224. * Just adds one space paddings to both sides of a text.
  1225. *
  1226. * @private
  1227. * @param {string} text
  1228. * @returns {string}
  1229. */
  1230. function _padText(text) {
  1231. return ` ${text} `;
  1232. }
  1233. /**
  1234. * Formats a table.
  1235. *
  1236. * @private
  1237. * @param {Table} table - A table object.
  1238. * @param {Object} options - An object containing options for formatting.
  1239. *
  1240. * | property name | type | description |
  1241. * | ------------------- | ------------------------ | ------------------------------------------------------- |
  1242. * | `minDelimiterWidth` | {@link number} | Minimum width of delimiters. |
  1243. * | `defaultAlignment` | {@link DefaultAlignment} | Default alignment of columns. |
  1244. * | `headerAlignment` | {@link HeaderAlignment} | Alignment of header cells. |
  1245. * | `textWidthOptions` | {@link Object} | An object containing options for computing text widths. |
  1246. *
  1247. * `options.textWidthOptions` must contain the following options.
  1248. *
  1249. * | property name | type | description |
  1250. * | ----------------- | --------------------------------- | --------------------------------------------------- |
  1251. * | `normalize` | {@link boolean} | Normalize texts before computing text widths. |
  1252. * | `wideChars` | {@link Set}&lt;{@link string}&gt; | Set of characters that should be treated as wide. |
  1253. * | `narrowChars` | {@link Set}&lt;{@link string}&gt; | Set of characters that should be treated as narrow. |
  1254. * | `ambiguousAsWide` | {@link boolean} | Treat East Asian Ambiguous characters as wide. |
  1255. *
  1256. * @returns {Object} An object that represents the result of formatting.
  1257. *
  1258. * | property name | type | description |
  1259. * | --------------- | -------------- | ---------------------------------------------- |
  1260. * | `table` | {@link Table} | A formatted table object. |
  1261. * | `marginLeft` | {@link string} | The common left margin of the formatted table. |
  1262. */
  1263. function _formatTable(table, options) {
  1264. const tableHeight = table.getHeight();
  1265. const tableWidth = table.getWidth();
  1266. if (tableHeight === 0) {
  1267. return {
  1268. table,
  1269. marginLeft: ""
  1270. };
  1271. }
  1272. const marginLeft = table.getRowAt(0).marginLeft;
  1273. if (tableWidth === 0) {
  1274. const rows = new Array(tableHeight).fill()
  1275. .map(() => new TableRow([], marginLeft, ""));
  1276. return {
  1277. table: new Table(rows),
  1278. marginLeft
  1279. };
  1280. }
  1281. // compute column widths
  1282. const delimiterRow = table.getDelimiterRow();
  1283. const columnWidths = new Array(tableWidth).fill(0);
  1284. if (delimiterRow !== undefined) {
  1285. const delimiterRowWidth = delimiterRow.getWidth();
  1286. for (let j = 0; j < delimiterRowWidth; j++) {
  1287. columnWidths[j] = options.minDelimiterWidth;
  1288. }
  1289. }
  1290. for (let i = 0; i < tableHeight; i++) {
  1291. if (delimiterRow !== undefined && i === 1) {
  1292. continue;
  1293. }
  1294. const row = table.getRowAt(i);
  1295. const rowWidth = row.getWidth();
  1296. for (let j = 0; j < rowWidth; j++) {
  1297. columnWidths[j] = Math.max(
  1298. columnWidths[j],
  1299. _computeTextWidth(row.getCellAt(j).content, options.textWidthOptions)
  1300. );
  1301. }
  1302. }
  1303. // get column alignments
  1304. const alignments = delimiterRow !== undefined
  1305. ? _extendArray(
  1306. delimiterRow.getCells().map(cell => cell.getAlignment()),
  1307. tableWidth,
  1308. () => options.defaultAlignment
  1309. )
  1310. : new Array(tableWidth).fill(options.defaultAlignment);
  1311. // format
  1312. const rows = [];
  1313. // header
  1314. const headerRow = table.getRowAt(0);
  1315. rows.push(new TableRow(
  1316. headerRow.getCells().map((cell, j) =>
  1317. new TableCell(_padText(_alignText(
  1318. cell.content,
  1319. columnWidths[j],
  1320. options.headerAlignment === HeaderAlignment.FOLLOW
  1321. ? (alignments[j] === Alignment.NONE ? options.defaultAlignment : alignments[j])
  1322. : options.headerAlignment,
  1323. options.textWidthOptions
  1324. )))
  1325. ),
  1326. marginLeft,
  1327. ""
  1328. ));
  1329. // delimiter
  1330. if (delimiterRow !== undefined) {
  1331. rows.push(new TableRow(
  1332. delimiterRow.getCells().map((cell, j) =>
  1333. new TableCell(_delimiterText(alignments[j], columnWidths[j]))
  1334. ),
  1335. marginLeft,
  1336. ""
  1337. ));
  1338. }
  1339. // body
  1340. for (let i = delimiterRow !== undefined ? 2 : 1; i < tableHeight; i++) {
  1341. const row = table.getRowAt(i);
  1342. rows.push(new TableRow(
  1343. row.getCells().map((cell, j) =>
  1344. new TableCell(_padText(_alignText(
  1345. cell.content,
  1346. columnWidths[j],
  1347. alignments[j] === Alignment.NONE ? options.defaultAlignment : alignments[j],
  1348. options.textWidthOptions
  1349. )))
  1350. ),
  1351. marginLeft,
  1352. ""
  1353. ));
  1354. }
  1355. return {
  1356. table: new Table(rows),
  1357. marginLeft
  1358. };
  1359. }
  1360. /**
  1361. * Formats a table weakly.
  1362. * Rows are formatted independently to each other, cell contents are just trimmed and not aligned.
  1363. * This is useful when using a non-monospaced font or dealing with wide tables.
  1364. *
  1365. * @private
  1366. * @param {Table} table - A table object.
  1367. * @param {Object} options - An object containing options for formatting.
  1368. * The function accepts the same option object for {@link formatTable}, but properties not listed
  1369. * here are just ignored.
  1370. *
  1371. * | property name | type | description |
  1372. * | ------------------- | -------------- | -------------------- |
  1373. * | `minDelimiterWidth` | {@link number} | Width of delimiters. |
  1374. *
  1375. * @returns {Object} An object that represents the result of formatting.
  1376. *
  1377. * | property name | type | description |
  1378. * | --------------- | -------------- | ---------------------------------------------- |
  1379. * | `table` | {@link Table} | A formatted table object. |
  1380. * | `marginLeft` | {@link string} | The common left margin of the formatted table. |
  1381. */
  1382. function _weakFormatTable(table, options) {
  1383. const tableHeight = table.getHeight();
  1384. const tableWidth = table.getWidth();
  1385. if (tableHeight === 0) {
  1386. return {
  1387. table,
  1388. marginLeft: ""
  1389. };
  1390. }
  1391. const marginLeft = table.getRowAt(0).marginLeft;
  1392. if (tableWidth === 0) {
  1393. const rows = new Array(tableHeight).fill()
  1394. .map(() => new TableRow([], marginLeft, ""));
  1395. return {
  1396. table: new Table(rows),
  1397. marginLeft
  1398. };
  1399. }
  1400. const delimiterRow = table.getDelimiterRow();
  1401. // format
  1402. const rows = [];
  1403. // header
  1404. const headerRow = table.getRowAt(0);
  1405. rows.push(new TableRow(
  1406. headerRow.getCells().map(cell =>
  1407. new TableCell(_padText(cell.content))
  1408. ),
  1409. marginLeft,
  1410. ""
  1411. ));
  1412. // delimiter
  1413. if (delimiterRow !== undefined) {
  1414. rows.push(new TableRow(
  1415. delimiterRow.getCells().map(cell =>
  1416. new TableCell(_delimiterText(cell.getAlignment(), options.minDelimiterWidth))
  1417. ),
  1418. marginLeft,
  1419. ""
  1420. ));
  1421. }
  1422. // body
  1423. for (let i = delimiterRow !== undefined ? 2 : 1; i < tableHeight; i++) {
  1424. const row = table.getRowAt(i);
  1425. rows.push(new TableRow(
  1426. row.getCells().map(cell =>
  1427. new TableCell(_padText(cell.content))
  1428. ),
  1429. marginLeft,
  1430. ""
  1431. ));
  1432. }
  1433. return {
  1434. table: new Table(rows),
  1435. marginLeft
  1436. };
  1437. }
  1438. /**
  1439. * Represents table format type.
  1440. *
  1441. * - `FormatType.NORMAL` - Formats table normally.
  1442. * - `FormatType.WEAK` - Formats table weakly, rows are formatted independently to each other, cell
  1443. * contents are just trimmed and not aligned.
  1444. *
  1445. * @type {Object}
  1446. */
  1447. const FormatType = Object.freeze({
  1448. NORMAL: "normal",
  1449. WEAK : "weak"
  1450. });
  1451. /**
  1452. * Formats a table.
  1453. *
  1454. * @private
  1455. * @param {Table} table - A table object.
  1456. * @param {Object} options - An object containing options for formatting.
  1457. *
  1458. * | property name | type | description |
  1459. * | ------------------- | ------------------------ | ------------------------------------------------------- |
  1460. * | `formatType` | {@link FormatType} | Format type, normal or weak. |
  1461. * | `minDelimiterWidth` | {@link number} | Minimum width of delimiters. |
  1462. * | `defaultAlignment` | {@link DefaultAlignment} | Default alignment of columns. |
  1463. * | `headerAlignment` | {@link HeaderAlignment} | Alignment of header cells. |
  1464. * | `textWidthOptions` | {@link Object} | An object containing options for computing text widths. |
  1465. *
  1466. * `options.textWidthOptions` must contain the following options.
  1467. *
  1468. * | property name | type | description |
  1469. * | ----------------- | --------------------------------- | --------------------------------------------------- |
  1470. * | `normalize` | {@link boolean} | Normalize texts before computing text widths. |
  1471. * | `wideChars` | {@link Set}&lt;{@link string}&gt; | Set of characters that should be treated as wide. |
  1472. * | `narrowChars` | {@link Set}&lt;{@link string}&gt; | Set of characters that should be treated as narrow. |
  1473. * | `ambiguousAsWide` | {@link boolean} | Treat East Asian Ambiguous characters as wide. |
  1474. *
  1475. * @returns {Object} An object that represents the result of formatting.
  1476. *
  1477. * | property name | type | description |
  1478. * | --------------- | -------------- | ---------------------------------------------- |
  1479. * | `table` | {@link Table} | A formatted table object. |
  1480. * | `marginLeft` | {@link string} | The common left margin of the formatted table. |
  1481. *
  1482. * @throws {Error} Unknown format type.
  1483. */
  1484. function formatTable(table, options) {
  1485. switch (options.formatType) {
  1486. case FormatType.NORMAL:
  1487. return _formatTable(table, options);
  1488. case FormatType.WEAK:
  1489. return _weakFormatTable(table, options);
  1490. default:
  1491. throw new Error("Unknown format type: " + options.formatType);
  1492. }
  1493. }
  1494. /**
  1495. * Alters a column's alignment of a table.
  1496. *
  1497. * @private
  1498. * @param {Table} table - A completed non-empty table.
  1499. * @param {number} columnIndex - An index of the column.
  1500. * @param {Alignment} alignment - A new alignment of the column.
  1501. * @param {Object} options - An object containing options for completion.
  1502. *
  1503. * | property name | type | description |
  1504. * | ------------------- | -------------- | -------------------- |
  1505. * | `minDelimiterWidth` | {@link number} | Width of delimiters. |
  1506. *
  1507. * @returns {Table} An altered table object.
  1508. * If the column index is out of range, returns the original table.
  1509. */
  1510. function alterAlignment(table, columnIndex, alignment, options) {
  1511. const delimiterRow = table.getRowAt(1);
  1512. if (columnIndex < 0 || delimiterRow.getWidth() - 1 < columnIndex) {
  1513. return table;
  1514. }
  1515. const delimiterCells = delimiterRow.getCells();
  1516. delimiterCells[columnIndex] = new TableCell(_delimiterText(alignment, options.minDelimiterWidth));
  1517. const rows = table.getRows();
  1518. rows[1] = new TableRow(delimiterCells, delimiterRow.marginLeft, delimiterRow.marginRight);
  1519. return new Table(rows);
  1520. }
  1521. /**
  1522. * Inserts a row to a table.
  1523. * The row is always inserted after the header and the delimiter rows, even if the index specifies
  1524. * the header or the delimiter.
  1525. *
  1526. * @private
  1527. * @param {Table} table - A completed non-empty table.
  1528. * @param {number} rowIndex - An row index at which a new row will be inserted.
  1529. * @param {TableRow} row - A table row to be inserted.
  1530. * @returns {Table} An altered table obejct.
  1531. */
  1532. function insertRow(table, rowIndex, row) {
  1533. const rows = table.getRows();
  1534. rows.splice(Math.max(rowIndex, 2), 0, row);
  1535. return new Table(rows);
  1536. }
  1537. /**
  1538. * Deletes a row in a table.
  1539. * If the index specifies the header row, the cells are emptied but the row will not be removed.
  1540. * If the index specifies the delimiter row, it does nothing.
  1541. *
  1542. * @private
  1543. * @param {Table} table - A completed non-empty table.
  1544. * @param {number} rowIndex - An index of the row to be deleted.
  1545. * @returns {Table} An altered table obejct.
  1546. */
  1547. function deleteRow(table, rowIndex) {
  1548. if (rowIndex === 1) {
  1549. return table;
  1550. }
  1551. const rows = table.getRows();
  1552. if (rowIndex === 0) {
  1553. const headerRow = rows[0];
  1554. rows[0] = new TableRow(
  1555. new Array(headerRow.getWidth()).fill(new TableCell("")),
  1556. headerRow.marginLeft,
  1557. headerRow.marginRight
  1558. );
  1559. }
  1560. else {
  1561. rows.splice(rowIndex, 1);
  1562. }
  1563. return new Table(rows);
  1564. }
  1565. /**
  1566. * Moves a row at the index to the specified destination.
  1567. *
  1568. * @private
  1569. * @param {Table} table - A completed non-empty table.
  1570. * @param {number} rowIndex - Index of the row to be moved.
  1571. * @param {number} destIndex - Index of the destination.
  1572. * @returns {Table} An altered table object.
  1573. */
  1574. function moveRow(table, rowIndex, destIndex) {
  1575. if (rowIndex <= 1 || destIndex <= 1 || rowIndex === destIndex) {
  1576. return table;
  1577. }
  1578. const rows = table.getRows();
  1579. const row = rows[rowIndex];
  1580. rows.splice(rowIndex, 1);
  1581. rows.splice(destIndex, 0, row);
  1582. return new Table(rows);
  1583. }
  1584. /**
  1585. * Inserts a column to a table.
  1586. *
  1587. * @private
  1588. * @param {Table} table - A completed non-empty table.
  1589. * @param {number} columnIndex - An column index at which the new column will be inserted.
  1590. * @param {Array<TableCell>} column - An array of cells.
  1591. * @param {Object} options - An object containing options for completion.
  1592. *
  1593. * | property name | type | description |
  1594. * | ------------------- | -------------- | ----------------------- |
  1595. * | `minDelimiterWidth` | {@link number} | Width of the delimiter. |
  1596. *
  1597. * @returns {Table} An altered table obejct.
  1598. */
  1599. function insertColumn(table, columnIndex, column, options) {
  1600. const rows = table.getRows();
  1601. for (let i = 0; i < rows.length; i++) {
  1602. const row = rows[i];
  1603. const cells = rows[i].getCells();
  1604. const cell = i === 1
  1605. ? new TableCell(_delimiterText(Alignment.NONE, options.minDelimiterWidth))
  1606. : column[i > 1 ? i - 1 : i];
  1607. cells.splice(columnIndex, 0, cell);
  1608. rows[i] = new TableRow(cells, row.marginLeft, row.marginRight);
  1609. }
  1610. return new Table(rows);
  1611. }
  1612. /**
  1613. * Deletes a column in a table.
  1614. * If there will be no columns after the deletion, the cells are emptied but the column will not be
  1615. * removed.
  1616. *
  1617. * @private
  1618. * @param {Table} table - A completed non-empty table.
  1619. * @param {number} columnIndex - An index of the column to be deleted.
  1620. * @param {Object} options - An object containing options for completion.
  1621. *
  1622. * | property name | type | description |
  1623. * | ------------------- | -------------- | ----------------------- |
  1624. * | `minDelimiterWidth` | {@link number} | Width of the delimiter. |
  1625. *
  1626. * @returns {Table} An altered table object.
  1627. */
  1628. function deleteColumn(table, columnIndex, options) {
  1629. const rows = table.getRows();
  1630. for (let i = 0; i < rows.length; i++) {
  1631. const row = rows[i];
  1632. let cells = row.getCells();
  1633. if (cells.length <= 1) {
  1634. cells = [new TableCell(i === 1
  1635. ? _delimiterText(Alignment.NONE, options.minDelimiterWidth)
  1636. : ""
  1637. )];
  1638. }
  1639. else {
  1640. cells.splice(columnIndex, 1);
  1641. }
  1642. rows[i] = new TableRow(cells, row.marginLeft, row.marginRight);
  1643. }
  1644. return new Table(rows);
  1645. }
  1646. /**
  1647. * Moves a column at the index to the specified destination.
  1648. *
  1649. * @private
  1650. * @param {Table} table - A completed non-empty table.
  1651. * @param {number} columnIndex - Index of the column to be moved.
  1652. * @param {number} destIndex - Index of the destination.
  1653. * @returns {Table} An altered table object.
  1654. */
  1655. function moveColumn(table, columnIndex, destIndex) {
  1656. if (columnIndex === destIndex) {
  1657. return table;
  1658. }
  1659. const rows = table.getRows();
  1660. for (let i = 0; i < rows.length; i++) {
  1661. const row = rows[i];
  1662. const cells = row.getCells();
  1663. const cell = cells[columnIndex];
  1664. cells.splice(columnIndex, 1);
  1665. cells.splice(destIndex, 0, cell);
  1666. rows[i] = new TableRow(cells, row.marginLeft, row.marginRight);
  1667. }
  1668. return new Table(rows);
  1669. }
  1670. /**
  1671. * The `Insert` class represents an insertion of a line.
  1672. *
  1673. * @private
  1674. */
  1675. class Insert {
  1676. /**
  1677. * Creats a new `Insert` object.
  1678. *
  1679. * @param {number} row - Row index, starts from `0`.
  1680. * @param {string} line - A string to be inserted at the row.
  1681. */
  1682. constructor(row, line) {
  1683. /** @private */
  1684. this._row = row;
  1685. /** @private */
  1686. this._line = line;
  1687. }
  1688. /**
  1689. * Row index, starts from `0`.
  1690. *
  1691. * @type {number}
  1692. */
  1693. get row() {
  1694. return this._row;
  1695. }
  1696. /**
  1697. * A string to be inserted.
  1698. *
  1699. * @type {string}
  1700. */
  1701. get line() {
  1702. return this._line;
  1703. }
  1704. }
  1705. /**
  1706. * The `Delete` class represents a deletion of a line.
  1707. *
  1708. * @private
  1709. */
  1710. class Delete {
  1711. /**
  1712. * Creates a new `Delete` object.
  1713. *
  1714. * @param {number} row - Row index, starts from `0`.
  1715. */
  1716. constructor(row) {
  1717. /** @private */
  1718. this._row = row;
  1719. }
  1720. /**
  1721. * Row index, starts from `0`.
  1722. *
  1723. * @type {number}
  1724. */
  1725. get row() {
  1726. return this._row;
  1727. }
  1728. }
  1729. /**
  1730. * Applies a command to the text editor.
  1731. *
  1732. * @private
  1733. * @param {ITextEditor} textEditor - An interface to the text editor.
  1734. * @param {Insert|Delete} command - A command.
  1735. * @param {number} rowOffset - Offset to the row index of the command.
  1736. * @returns {undefined}
  1737. */
  1738. function _applyCommand(textEditor, command, rowOffset) {
  1739. if (command instanceof Insert) {
  1740. textEditor.insertLine(rowOffset + command.row, command.line);
  1741. }
  1742. else if (command instanceof Delete) {
  1743. textEditor.deleteLine(rowOffset + command.row);
  1744. }
  1745. else {
  1746. throw new Error("Unknown command");
  1747. }
  1748. }
  1749. /**
  1750. * Apply an edit script (array of commands) to the text editor.
  1751. *
  1752. * @private
  1753. * @param {ITextEditor} textEditor - An interface to the text editor.
  1754. * @param {Array<Insert|Delete>} script - An array of commands.
  1755. * The commands are applied sequentially in the order of the array.
  1756. * @param {number} rowOffset - Offset to the row index of the commands.
  1757. * @returns {undefined}
  1758. */
  1759. function applyEditScript(textEditor, script, rowOffset) {
  1760. for (const command of script) {
  1761. _applyCommand(textEditor, command, rowOffset);
  1762. }
  1763. }
  1764. /**
  1765. * Linked list used to remember edit script.
  1766. *
  1767. * @private
  1768. */
  1769. class IList {
  1770. get car() {
  1771. throw new Error("Not implemented");
  1772. }
  1773. get cdr() {
  1774. throw new Error("Not implemented");
  1775. }
  1776. isEmpty() {
  1777. throw new Error("Not implemented");
  1778. }
  1779. unshift(value) {
  1780. return new Cons(value, this);
  1781. }
  1782. toArray() {
  1783. const arr = [];
  1784. let rest = this;
  1785. while (!rest.isEmpty()) {
  1786. arr.push(rest.car);
  1787. rest = rest.cdr;
  1788. }
  1789. return arr;
  1790. }
  1791. }
  1792. /**
  1793. * @private
  1794. */
  1795. class Nil extends IList {
  1796. constructor() {
  1797. super();
  1798. }
  1799. get car() {
  1800. throw new Error("Empty list");
  1801. }
  1802. get cdr() {
  1803. throw new Error("Empty list");
  1804. }
  1805. isEmpty() {
  1806. return true;
  1807. }
  1808. }
  1809. /**
  1810. * @private
  1811. */
  1812. class Cons extends IList {
  1813. constructor(car, cdr) {
  1814. super();
  1815. this._car = car;
  1816. this._cdr = cdr;
  1817. }
  1818. get car() {
  1819. return this._car;
  1820. }
  1821. get cdr() {
  1822. return this._cdr;
  1823. }
  1824. isEmpty() {
  1825. return false;
  1826. }
  1827. }
  1828. const nil = new Nil();
  1829. /**
  1830. * Computes the shortest edit script between two arrays of strings.
  1831. *
  1832. * @private
  1833. * @param {Array<string>} from - An array of string the edit starts from.
  1834. * @param {Array<string>} to - An array of string the edit goes to.
  1835. * @param {number} [limit=-1] - Upper limit of edit distance to be searched.
  1836. * If negative, there is no limit.
  1837. * @returns {Array<Insert|Delete>|undefined} The shortest edit script that turns `from` into `to`;
  1838. * `undefined` if no edit script is found in the given range.
  1839. */
  1840. function shortestEditScript(from, to, limit = -1) {
  1841. const fromLen = from.length;
  1842. const toLen = to.length;
  1843. const maxd = limit >= 0 ? Math.min(limit, fromLen + toLen) : fromLen + toLen;
  1844. const mem = new Array(Math.min(maxd, fromLen) + Math.min(maxd, toLen) + 1);
  1845. const offset = Math.min(maxd, fromLen);
  1846. for (let d = 0; d <= maxd; d++) {
  1847. const mink = d <= fromLen ? -d : d - 2 * fromLen;
  1848. const maxk = d <= toLen ? d : -d + 2 * toLen;
  1849. for (let k = mink; k <= maxk; k += 2) {
  1850. let i;
  1851. let script;
  1852. if (d === 0) {
  1853. i = 0;
  1854. script = nil;
  1855. }
  1856. else if (k === -d) {
  1857. i = mem[offset + k + 1].i + 1;
  1858. script = mem[offset + k + 1].script.unshift(new Delete(i + k));
  1859. }
  1860. else if (k === d) {
  1861. i = mem[offset + k - 1].i;
  1862. script = mem[offset + k - 1].script.unshift(new Insert(i + k - 1, to[i + k - 1]));
  1863. }
  1864. else {
  1865. const vi = mem[offset + k + 1].i + 1;
  1866. const hi = mem[offset + k - 1].i;
  1867. if (vi > hi) {
  1868. i = vi;
  1869. script = mem[offset + k + 1].script.unshift(new Delete(i + k));
  1870. }
  1871. else {
  1872. i = hi;
  1873. script = mem[offset + k - 1].script.unshift(new Insert(i + k - 1, to[i + k - 1]));
  1874. }
  1875. }
  1876. while (i < fromLen && i + k < toLen && from[i] === to[i + k]) {
  1877. i += 1;
  1878. }
  1879. if (k === toLen - fromLen && i === fromLen) {
  1880. return script.toArray().reverse();
  1881. }
  1882. mem[offset + k] = { i, script };
  1883. }
  1884. }
  1885. return undefined;
  1886. }
  1887. /**
  1888. * The `ITextEditor` represents an interface to a text editor.
  1889. *
  1890. * @interface
  1891. */
  1892. class ITextEditor {
  1893. /**
  1894. * Gets the current cursor position.
  1895. *
  1896. * @returns {Point} A point object that represents the cursor position.
  1897. */
  1898. getCursorPosition() {
  1899. throw new Error("Not implemented: getCursorPosition");
  1900. }
  1901. /**
  1902. * Sets the cursor position to a specified one.
  1903. *
  1904. * @param {Point} pos - A point object which the cursor position is set to.
  1905. * @returns {undefined}
  1906. */
  1907. setCursorPosition(pos) {
  1908. throw new Error("Not implemented: setCursorPosition");
  1909. }
  1910. /**
  1911. * Sets the selection range.
  1912. * This method also expects the cursor position to be moved as the end of the selection range.
  1913. *
  1914. * @param {Range} range - A range object that describes a selection range.
  1915. * @returns {undefined}
  1916. */
  1917. setSelectionRange(range) {
  1918. throw new Error("Not implemented: setSelectionRange");
  1919. }
  1920. /**
  1921. * Gets the last row index of the text editor.
  1922. *
  1923. * @returns {number} The last row index.
  1924. */
  1925. getLastRow() {
  1926. throw new Error("Not implemented: getLastRow");
  1927. }
  1928. /**
  1929. * Checks if the editor accepts a table at a row to be editted.
  1930. * It should return `false` if, for example, the row is in a code block (not Markdown).
  1931. *
  1932. * @param {number} row - A row index in the text editor.
  1933. * @returns {boolean} `true` if the table at the row can be editted.
  1934. */
  1935. acceptsTableEdit(row) {
  1936. throw new Error("Not implemented: acceptsTableEdit");
  1937. }
  1938. /**
  1939. * Gets a line string at a row.
  1940. *
  1941. * @param {number} row - Row index, starts from `0`.
  1942. * @returns {string} The line at the specified row.
  1943. * The line must not contain an EOL like `"\n"` or `"\r"`.
  1944. */
  1945. getLine(row) {
  1946. throw new Error("Not implemented: getLine");
  1947. }
  1948. /**
  1949. * Inserts a line at a specified row.
  1950. *
  1951. * @param {number} row - Row index, starts from `0`.
  1952. * @param {string} line - A string to be inserted.
  1953. * This must not contain an EOL like `"\n"` or `"\r"`.
  1954. * @return {undefined}
  1955. */
  1956. insertLine(row, line) {
  1957. throw new Error("Not implemented: insertLine");
  1958. }
  1959. /**
  1960. * Deletes a line at a specified row.
  1961. *
  1962. * @param {number} row - Row index, starts from `0`.
  1963. * @returns {undefined}
  1964. */
  1965. deleteLine(row) {
  1966. throw new Error("Not implemented: deleteLine");
  1967. }
  1968. /**
  1969. * Replace lines in a specified range.
  1970. *
  1971. * @param {number} startRow - Start row index, starts from `0`.
  1972. * @param {number} endRow - End row index.
  1973. * Lines from `startRow` to `endRow - 1` is replaced.
  1974. * @param {Array<string>} lines - An array of string.
  1975. * Each strings must not contain an EOL like `"\n"` or `"\r"`.
  1976. * @returns {undefined}
  1977. */
  1978. replaceLines(startRow, endRow, lines) {
  1979. throw new Error("Not implemented: replaceLines");
  1980. }
  1981. /**
  1982. * Batches multiple operations as a single undo/redo step.
  1983. *
  1984. * @param {Function} func - A callback function that executes some operations on the text editor.
  1985. * @returns {undefined}
  1986. */
  1987. transact(func) {
  1988. throw new Error("Not implemented: transact");
  1989. }
  1990. }
  1991. /**
  1992. * Reads a property of an object if exists; otherwise uses a default value.
  1993. *
  1994. * @private
  1995. * @param {*} obj - An object. If a non-object value is specified, the default value is used.
  1996. * @param {string} key - A key (or property name).
  1997. * @param {*} defaultVal - A default value that is used when a value does not exist.
  1998. * @returns {*} A read value or the default value.
  1999. */
  2000. function _value(obj, key, defaultVal) {
  2001. return (typeof obj === "object" && obj !== null && obj[key] !== undefined)
  2002. ? obj[key]
  2003. : defaultVal;
  2004. }
  2005. /**
  2006. * Reads multiple properties of an object if exists; otherwise uses default values.
  2007. *
  2008. * @private
  2009. * @param {*} obj - An object. If a non-object value is specified, the default value is used.
  2010. * @param {Object} keys - An object that consists of pairs of a key and a default value.
  2011. * @returns {Object} A new object that contains read values.
  2012. */
  2013. function _values(obj, keys) {
  2014. const res = {};
  2015. for (const [key, defaultVal] of Object.entries(keys)) {
  2016. res[key] = _value(obj, key, defaultVal);
  2017. }
  2018. return res;
  2019. }
  2020. /**
  2021. * Reads options for the formatter from an object.
  2022. * The default values are used for options that are not specified.
  2023. *
  2024. * @param {Object} obj - An object containing options.
  2025. * The available options and default values are listed below.
  2026. *
  2027. * | property name | type | description | default value |
  2028. * | ------------------- | ------------------------ | ------------------------------------------------------- | ------------------------ |
  2029. * | `formatType` | {@link FormatType} | Format type, normal or weak. | `FormatType.NORMAL` |
  2030. * | `minDelimiterWidth` | {@link number} | Minimum width of delimiters. | `3` |
  2031. * | `defaultAlignment` | {@link DefaultAlignment} | Default alignment of columns. | `DefaultAlignment.LEFT` |
  2032. * | `headerAlignment` | {@link HeaderAlignment} | Alignment of header cells. | `HeaderAlignment.FOLLOW` |
  2033. * | `textWidthOptions` | {@link Object} | An object containing options for computing text widths. | |
  2034. * | `smartCursor` | {@link boolean} | Enables "Smart Cursor" feature. | `false` |
  2035. *
  2036. * The available options for `obj.textWidthOptions` are the following ones.
  2037. *
  2038. * | property name | type | description | default value |
  2039. * | ----------------- | --------------------------------- | ----------------------------------------------------- | ------------- |
  2040. * | `normalize` | {@link boolean} | Normalizes texts before computing text widths. | `true` |
  2041. * | `wideChars` | {@link Set}&lt;{@link string}&gt; | A set of characters that should be treated as wide. | `new Set()` |
  2042. * | `narrowChars` | {@link Set}&lt;{@link string}&gt; | A set of characters that should be treated as narrow. | `new Set()` |
  2043. * | `ambiguousAsWide` | {@link boolean} | Treats East Asian Ambiguous characters as wide. | `false` |
  2044. *
  2045. * @returns {Object} - An object that contains complete options.
  2046. */
  2047. function options(obj) {
  2048. const res = _values(obj, {
  2049. formatType : FormatType.NORMAL,
  2050. minDelimiterWidth: 3,
  2051. defaultAlignment : DefaultAlignment.LEFT,
  2052. headerAlignment : HeaderAlignment.FOLLOW,
  2053. smartCursor : false
  2054. });
  2055. res.textWidthOptions = _values(obj.textWidthOptions, {
  2056. normalize : true,
  2057. wideChars : new Set(),
  2058. narrowChars : new Set(),
  2059. ambiguousAsWide: false
  2060. });
  2061. return res;
  2062. }
  2063. /**
  2064. * Checks if a line is a table row.
  2065. *
  2066. * @private
  2067. * @param {string} line - A string.
  2068. * @returns {boolean} `true` if the given line starts with a pipe `|`.
  2069. */
  2070. function _isTableRow(line) {
  2071. return line.trimLeft()[0] === "|";
  2072. }
  2073. /**
  2074. * Computes new focus offset from information of completed and formatted tables.
  2075. *
  2076. * @private
  2077. * @param {Focus} focus - A focus.
  2078. * @param {Table} table - A completed but not formatted table with original cell contents.
  2079. * @param {Object} formatted - Information of the formatted table.
  2080. * @param {boolean} moved - Indicates whether the focus position is moved by a command or not.
  2081. * @returns {number}
  2082. */
  2083. function _computeNewOffset(focus, table, formatted, moved) {
  2084. if (moved) {
  2085. const formattedFocusedCell = formatted.table.getFocusedCell(focus);
  2086. if (formattedFocusedCell !== undefined) {
  2087. return formattedFocusedCell.computeRawOffset(0);
  2088. }
  2089. else {
  2090. return focus.column < 0 ? formatted.marginLeft.length : 0;
  2091. }
  2092. }
  2093. else {
  2094. const focusedCell = table.getFocusedCell(focus);
  2095. const formattedFocusedCell = formatted.table.getFocusedCell(focus);
  2096. if (focusedCell !== undefined && formattedFocusedCell !== undefined) {
  2097. const contentOffset = Math.min(
  2098. focusedCell.computeContentOffset(focus.offset),
  2099. formattedFocusedCell.content.length
  2100. );
  2101. return formattedFocusedCell.computeRawOffset(contentOffset);
  2102. }
  2103. else {
  2104. return focus.column < 0 ? formatted.marginLeft.length : 0;
  2105. }
  2106. }
  2107. }
  2108. /**
  2109. * The `TableEditor` class is at the center of the markdown-table-editor.
  2110. * When a command is executed, it reads a table from the text editor, does some operation on the
  2111. * table, and then apply the result to the text editor.
  2112. *
  2113. * To use this class, the text editor (or an interface to it) must implement {@link ITextEditor}.
  2114. */
  2115. class TableEditor {
  2116. /**
  2117. * Creates a new table editor instance.
  2118. *
  2119. * @param {ITextEditor} textEditor - A text editor interface.
  2120. */
  2121. constructor(textEditor) {
  2122. /** @private */
  2123. this._textEditor = textEditor;
  2124. // smart cursor
  2125. /** @private */
  2126. this._scActive = false;
  2127. /** @private */
  2128. this._scTablePos = null;
  2129. /** @private */
  2130. this._scStartFocus = null;
  2131. /** @private */
  2132. this._scLastFocus = null;
  2133. }
  2134. /**
  2135. * Resets the smart cursor.
  2136. * Call this method when the table editor is inactivated.
  2137. *
  2138. * @returns {undefined}
  2139. */
  2140. resetSmartCursor() {
  2141. this._scActive = false;
  2142. }
  2143. /**
  2144. * Checks if the cursor is in a table row.
  2145. * This is useful to check whether the table editor should be activated or not.
  2146. *
  2147. * @returns {boolean} `true` if the cursor is in a table row.
  2148. */
  2149. cursorIsInTable() {
  2150. const pos = this._textEditor.getCursorPosition();
  2151. return this._textEditor.acceptsTableEdit(pos.row)
  2152. && _isTableRow(this._textEditor.getLine(pos.row));
  2153. }
  2154. /**
  2155. * Finds a table under the current cursor position.
  2156. *
  2157. * @private
  2158. * @returns {Object|undefined} An object that contains information about the table;
  2159. * `undefined` if there is no table.
  2160. * The return object contains the properties listed in the table.
  2161. *
  2162. * | property name | type | description |
  2163. * | --------------- | ----------------------------------- | ------------------------------------------------------------------------ |
  2164. * | `range` | {@link Range} | The range of the table. |
  2165. * | `lines` | {@link Array}&lt;{@link string}&gt; | An array of the lines in the range. |
  2166. * | `table` | {@link Table} | A table object read from the text editor. |
  2167. * | `focus` | {@link Focus} | A focus object that represents the current cursor position in the table. |
  2168. */
  2169. _findTable() {
  2170. const pos = this._textEditor.getCursorPosition();
  2171. const lastRow = this._textEditor.getLastRow();
  2172. const lines = [];
  2173. let startRow = pos.row;
  2174. let endRow = pos.row;
  2175. // current line
  2176. {
  2177. const line = this._textEditor.getLine(pos.row);
  2178. if (!this._textEditor.acceptsTableEdit(pos.row) || !_isTableRow(line)) {
  2179. return undefined;
  2180. }
  2181. lines.push(line);
  2182. }
  2183. // previous lines
  2184. for (let row = pos.row - 1; row >= 0; row--) {
  2185. const line = this._textEditor.getLine(row);
  2186. if (!this._textEditor.acceptsTableEdit(row) || !_isTableRow(line)) {
  2187. break;
  2188. }
  2189. lines.unshift(line);
  2190. startRow = row;
  2191. }
  2192. // next lines
  2193. for (let row = pos.row + 1; row <= lastRow; row++) {
  2194. const line = this._textEditor.getLine(row);
  2195. if (!this._textEditor.acceptsTableEdit(row) || !_isTableRow(line)) {
  2196. break;
  2197. }
  2198. lines.push(line);
  2199. endRow = row;
  2200. }
  2201. const range = new Range(
  2202. new Point(startRow, 0),
  2203. new Point(endRow, lines[lines.length - 1].length)
  2204. );
  2205. const table = readTable(lines);
  2206. const focus = table.focusOfPosition(pos, startRow);
  2207. return { range, lines, table, focus };
  2208. }
  2209. /**
  2210. * Finds a table and does an operation with it.
  2211. *
  2212. * @private
  2213. * @param {Function} func - A function that does some operation on table information obtained by
  2214. * {@link TableEditor#_findTable}.
  2215. * @returns {undefined}
  2216. */
  2217. _withTable(func) {
  2218. const info = this._findTable();
  2219. if (info === undefined) {
  2220. return;
  2221. }
  2222. func(info);
  2223. }
  2224. /**
  2225. * Updates lines in a given range in the text editor.
  2226. *
  2227. * @private
  2228. * @param {number} startRow - Start row index, starts from `0`.
  2229. * @param {number} endRow - End row index.
  2230. * Lines from `startRow` to `endRow - 1` are replaced.
  2231. * @param {Array<string>} newLines - New lines.
  2232. * @param {Array<string>} [oldLines=undefined] - Old lines to be replaced.
  2233. * @returns {undefined}
  2234. */
  2235. _updateLines(startRow, endRow, newLines, oldLines = undefined) {
  2236. if (oldLines !== undefined) {
  2237. // apply the shortest edit script
  2238. // if a table is edited in a normal manner, the edit distance never exceeds 3
  2239. const ses = shortestEditScript(oldLines, newLines, 3);
  2240. if (ses !== undefined) {
  2241. applyEditScript(this._textEditor, ses, startRow);
  2242. return;
  2243. }
  2244. }
  2245. this._textEditor.replaceLines(startRow, endRow, newLines);
  2246. }
  2247. /**
  2248. * Moves the cursor position to the focused cell,
  2249. *
  2250. * @private
  2251. * @param {number} startRow - Row index where the table starts in the text editor.
  2252. * @param {Table} table - A table.
  2253. * @param {Focus} focus - A focus to which the cursor will be moved.
  2254. * @returns {undefined}
  2255. */
  2256. _moveToFocus(startRow, table, focus) {
  2257. const pos = table.positionOfFocus(focus, startRow);
  2258. if (pos !== undefined) {
  2259. this._textEditor.setCursorPosition(pos);
  2260. }
  2261. }
  2262. /**
  2263. * Selects the focused cell.
  2264. * If the cell has no content to be selected, then just moves the cursor position.
  2265. *
  2266. * @private
  2267. * @param {number} startRow - Row index where the table starts in the text editor.
  2268. * @param {Table} table - A table.
  2269. * @param {Focus} focus - A focus to be selected.
  2270. * @returns {undefined}
  2271. */
  2272. _selectFocus(startRow, table, focus) {
  2273. const range = table.selectionRangeOfFocus(focus, startRow);
  2274. if (range !== undefined) {
  2275. this._textEditor.setSelectionRange(range);
  2276. }
  2277. else {
  2278. this._moveToFocus(startRow, table, focus);
  2279. }
  2280. }
  2281. /**
  2282. * Formats the table under the cursor.
  2283. *
  2284. * @param {Object} options - See {@link options}.
  2285. * @returns {undefined}
  2286. */
  2287. format(options) {
  2288. this._withTable(({ range, lines, table, focus }) => {
  2289. let newFocus = focus;
  2290. // complete
  2291. const completed = completeTable(table, options);
  2292. if (completed.delimiterInserted && newFocus.row > 0) {
  2293. newFocus = newFocus.setRow(newFocus.row + 1);
  2294. }
  2295. // format
  2296. const formatted = formatTable(completed.table, options);
  2297. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, completed.table, formatted, false));
  2298. // apply
  2299. this._textEditor.transact(() => {
  2300. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2301. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2302. });
  2303. });
  2304. }
  2305. /**
  2306. * Formats and escapes from the table.
  2307. *
  2308. * @param {Object} options - See {@link options}.
  2309. * @returns {undefined}
  2310. */
  2311. escape(options) {
  2312. this._withTable(({ range, lines, table, focus }) => {
  2313. // complete
  2314. const completed = completeTable(table, options);
  2315. // format
  2316. const formatted = formatTable(completed.table, options);
  2317. // apply
  2318. const newPos = new Point(range.end.row + (completed.delimiterInserted ? 2 : 1), 0);
  2319. this._textEditor.transact(() => {
  2320. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2321. if (newPos.row > this._textEditor.getLastRow()) {
  2322. this._textEditor.insertLine(newPos.row, "");
  2323. }
  2324. this._textEditor.setCursorPosition(newPos);
  2325. });
  2326. this.resetSmartCursor();
  2327. });
  2328. }
  2329. /**
  2330. * Alters the alignment of the focused column.
  2331. *
  2332. * @param {Alignment} alignment - New alignment.
  2333. * @param {Object} options - See {@link options}.
  2334. * @returns {undefined}
  2335. */
  2336. alignColumn(alignment, options) {
  2337. this._withTable(({ range, lines, table, focus }) => {
  2338. let newFocus = focus;
  2339. // complete
  2340. const completed = completeTable(table, options);
  2341. if (completed.delimiterInserted && newFocus.row > 0) {
  2342. newFocus = newFocus.setRow(newFocus.row + 1);
  2343. }
  2344. // alter alignment
  2345. let altered = completed.table;
  2346. if (0 <= newFocus.column && newFocus.column <= altered.getHeaderWidth() - 1) {
  2347. altered = alterAlignment(completed.table, newFocus.column, alignment, options);
  2348. }
  2349. // format
  2350. const formatted = formatTable(altered, options);
  2351. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, completed.table, formatted, false));
  2352. // apply
  2353. this._textEditor.transact(() => {
  2354. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2355. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2356. });
  2357. });
  2358. }
  2359. /**
  2360. * Selects the focused cell content.
  2361. *
  2362. * @param {Object} options - See {@link options}.
  2363. * @returns {undefined}
  2364. */
  2365. selectCell(options) {
  2366. this._withTable(({ range, lines, table, focus }) => {
  2367. let newFocus = focus;
  2368. // complete
  2369. const completed = completeTable(table, options);
  2370. if (completed.delimiterInserted && newFocus.row > 0) {
  2371. newFocus = newFocus.setRow(newFocus.row + 1);
  2372. }
  2373. // format
  2374. const formatted = formatTable(completed.table, options);
  2375. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, completed.table, formatted, false));
  2376. // apply
  2377. this._textEditor.transact(() => {
  2378. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2379. this._selectFocus(range.start.row, formatted.table, newFocus);
  2380. });
  2381. });
  2382. }
  2383. /**
  2384. * Moves the focus to another cell.
  2385. *
  2386. * @param {number} rowOffset - Offset in row.
  2387. * @param {number} columnOffset - Offset in column.
  2388. * @param {Object} options - See {@link options}.
  2389. * @returns {undefined}
  2390. */
  2391. moveFocus(rowOffset, columnOffset, options) {
  2392. this._withTable(({ range, lines, table, focus }) => {
  2393. let newFocus = focus;
  2394. // complete
  2395. const completed = completeTable(table, options);
  2396. if (completed.delimiterInserted && newFocus.row > 0) {
  2397. newFocus = newFocus.setRow(newFocus.row + 1);
  2398. }
  2399. const startFocus = newFocus;
  2400. // move focus
  2401. if (rowOffset !== 0) {
  2402. const height = completed.table.getHeight();
  2403. // skip delimiter row
  2404. const skip =
  2405. newFocus.row < 1 && newFocus.row + rowOffset >= 1 ? 1
  2406. : newFocus.row > 1 && newFocus.row + rowOffset <= 1 ? -1
  2407. : 0;
  2408. newFocus = newFocus.setRow(
  2409. Math.min(Math.max(newFocus.row + rowOffset + skip, 0), height <= 2 ? 0 : height - 1)
  2410. );
  2411. }
  2412. if (columnOffset !== 0) {
  2413. const width = completed.table.getHeaderWidth();
  2414. if (!(newFocus.column < 0 && columnOffset < 0)
  2415. && !(newFocus.column > width - 1 && columnOffset > 0)) {
  2416. newFocus = newFocus.setColumn(
  2417. Math.min(Math.max(newFocus.column + columnOffset, 0), width - 1)
  2418. );
  2419. }
  2420. }
  2421. const moved = !newFocus.posEquals(startFocus);
  2422. // format
  2423. const formatted = formatTable(completed.table, options);
  2424. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, completed.table, formatted, moved));
  2425. // apply
  2426. this._textEditor.transact(() => {
  2427. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2428. if (moved) {
  2429. this._selectFocus(range.start.row, formatted.table, newFocus);
  2430. }
  2431. else {
  2432. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2433. }
  2434. });
  2435. if (moved) {
  2436. this.resetSmartCursor();
  2437. }
  2438. });
  2439. }
  2440. /**
  2441. * Moves the focus to the next cell.
  2442. *
  2443. * @param {Object} options - See {@link options}.
  2444. * @returns {undefined}
  2445. */
  2446. nextCell(options) {
  2447. this._withTable(({ range, lines, table, focus }) => {
  2448. // reset smart cursor if moved
  2449. const focusMoved = (this._scTablePos !== null && !range.start.equals(this._scTablePos))
  2450. || (this._scLastFocus !== null && !focus.posEquals(this._scLastFocus));
  2451. if (this._scActive && focusMoved) {
  2452. this.resetSmartCursor();
  2453. }
  2454. let newFocus = focus;
  2455. // complete
  2456. const completed = completeTable(table, options);
  2457. if (completed.delimiterInserted && newFocus.row > 0) {
  2458. newFocus = newFocus.setRow(newFocus.row + 1);
  2459. }
  2460. const startFocus = newFocus;
  2461. let altered = completed.table;
  2462. // move focus
  2463. if (newFocus.row === 1) {
  2464. // move to next row
  2465. newFocus = newFocus.setRow(2);
  2466. if (options.smartCursor) {
  2467. if (newFocus.column < 0 || altered.getHeaderWidth() - 1 < newFocus.column) {
  2468. newFocus = newFocus.setColumn(0);
  2469. }
  2470. }
  2471. else {
  2472. newFocus = newFocus.setColumn(0);
  2473. }
  2474. // insert an empty row if needed
  2475. if (newFocus.row > altered.getHeight() - 1) {
  2476. const row = new Array(altered.getHeaderWidth()).fill(new TableCell(""));
  2477. altered = insertRow(altered, altered.getHeight(), new TableRow(row, "", ""));
  2478. }
  2479. }
  2480. else {
  2481. // insert an empty column if needed
  2482. if (newFocus.column > altered.getHeaderWidth() - 1) {
  2483. const column = new Array(altered.getHeight() - 1).fill(new TableCell(""));
  2484. altered = insertColumn(altered, altered.getHeaderWidth(), column, options);
  2485. }
  2486. // move to next column
  2487. newFocus = newFocus.setColumn(newFocus.column + 1);
  2488. }
  2489. // format
  2490. const formatted = formatTable(altered, options);
  2491. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, true));
  2492. // apply
  2493. const newLines = formatted.table.toLines();
  2494. if (newFocus.column > formatted.table.getHeaderWidth() - 1) {
  2495. // add margin
  2496. newLines[newFocus.row] += " ";
  2497. newFocus = newFocus.setOffset(1);
  2498. }
  2499. this._textEditor.transact(() => {
  2500. this._updateLines(range.start.row, range.end.row + 1, newLines, lines);
  2501. this._selectFocus(range.start.row, formatted.table, newFocus);
  2502. });
  2503. if (options.smartCursor) {
  2504. if (!this._scActive) {
  2505. // activate smart cursor
  2506. this._scActive = true;
  2507. this._scTablePos = range.start;
  2508. if (startFocus.column < 0 || formatted.table.getHeaderWidth() - 1 < startFocus.column) {
  2509. this._scStartFocus = new Focus(startFocus.row, 0, 0);
  2510. }
  2511. else {
  2512. this._scStartFocus = startFocus;
  2513. }
  2514. }
  2515. this._scLastFocus = newFocus;
  2516. }
  2517. });
  2518. }
  2519. /**
  2520. * Moves the focus to the previous cell.
  2521. *
  2522. * @param {Object} options - See {@link options}.
  2523. * @returns {undefined}
  2524. */
  2525. previousCell(options) {
  2526. this._withTable(({ range, lines, table, focus }) => {
  2527. let newFocus = focus;
  2528. // complete
  2529. const completed = completeTable(table, options);
  2530. if (completed.delimiterInserted && newFocus.row > 0) {
  2531. newFocus = newFocus.setRow(newFocus.row + 1);
  2532. }
  2533. const startFocus = newFocus;
  2534. // move focus
  2535. if (newFocus.row === 0) {
  2536. if (newFocus.column > 0) {
  2537. newFocus = newFocus.setColumn(newFocus.column - 1);
  2538. }
  2539. }
  2540. else if (newFocus.row === 1) {
  2541. newFocus = new Focus(0, completed.table.getHeaderWidth() - 1, newFocus.offset);
  2542. }
  2543. else {
  2544. if (newFocus.column > 0) {
  2545. newFocus = newFocus.setColumn(newFocus.column - 1);
  2546. }
  2547. else {
  2548. newFocus = new Focus(
  2549. newFocus.row === 2 ? 0 : newFocus.row - 1,
  2550. completed.table.getHeaderWidth() - 1,
  2551. newFocus.offset
  2552. );
  2553. }
  2554. }
  2555. const moved = !newFocus.posEquals(startFocus);
  2556. // format
  2557. const formatted = formatTable(completed.table, options);
  2558. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, completed.table, formatted, moved));
  2559. // apply
  2560. this._textEditor.transact(() => {
  2561. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2562. if (moved) {
  2563. this._selectFocus(range.start.row, formatted.table, newFocus);
  2564. }
  2565. else {
  2566. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2567. }
  2568. });
  2569. if (moved) {
  2570. this.resetSmartCursor();
  2571. }
  2572. });
  2573. }
  2574. /**
  2575. * Moves the focus to the next row.
  2576. *
  2577. * @param {Object} options - See {@link options}.
  2578. * @returns {undefined}
  2579. */
  2580. nextRow(options) {
  2581. this._withTable(({ range, lines, table, focus }) => {
  2582. // reset smart cursor if moved
  2583. const focusMoved = (this._scTablePos !== null && !range.start.equals(this._scTablePos))
  2584. || (this._scLastFocus !== null && !focus.posEquals(this._scLastFocus));
  2585. if (this._scActive && focusMoved) {
  2586. this.resetSmartCursor();
  2587. }
  2588. let newFocus = focus;
  2589. // complete
  2590. const completed = completeTable(table, options);
  2591. if (completed.delimiterInserted && newFocus.row > 0) {
  2592. newFocus = newFocus.setRow(newFocus.row + 1);
  2593. }
  2594. const startFocus = newFocus;
  2595. let altered = completed.table;
  2596. // move focus
  2597. if (newFocus.row === 0) {
  2598. newFocus = newFocus.setRow(2);
  2599. }
  2600. else {
  2601. newFocus = newFocus.setRow(newFocus.row + 1);
  2602. }
  2603. if (options.smartCursor) {
  2604. if (this._scActive) {
  2605. newFocus = newFocus.setColumn(this._scStartFocus.column);
  2606. }
  2607. else if (newFocus.column < 0 || altered.getHeaderWidth() - 1 < newFocus.column) {
  2608. newFocus = newFocus.setColumn(0);
  2609. }
  2610. }
  2611. else {
  2612. newFocus = newFocus.setColumn(0);
  2613. }
  2614. // insert empty row if needed
  2615. if (newFocus.row > altered.getHeight() - 1) {
  2616. const row = new Array(altered.getHeaderWidth()).fill(new TableCell(""));
  2617. altered = insertRow(altered, altered.getHeight(), new TableRow(row, "", ""));
  2618. }
  2619. // format
  2620. const formatted = formatTable(altered, options);
  2621. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, true));
  2622. // apply
  2623. this._textEditor.transact(() => {
  2624. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2625. this._selectFocus(range.start.row, formatted.table, newFocus);
  2626. });
  2627. if (options.smartCursor) {
  2628. if (!this._scActive) {
  2629. // activate smart cursor
  2630. this._scActive = true;
  2631. this._scTablePos = range.start;
  2632. if (startFocus.column < 0 || formatted.table.getHeaderWidth() - 1 < startFocus.column) {
  2633. this._scStartFocus = new Focus(startFocus.row, 0, 0);
  2634. }
  2635. else {
  2636. this._scStartFocus = startFocus;
  2637. }
  2638. }
  2639. this._scLastFocus = newFocus;
  2640. }
  2641. });
  2642. }
  2643. /**
  2644. * Inserts an empty row at the current focus.
  2645. *
  2646. * @param {Object} options - See {@link options}.
  2647. * @returns {undefined}
  2648. */
  2649. insertRow(options) {
  2650. this._withTable(({ range, lines, table, focus }) => {
  2651. let newFocus = focus;
  2652. // complete
  2653. const completed = completeTable(table, options);
  2654. if (completed.delimiterInserted && newFocus.row > 0) {
  2655. newFocus = newFocus.setRow(newFocus.row + 1);
  2656. }
  2657. // move focus
  2658. if (newFocus.row <= 1) {
  2659. newFocus = newFocus.setRow(2);
  2660. }
  2661. newFocus = newFocus.setColumn(0);
  2662. // insert an empty row
  2663. const row = new Array(completed.table.getHeaderWidth()).fill(new TableCell(""));
  2664. const altered = insertRow(completed.table, newFocus.row, new TableRow(row, "", ""));
  2665. // format
  2666. const formatted = formatTable(altered, options);
  2667. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, true));
  2668. // apply
  2669. this._textEditor.transact(() => {
  2670. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2671. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2672. });
  2673. this.resetSmartCursor();
  2674. });
  2675. }
  2676. /**
  2677. * Deletes a row at the current focus.
  2678. *
  2679. * @param {Object} options - See {@link options}.
  2680. * @returns {undefined}
  2681. */
  2682. deleteRow(options) {
  2683. this._withTable(({ range, lines, table, focus }) => {
  2684. let newFocus = focus;
  2685. // complete
  2686. const completed = completeTable(table, options);
  2687. if (completed.delimiterInserted && newFocus.row > 0) {
  2688. newFocus = newFocus.setRow(newFocus.row + 1);
  2689. }
  2690. // delete a row
  2691. let altered = completed.table;
  2692. let moved = false;
  2693. if (newFocus.row !== 1) {
  2694. altered = deleteRow(altered, newFocus.row);
  2695. moved = true;
  2696. if (newFocus.row > altered.getHeight() - 1) {
  2697. newFocus = newFocus.setRow(newFocus.row === 2 ? 0 : newFocus.row - 1);
  2698. }
  2699. }
  2700. // format
  2701. const formatted = formatTable(altered, options);
  2702. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, moved));
  2703. // apply
  2704. this._textEditor.transact(() => {
  2705. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2706. if (moved) {
  2707. this._selectFocus(range.start.row, formatted.table, newFocus);
  2708. }
  2709. else {
  2710. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2711. }
  2712. });
  2713. this.resetSmartCursor();
  2714. });
  2715. }
  2716. /**
  2717. * Moves the focused row by the specified offset.
  2718. *
  2719. * @param {number} offset - An offset the row is moved by.
  2720. * @param {Object} options - See {@link options}.
  2721. * @returns {undefined}
  2722. */
  2723. moveRow(offset, options) {
  2724. this._withTable(({ range, lines, table, focus }) => {
  2725. let newFocus = focus;
  2726. // complete
  2727. const completed = completeTable(table, options);
  2728. if (completed.delimiterInserted && newFocus.row > 0) {
  2729. newFocus = newFocus.setRow(newFocus.row + 1);
  2730. }
  2731. // move row
  2732. let altered = completed.table;
  2733. if (newFocus.row > 1) {
  2734. const dest = Math.min(Math.max(newFocus.row + offset, 2), altered.getHeight() - 1);
  2735. altered = moveRow(altered, newFocus.row, dest);
  2736. newFocus = newFocus.setRow(dest);
  2737. }
  2738. // format
  2739. const formatted = formatTable(altered, options);
  2740. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, false));
  2741. // apply
  2742. this._textEditor.transact(() => {
  2743. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2744. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2745. });
  2746. this.resetSmartCursor();
  2747. });
  2748. }
  2749. /**
  2750. * Inserts an empty column at the current focus.
  2751. *
  2752. * @param {Object} options - See {@link options}.
  2753. * @returns {undefined}
  2754. */
  2755. insertColumn(options) {
  2756. this._withTable(({ range, lines, table, focus }) => {
  2757. let newFocus = focus;
  2758. // complete
  2759. const completed = completeTable(table, options);
  2760. if (completed.delimiterInserted && newFocus.row > 0) {
  2761. newFocus = newFocus.setRow(newFocus.row + 1);
  2762. }
  2763. // move focus
  2764. if (newFocus.row === 1) {
  2765. newFocus = newFocus.setRow(0);
  2766. }
  2767. if (newFocus.column < 0) {
  2768. newFocus = newFocus.setColumn(0);
  2769. }
  2770. // insert an empty column
  2771. const column = new Array(completed.table.getHeight() - 1).fill(new TableCell(""));
  2772. const altered = insertColumn(completed.table, newFocus.column, column, options);
  2773. // format
  2774. const formatted = formatTable(altered, options);
  2775. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, true));
  2776. // apply
  2777. this._textEditor.transact(() => {
  2778. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2779. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2780. });
  2781. this.resetSmartCursor();
  2782. });
  2783. }
  2784. /**
  2785. * Deletes a column at the current focus.
  2786. *
  2787. * @param {Object} options - See {@link options}.
  2788. * @returns {undefined}
  2789. */
  2790. deleteColumn(options) {
  2791. this._withTable(({ range, lines, table, focus }) => {
  2792. let newFocus = focus;
  2793. // complete
  2794. const completed = completeTable(table, options);
  2795. if (completed.delimiterInserted && newFocus.row > 0) {
  2796. newFocus = newFocus.setRow(newFocus.row + 1);
  2797. }
  2798. // move focus
  2799. if (newFocus.row === 1) {
  2800. newFocus = newFocus.setRow(0);
  2801. }
  2802. // delete a column
  2803. let altered = completed.table;
  2804. let moved = false;
  2805. if (0 <= newFocus.column && newFocus.column <= altered.getHeaderWidth() - 1) {
  2806. altered = deleteColumn(completed.table, newFocus.column, options);
  2807. moved = true;
  2808. if (newFocus.column > altered.getHeaderWidth() - 1) {
  2809. newFocus = newFocus.setColumn(altered.getHeaderWidth() - 1);
  2810. }
  2811. }
  2812. // format
  2813. const formatted = formatTable(altered, options);
  2814. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, moved));
  2815. // apply
  2816. this._textEditor.transact(() => {
  2817. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2818. if (moved) {
  2819. this._selectFocus(range.start.row, formatted.table, newFocus);
  2820. }
  2821. else {
  2822. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2823. }
  2824. });
  2825. this.resetSmartCursor();
  2826. });
  2827. }
  2828. /**
  2829. * Moves the focused column by the specified offset.
  2830. *
  2831. * @param {number} offset - An offset the column is moved by.
  2832. * @param {Object} options - See {@link options}.
  2833. * @returns {undefined}
  2834. */
  2835. moveColumn(offset, options) {
  2836. this._withTable(({ range, lines, table, focus }) => {
  2837. let newFocus = focus;
  2838. // complete
  2839. const completed = completeTable(table, options);
  2840. if (completed.delimiterInserted && newFocus.row > 0) {
  2841. newFocus = newFocus.setRow(newFocus.row + 1);
  2842. }
  2843. // move column
  2844. let altered = completed.table;
  2845. if (0 <= newFocus.column && newFocus.column <= altered.getHeaderWidth() - 1) {
  2846. const dest = Math.min(Math.max(newFocus.column + offset, 0), altered.getHeaderWidth() - 1);
  2847. altered = moveColumn(altered, newFocus.column, dest);
  2848. newFocus = newFocus.setColumn(dest);
  2849. }
  2850. // format
  2851. const formatted = formatTable(altered, options);
  2852. newFocus = newFocus.setOffset(_computeNewOffset(newFocus, altered, formatted, false));
  2853. // apply
  2854. this._textEditor.transact(() => {
  2855. this._updateLines(range.start.row, range.end.row + 1, formatted.table.toLines(), lines);
  2856. this._moveToFocus(range.start.row, formatted.table, newFocus);
  2857. });
  2858. this.resetSmartCursor();
  2859. });
  2860. }
  2861. /**
  2862. * Formats all the tables in the text editor.
  2863. *
  2864. * @param {Object} options - See {@link options}.
  2865. * @returns {undefined}
  2866. */
  2867. formatAll(options) {
  2868. this._textEditor.transact(() => {
  2869. let pos = this._textEditor.getCursorPosition();
  2870. let lines = [];
  2871. let startRow = undefined;
  2872. let lastRow = this._textEditor.getLastRow();
  2873. // find tables
  2874. for (let row = 0; row <= lastRow; row++) {
  2875. const line = this._textEditor.getLine(row);
  2876. if (this._textEditor.acceptsTableEdit(row) && _isTableRow(line)) {
  2877. lines.push(line);
  2878. if (startRow === undefined) {
  2879. startRow = row;
  2880. }
  2881. }
  2882. else if (startRow !== undefined) {
  2883. // get table info
  2884. const endRow = row - 1;
  2885. const range = new Range(
  2886. new Point(startRow, 0),
  2887. new Point(endRow, lines[lines.length - 1].length)
  2888. );
  2889. const table = readTable(lines);
  2890. const focus = table.focusOfPosition(pos, startRow);
  2891. const focused = focus !== undefined;
  2892. // format
  2893. let newFocus = focus;
  2894. const completed = completeTable(table, options);
  2895. if (focused && completed.delimiterInserted && newFocus.row > 0) {
  2896. newFocus = newFocus.setRow(newFocus.row + 1);
  2897. }
  2898. const formatted = formatTable(completed.table, options);
  2899. if (focused) {
  2900. newFocus = newFocus.setOffset(
  2901. _computeNewOffset(newFocus, completed.table, formatted, false)
  2902. );
  2903. }
  2904. // apply
  2905. const newLines = formatted.table.toLines();
  2906. this._updateLines(range.start.row, range.end.row + 1, newLines, lines);
  2907. // update cursor position
  2908. const diff = newLines.length - lines.length;
  2909. if (focused) {
  2910. pos = formatted.table.positionOfFocus(newFocus, startRow);
  2911. }
  2912. else if (pos.row > endRow) {
  2913. pos = new Point(pos.row + diff, pos.column);
  2914. }
  2915. // reset
  2916. lines = [];
  2917. startRow = undefined;
  2918. // update
  2919. lastRow += diff;
  2920. row += diff;
  2921. }
  2922. }
  2923. if (startRow !== undefined) {
  2924. // get table info
  2925. const endRow = lastRow;
  2926. const range = new Range(
  2927. new Point(startRow, 0),
  2928. new Point(endRow, lines[lines.length - 1].length)
  2929. );
  2930. const table = readTable(lines);
  2931. const focus = table.focusOfPosition(pos, startRow);
  2932. // format
  2933. let newFocus = focus;
  2934. const completed = completeTable(table, options);
  2935. if (completed.delimiterInserted && newFocus.row > 0) {
  2936. newFocus = newFocus.setRow(newFocus.row + 1);
  2937. }
  2938. const formatted = formatTable(completed.table, options);
  2939. newFocus = newFocus.setOffset(
  2940. _computeNewOffset(newFocus, completed.table, formatted, false)
  2941. );
  2942. // apply
  2943. const newLines = formatted.table.toLines();
  2944. this._updateLines(range.start.row, range.end.row + 1, newLines, lines);
  2945. pos = formatted.table.positionOfFocus(newFocus, startRow);
  2946. }
  2947. this._textEditor.setCursorPosition(pos);
  2948. });
  2949. }
  2950. }
  2951. //# sourceMappingURL=mte-kernel.mjs.map
  2952. /***/ }),
  2953. /* 2 */
  2954. /***/ (function(module, __webpack_exports__, __webpack_require__) {
  2955. "use strict";
  2956. /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getEAW; });
  2957. /* unused harmony export computeWidth */
  2958. /*
  2959. * This file is generated by a script. DO NOT EDIT BY HAND!
  2960. */
  2961. /*
  2962. * This part (from BEGIN to END) is derived from the Unicode Data Files:
  2963. *
  2964. * UNICODE, INC. LICENSE AGREEMENT
  2965. *
  2966. * Copyright © 1991-2017 Unicode, Inc. All rights reserved.
  2967. * Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
  2968. *
  2969. * Permission is hereby granted, free of charge, to any person obtaining
  2970. * a copy of the Unicode data files and any associated documentation
  2971. * (the "Data Files") or Unicode software and any associated documentation
  2972. * (the "Software") to deal in the Data Files or Software
  2973. * without restriction, including without limitation the rights to use,
  2974. * copy, modify, merge, publish, distribute, and/or sell copies of
  2975. * the Data Files or Software, and to permit persons to whom the Data Files
  2976. * or Software are furnished to do so, provided that either
  2977. * (a) this copyright and permission notice appear with all copies
  2978. * of the Data Files or Software, or
  2979. * (b) this copyright and permission notice appear in associated
  2980. * Documentation.
  2981. *
  2982. * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
  2983. * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  2984. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  2985. * NONINFRINGEMENT OF THIRD PARTY RIGHTS.
  2986. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
  2987. * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
  2988. * DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  2989. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  2990. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  2991. * PERFORMANCE OF THE DATA FILES OR SOFTWARE.
  2992. */
  2993. /* BEGIN */
  2994. var defs = [
  2995. { start: 0, end: 31, prop: "N" },
  2996. { start: 32, end: 126, prop: "Na" },
  2997. { start: 127, end: 160, prop: "N" },
  2998. { start: 161, end: 161, prop: "A" },
  2999. { start: 162, end: 163, prop: "Na" },
  3000. { start: 164, end: 164, prop: "A" },
  3001. { start: 165, end: 166, prop: "Na" },
  3002. { start: 167, end: 168, prop: "A" },
  3003. { start: 169, end: 169, prop: "N" },
  3004. { start: 170, end: 170, prop: "A" },
  3005. { start: 171, end: 171, prop: "N" },
  3006. { start: 172, end: 172, prop: "Na" },
  3007. { start: 173, end: 174, prop: "A" },
  3008. { start: 175, end: 175, prop: "Na" },
  3009. { start: 176, end: 180, prop: "A" },
  3010. { start: 181, end: 181, prop: "N" },
  3011. { start: 182, end: 186, prop: "A" },
  3012. { start: 187, end: 187, prop: "N" },
  3013. { start: 188, end: 191, prop: "A" },
  3014. { start: 192, end: 197, prop: "N" },
  3015. { start: 198, end: 198, prop: "A" },
  3016. { start: 199, end: 207, prop: "N" },
  3017. { start: 208, end: 208, prop: "A" },
  3018. { start: 209, end: 214, prop: "N" },
  3019. { start: 215, end: 216, prop: "A" },
  3020. { start: 217, end: 221, prop: "N" },
  3021. { start: 222, end: 225, prop: "A" },
  3022. { start: 226, end: 229, prop: "N" },
  3023. { start: 230, end: 230, prop: "A" },
  3024. { start: 231, end: 231, prop: "N" },
  3025. { start: 232, end: 234, prop: "A" },
  3026. { start: 235, end: 235, prop: "N" },
  3027. { start: 236, end: 237, prop: "A" },
  3028. { start: 238, end: 239, prop: "N" },
  3029. { start: 240, end: 240, prop: "A" },
  3030. { start: 241, end: 241, prop: "N" },
  3031. { start: 242, end: 243, prop: "A" },
  3032. { start: 244, end: 246, prop: "N" },
  3033. { start: 247, end: 250, prop: "A" },
  3034. { start: 251, end: 251, prop: "N" },
  3035. { start: 252, end: 252, prop: "A" },
  3036. { start: 253, end: 253, prop: "N" },
  3037. { start: 254, end: 254, prop: "A" },
  3038. { start: 255, end: 256, prop: "N" },
  3039. { start: 257, end: 257, prop: "A" },
  3040. { start: 258, end: 272, prop: "N" },
  3041. { start: 273, end: 273, prop: "A" },
  3042. { start: 274, end: 274, prop: "N" },
  3043. { start: 275, end: 275, prop: "A" },
  3044. { start: 276, end: 282, prop: "N" },
  3045. { start: 283, end: 283, prop: "A" },
  3046. { start: 284, end: 293, prop: "N" },
  3047. { start: 294, end: 295, prop: "A" },
  3048. { start: 296, end: 298, prop: "N" },
  3049. { start: 299, end: 299, prop: "A" },
  3050. { start: 300, end: 304, prop: "N" },
  3051. { start: 305, end: 307, prop: "A" },
  3052. { start: 308, end: 311, prop: "N" },
  3053. { start: 312, end: 312, prop: "A" },
  3054. { start: 313, end: 318, prop: "N" },
  3055. { start: 319, end: 322, prop: "A" },
  3056. { start: 323, end: 323, prop: "N" },
  3057. { start: 324, end: 324, prop: "A" },
  3058. { start: 325, end: 327, prop: "N" },
  3059. { start: 328, end: 331, prop: "A" },
  3060. { start: 332, end: 332, prop: "N" },
  3061. { start: 333, end: 333, prop: "A" },
  3062. { start: 334, end: 337, prop: "N" },
  3063. { start: 338, end: 339, prop: "A" },
  3064. { start: 340, end: 357, prop: "N" },
  3065. { start: 358, end: 359, prop: "A" },
  3066. { start: 360, end: 362, prop: "N" },
  3067. { start: 363, end: 363, prop: "A" },
  3068. { start: 364, end: 461, prop: "N" },
  3069. { start: 462, end: 462, prop: "A" },
  3070. { start: 463, end: 463, prop: "N" },
  3071. { start: 464, end: 464, prop: "A" },
  3072. { start: 465, end: 465, prop: "N" },
  3073. { start: 466, end: 466, prop: "A" },
  3074. { start: 467, end: 467, prop: "N" },
  3075. { start: 468, end: 468, prop: "A" },
  3076. { start: 469, end: 469, prop: "N" },
  3077. { start: 470, end: 470, prop: "A" },
  3078. { start: 471, end: 471, prop: "N" },
  3079. { start: 472, end: 472, prop: "A" },
  3080. { start: 473, end: 473, prop: "N" },
  3081. { start: 474, end: 474, prop: "A" },
  3082. { start: 475, end: 475, prop: "N" },
  3083. { start: 476, end: 476, prop: "A" },
  3084. { start: 477, end: 592, prop: "N" },
  3085. { start: 593, end: 593, prop: "A" },
  3086. { start: 594, end: 608, prop: "N" },
  3087. { start: 609, end: 609, prop: "A" },
  3088. { start: 610, end: 707, prop: "N" },
  3089. { start: 708, end: 708, prop: "A" },
  3090. { start: 709, end: 710, prop: "N" },
  3091. { start: 711, end: 711, prop: "A" },
  3092. { start: 712, end: 712, prop: "N" },
  3093. { start: 713, end: 715, prop: "A" },
  3094. { start: 716, end: 716, prop: "N" },
  3095. { start: 717, end: 717, prop: "A" },
  3096. { start: 718, end: 719, prop: "N" },
  3097. { start: 720, end: 720, prop: "A" },
  3098. { start: 721, end: 727, prop: "N" },
  3099. { start: 728, end: 731, prop: "A" },
  3100. { start: 732, end: 732, prop: "N" },
  3101. { start: 733, end: 733, prop: "A" },
  3102. { start: 734, end: 734, prop: "N" },
  3103. { start: 735, end: 735, prop: "A" },
  3104. { start: 736, end: 767, prop: "N" },
  3105. { start: 768, end: 879, prop: "A" },
  3106. { start: 880, end: 912, prop: "N" },
  3107. { start: 913, end: 929, prop: "A" },
  3108. { start: 930, end: 930, prop: "N" },
  3109. { start: 931, end: 937, prop: "A" },
  3110. { start: 938, end: 944, prop: "N" },
  3111. { start: 945, end: 961, prop: "A" },
  3112. { start: 962, end: 962, prop: "N" },
  3113. { start: 963, end: 969, prop: "A" },
  3114. { start: 970, end: 1024, prop: "N" },
  3115. { start: 1025, end: 1025, prop: "A" },
  3116. { start: 1026, end: 1039, prop: "N" },
  3117. { start: 1040, end: 1103, prop: "A" },
  3118. { start: 1104, end: 1104, prop: "N" },
  3119. { start: 1105, end: 1105, prop: "A" },
  3120. { start: 1106, end: 4351, prop: "N" },
  3121. { start: 4352, end: 4447, prop: "W" },
  3122. { start: 4448, end: 8207, prop: "N" },
  3123. { start: 8208, end: 8208, prop: "A" },
  3124. { start: 8209, end: 8210, prop: "N" },
  3125. { start: 8211, end: 8214, prop: "A" },
  3126. { start: 8215, end: 8215, prop: "N" },
  3127. { start: 8216, end: 8217, prop: "A" },
  3128. { start: 8218, end: 8219, prop: "N" },
  3129. { start: 8220, end: 8221, prop: "A" },
  3130. { start: 8222, end: 8223, prop: "N" },
  3131. { start: 8224, end: 8226, prop: "A" },
  3132. { start: 8227, end: 8227, prop: "N" },
  3133. { start: 8228, end: 8231, prop: "A" },
  3134. { start: 8232, end: 8239, prop: "N" },
  3135. { start: 8240, end: 8240, prop: "A" },
  3136. { start: 8241, end: 8241, prop: "N" },
  3137. { start: 8242, end: 8243, prop: "A" },
  3138. { start: 8244, end: 8244, prop: "N" },
  3139. { start: 8245, end: 8245, prop: "A" },
  3140. { start: 8246, end: 8250, prop: "N" },
  3141. { start: 8251, end: 8251, prop: "A" },
  3142. { start: 8252, end: 8253, prop: "N" },
  3143. { start: 8254, end: 8254, prop: "A" },
  3144. { start: 8255, end: 8307, prop: "N" },
  3145. { start: 8308, end: 8308, prop: "A" },
  3146. { start: 8309, end: 8318, prop: "N" },
  3147. { start: 8319, end: 8319, prop: "A" },
  3148. { start: 8320, end: 8320, prop: "N" },
  3149. { start: 8321, end: 8324, prop: "A" },
  3150. { start: 8325, end: 8360, prop: "N" },
  3151. { start: 8361, end: 8361, prop: "H" },
  3152. { start: 8362, end: 8363, prop: "N" },
  3153. { start: 8364, end: 8364, prop: "A" },
  3154. { start: 8365, end: 8450, prop: "N" },
  3155. { start: 8451, end: 8451, prop: "A" },
  3156. { start: 8452, end: 8452, prop: "N" },
  3157. { start: 8453, end: 8453, prop: "A" },
  3158. { start: 8454, end: 8456, prop: "N" },
  3159. { start: 8457, end: 8457, prop: "A" },
  3160. { start: 8458, end: 8466, prop: "N" },
  3161. { start: 8467, end: 8467, prop: "A" },
  3162. { start: 8468, end: 8469, prop: "N" },
  3163. { start: 8470, end: 8470, prop: "A" },
  3164. { start: 8471, end: 8480, prop: "N" },
  3165. { start: 8481, end: 8482, prop: "A" },
  3166. { start: 8483, end: 8485, prop: "N" },
  3167. { start: 8486, end: 8486, prop: "A" },
  3168. { start: 8487, end: 8490, prop: "N" },
  3169. { start: 8491, end: 8491, prop: "A" },
  3170. { start: 8492, end: 8530, prop: "N" },
  3171. { start: 8531, end: 8532, prop: "A" },
  3172. { start: 8533, end: 8538, prop: "N" },
  3173. { start: 8539, end: 8542, prop: "A" },
  3174. { start: 8543, end: 8543, prop: "N" },
  3175. { start: 8544, end: 8555, prop: "A" },
  3176. { start: 8556, end: 8559, prop: "N" },
  3177. { start: 8560, end: 8569, prop: "A" },
  3178. { start: 8570, end: 8584, prop: "N" },
  3179. { start: 8585, end: 8585, prop: "A" },
  3180. { start: 8586, end: 8591, prop: "N" },
  3181. { start: 8592, end: 8601, prop: "A" },
  3182. { start: 8602, end: 8631, prop: "N" },
  3183. { start: 8632, end: 8633, prop: "A" },
  3184. { start: 8634, end: 8657, prop: "N" },
  3185. { start: 8658, end: 8658, prop: "A" },
  3186. { start: 8659, end: 8659, prop: "N" },
  3187. { start: 8660, end: 8660, prop: "A" },
  3188. { start: 8661, end: 8678, prop: "N" },
  3189. { start: 8679, end: 8679, prop: "A" },
  3190. { start: 8680, end: 8703, prop: "N" },
  3191. { start: 8704, end: 8704, prop: "A" },
  3192. { start: 8705, end: 8705, prop: "N" },
  3193. { start: 8706, end: 8707, prop: "A" },
  3194. { start: 8708, end: 8710, prop: "N" },
  3195. { start: 8711, end: 8712, prop: "A" },
  3196. { start: 8713, end: 8714, prop: "N" },
  3197. { start: 8715, end: 8715, prop: "A" },
  3198. { start: 8716, end: 8718, prop: "N" },
  3199. { start: 8719, end: 8719, prop: "A" },
  3200. { start: 8720, end: 8720, prop: "N" },
  3201. { start: 8721, end: 8721, prop: "A" },
  3202. { start: 8722, end: 8724, prop: "N" },
  3203. { start: 8725, end: 8725, prop: "A" },
  3204. { start: 8726, end: 8729, prop: "N" },
  3205. { start: 8730, end: 8730, prop: "A" },
  3206. { start: 8731, end: 8732, prop: "N" },
  3207. { start: 8733, end: 8736, prop: "A" },
  3208. { start: 8737, end: 8738, prop: "N" },
  3209. { start: 8739, end: 8739, prop: "A" },
  3210. { start: 8740, end: 8740, prop: "N" },
  3211. { start: 8741, end: 8741, prop: "A" },
  3212. { start: 8742, end: 8742, prop: "N" },
  3213. { start: 8743, end: 8748, prop: "A" },
  3214. { start: 8749, end: 8749, prop: "N" },
  3215. { start: 8750, end: 8750, prop: "A" },
  3216. { start: 8751, end: 8755, prop: "N" },
  3217. { start: 8756, end: 8759, prop: "A" },
  3218. { start: 8760, end: 8763, prop: "N" },
  3219. { start: 8764, end: 8765, prop: "A" },
  3220. { start: 8766, end: 8775, prop: "N" },
  3221. { start: 8776, end: 8776, prop: "A" },
  3222. { start: 8777, end: 8779, prop: "N" },
  3223. { start: 8780, end: 8780, prop: "A" },
  3224. { start: 8781, end: 8785, prop: "N" },
  3225. { start: 8786, end: 8786, prop: "A" },
  3226. { start: 8787, end: 8799, prop: "N" },
  3227. { start: 8800, end: 8801, prop: "A" },
  3228. { start: 8802, end: 8803, prop: "N" },
  3229. { start: 8804, end: 8807, prop: "A" },
  3230. { start: 8808, end: 8809, prop: "N" },
  3231. { start: 8810, end: 8811, prop: "A" },
  3232. { start: 8812, end: 8813, prop: "N" },
  3233. { start: 8814, end: 8815, prop: "A" },
  3234. { start: 8816, end: 8833, prop: "N" },
  3235. { start: 8834, end: 8835, prop: "A" },
  3236. { start: 8836, end: 8837, prop: "N" },
  3237. { start: 8838, end: 8839, prop: "A" },
  3238. { start: 8840, end: 8852, prop: "N" },
  3239. { start: 8853, end: 8853, prop: "A" },
  3240. { start: 8854, end: 8856, prop: "N" },
  3241. { start: 8857, end: 8857, prop: "A" },
  3242. { start: 8858, end: 8868, prop: "N" },
  3243. { start: 8869, end: 8869, prop: "A" },
  3244. { start: 8870, end: 8894, prop: "N" },
  3245. { start: 8895, end: 8895, prop: "A" },
  3246. { start: 8896, end: 8977, prop: "N" },
  3247. { start: 8978, end: 8978, prop: "A" },
  3248. { start: 8979, end: 8985, prop: "N" },
  3249. { start: 8986, end: 8987, prop: "W" },
  3250. { start: 8988, end: 9000, prop: "N" },
  3251. { start: 9001, end: 9002, prop: "W" },
  3252. { start: 9003, end: 9192, prop: "N" },
  3253. { start: 9193, end: 9196, prop: "W" },
  3254. { start: 9197, end: 9199, prop: "N" },
  3255. { start: 9200, end: 9200, prop: "W" },
  3256. { start: 9201, end: 9202, prop: "N" },
  3257. { start: 9203, end: 9203, prop: "W" },
  3258. { start: 9204, end: 9311, prop: "N" },
  3259. { start: 9312, end: 9449, prop: "A" },
  3260. { start: 9450, end: 9450, prop: "N" },
  3261. { start: 9451, end: 9547, prop: "A" },
  3262. { start: 9548, end: 9551, prop: "N" },
  3263. { start: 9552, end: 9587, prop: "A" },
  3264. { start: 9588, end: 9599, prop: "N" },
  3265. { start: 9600, end: 9615, prop: "A" },
  3266. { start: 9616, end: 9617, prop: "N" },
  3267. { start: 9618, end: 9621, prop: "A" },
  3268. { start: 9622, end: 9631, prop: "N" },
  3269. { start: 9632, end: 9633, prop: "A" },
  3270. { start: 9634, end: 9634, prop: "N" },
  3271. { start: 9635, end: 9641, prop: "A" },
  3272. { start: 9642, end: 9649, prop: "N" },
  3273. { start: 9650, end: 9651, prop: "A" },
  3274. { start: 9652, end: 9653, prop: "N" },
  3275. { start: 9654, end: 9655, prop: "A" },
  3276. { start: 9656, end: 9659, prop: "N" },
  3277. { start: 9660, end: 9661, prop: "A" },
  3278. { start: 9662, end: 9663, prop: "N" },
  3279. { start: 9664, end: 9665, prop: "A" },
  3280. { start: 9666, end: 9669, prop: "N" },
  3281. { start: 9670, end: 9672, prop: "A" },
  3282. { start: 9673, end: 9674, prop: "N" },
  3283. { start: 9675, end: 9675, prop: "A" },
  3284. { start: 9676, end: 9677, prop: "N" },
  3285. { start: 9678, end: 9681, prop: "A" },
  3286. { start: 9682, end: 9697, prop: "N" },
  3287. { start: 9698, end: 9701, prop: "A" },
  3288. { start: 9702, end: 9710, prop: "N" },
  3289. { start: 9711, end: 9711, prop: "A" },
  3290. { start: 9712, end: 9724, prop: "N" },
  3291. { start: 9725, end: 9726, prop: "W" },
  3292. { start: 9727, end: 9732, prop: "N" },
  3293. { start: 9733, end: 9734, prop: "A" },
  3294. { start: 9735, end: 9736, prop: "N" },
  3295. { start: 9737, end: 9737, prop: "A" },
  3296. { start: 9738, end: 9741, prop: "N" },
  3297. { start: 9742, end: 9743, prop: "A" },
  3298. { start: 9744, end: 9747, prop: "N" },
  3299. { start: 9748, end: 9749, prop: "W" },
  3300. { start: 9750, end: 9755, prop: "N" },
  3301. { start: 9756, end: 9756, prop: "A" },
  3302. { start: 9757, end: 9757, prop: "N" },
  3303. { start: 9758, end: 9758, prop: "A" },
  3304. { start: 9759, end: 9791, prop: "N" },
  3305. { start: 9792, end: 9792, prop: "A" },
  3306. { start: 9793, end: 9793, prop: "N" },
  3307. { start: 9794, end: 9794, prop: "A" },
  3308. { start: 9795, end: 9799, prop: "N" },
  3309. { start: 9800, end: 9811, prop: "W" },
  3310. { start: 9812, end: 9823, prop: "N" },
  3311. { start: 9824, end: 9825, prop: "A" },
  3312. { start: 9826, end: 9826, prop: "N" },
  3313. { start: 9827, end: 9829, prop: "A" },
  3314. { start: 9830, end: 9830, prop: "N" },
  3315. { start: 9831, end: 9834, prop: "A" },
  3316. { start: 9835, end: 9835, prop: "N" },
  3317. { start: 9836, end: 9837, prop: "A" },
  3318. { start: 9838, end: 9838, prop: "N" },
  3319. { start: 9839, end: 9839, prop: "A" },
  3320. { start: 9840, end: 9854, prop: "N" },
  3321. { start: 9855, end: 9855, prop: "W" },
  3322. { start: 9856, end: 9874, prop: "N" },
  3323. { start: 9875, end: 9875, prop: "W" },
  3324. { start: 9876, end: 9885, prop: "N" },
  3325. { start: 9886, end: 9887, prop: "A" },
  3326. { start: 9888, end: 9888, prop: "N" },
  3327. { start: 9889, end: 9889, prop: "W" },
  3328. { start: 9890, end: 9897, prop: "N" },
  3329. { start: 9898, end: 9899, prop: "W" },
  3330. { start: 9900, end: 9916, prop: "N" },
  3331. { start: 9917, end: 9918, prop: "W" },
  3332. { start: 9919, end: 9919, prop: "A" },
  3333. { start: 9920, end: 9923, prop: "N" },
  3334. { start: 9924, end: 9925, prop: "W" },
  3335. { start: 9926, end: 9933, prop: "A" },
  3336. { start: 9934, end: 9934, prop: "W" },
  3337. { start: 9935, end: 9939, prop: "A" },
  3338. { start: 9940, end: 9940, prop: "W" },
  3339. { start: 9941, end: 9953, prop: "A" },
  3340. { start: 9954, end: 9954, prop: "N" },
  3341. { start: 9955, end: 9955, prop: "A" },
  3342. { start: 9956, end: 9959, prop: "N" },
  3343. { start: 9960, end: 9961, prop: "A" },
  3344. { start: 9962, end: 9962, prop: "W" },
  3345. { start: 9963, end: 9969, prop: "A" },
  3346. { start: 9970, end: 9971, prop: "W" },
  3347. { start: 9972, end: 9972, prop: "A" },
  3348. { start: 9973, end: 9973, prop: "W" },
  3349. { start: 9974, end: 9977, prop: "A" },
  3350. { start: 9978, end: 9978, prop: "W" },
  3351. { start: 9979, end: 9980, prop: "A" },
  3352. { start: 9981, end: 9981, prop: "W" },
  3353. { start: 9982, end: 9983, prop: "A" },
  3354. { start: 9984, end: 9988, prop: "N" },
  3355. { start: 9989, end: 9989, prop: "W" },
  3356. { start: 9990, end: 9993, prop: "N" },
  3357. { start: 9994, end: 9995, prop: "W" },
  3358. { start: 9996, end: 10023, prop: "N" },
  3359. { start: 10024, end: 10024, prop: "W" },
  3360. { start: 10025, end: 10044, prop: "N" },
  3361. { start: 10045, end: 10045, prop: "A" },
  3362. { start: 10046, end: 10059, prop: "N" },
  3363. { start: 10060, end: 10060, prop: "W" },
  3364. { start: 10061, end: 10061, prop: "N" },
  3365. { start: 10062, end: 10062, prop: "W" },
  3366. { start: 10063, end: 10066, prop: "N" },
  3367. { start: 10067, end: 10069, prop: "W" },
  3368. { start: 10070, end: 10070, prop: "N" },
  3369. { start: 10071, end: 10071, prop: "W" },
  3370. { start: 10072, end: 10101, prop: "N" },
  3371. { start: 10102, end: 10111, prop: "A" },
  3372. { start: 10112, end: 10132, prop: "N" },
  3373. { start: 10133, end: 10135, prop: "W" },
  3374. { start: 10136, end: 10159, prop: "N" },
  3375. { start: 10160, end: 10160, prop: "W" },
  3376. { start: 10161, end: 10174, prop: "N" },
  3377. { start: 10175, end: 10175, prop: "W" },
  3378. { start: 10176, end: 10213, prop: "N" },
  3379. { start: 10214, end: 10221, prop: "Na" },
  3380. { start: 10222, end: 10628, prop: "N" },
  3381. { start: 10629, end: 10630, prop: "Na" },
  3382. { start: 10631, end: 11034, prop: "N" },
  3383. { start: 11035, end: 11036, prop: "W" },
  3384. { start: 11037, end: 11087, prop: "N" },
  3385. { start: 11088, end: 11088, prop: "W" },
  3386. { start: 11089, end: 11092, prop: "N" },
  3387. { start: 11093, end: 11093, prop: "W" },
  3388. { start: 11094, end: 11097, prop: "A" },
  3389. { start: 11098, end: 11903, prop: "N" },
  3390. { start: 11904, end: 11929, prop: "W" },
  3391. { start: 11930, end: 11930, prop: "N" },
  3392. { start: 11931, end: 12019, prop: "W" },
  3393. { start: 12020, end: 12031, prop: "N" },
  3394. { start: 12032, end: 12245, prop: "W" },
  3395. { start: 12246, end: 12271, prop: "N" },
  3396. { start: 12272, end: 12283, prop: "W" },
  3397. { start: 12284, end: 12287, prop: "N" },
  3398. { start: 12288, end: 12288, prop: "F" },
  3399. { start: 12289, end: 12350, prop: "W" },
  3400. { start: 12351, end: 12352, prop: "N" },
  3401. { start: 12353, end: 12438, prop: "W" },
  3402. { start: 12439, end: 12440, prop: "N" },
  3403. { start: 12441, end: 12543, prop: "W" },
  3404. { start: 12544, end: 12548, prop: "N" },
  3405. { start: 12549, end: 12590, prop: "W" },
  3406. { start: 12591, end: 12592, prop: "N" },
  3407. { start: 12593, end: 12686, prop: "W" },
  3408. { start: 12687, end: 12687, prop: "N" },
  3409. { start: 12688, end: 12730, prop: "W" },
  3410. { start: 12731, end: 12735, prop: "N" },
  3411. { start: 12736, end: 12771, prop: "W" },
  3412. { start: 12772, end: 12783, prop: "N" },
  3413. { start: 12784, end: 12830, prop: "W" },
  3414. { start: 12831, end: 12831, prop: "N" },
  3415. { start: 12832, end: 12871, prop: "W" },
  3416. { start: 12872, end: 12879, prop: "A" },
  3417. { start: 12880, end: 13054, prop: "W" },
  3418. { start: 13055, end: 13055, prop: "N" },
  3419. { start: 13056, end: 19903, prop: "W" },
  3420. { start: 19904, end: 19967, prop: "N" },
  3421. { start: 19968, end: 42124, prop: "W" },
  3422. { start: 42125, end: 42127, prop: "N" },
  3423. { start: 42128, end: 42182, prop: "W" },
  3424. { start: 42183, end: 43359, prop: "N" },
  3425. { start: 43360, end: 43388, prop: "W" },
  3426. { start: 43389, end: 44031, prop: "N" },
  3427. { start: 44032, end: 55203, prop: "W" },
  3428. { start: 55204, end: 57343, prop: "N" },
  3429. { start: 57344, end: 63743, prop: "A" },
  3430. { start: 63744, end: 64255, prop: "W" },
  3431. { start: 64256, end: 65023, prop: "N" },
  3432. { start: 65024, end: 65039, prop: "A" },
  3433. { start: 65040, end: 65049, prop: "W" },
  3434. { start: 65050, end: 65071, prop: "N" },
  3435. { start: 65072, end: 65106, prop: "W" },
  3436. { start: 65107, end: 65107, prop: "N" },
  3437. { start: 65108, end: 65126, prop: "W" },
  3438. { start: 65127, end: 65127, prop: "N" },
  3439. { start: 65128, end: 65131, prop: "W" },
  3440. { start: 65132, end: 65280, prop: "N" },
  3441. { start: 65281, end: 65376, prop: "F" },
  3442. { start: 65377, end: 65470, prop: "H" },
  3443. { start: 65471, end: 65473, prop: "N" },
  3444. { start: 65474, end: 65479, prop: "H" },
  3445. { start: 65480, end: 65481, prop: "N" },
  3446. { start: 65482, end: 65487, prop: "H" },
  3447. { start: 65488, end: 65489, prop: "N" },
  3448. { start: 65490, end: 65495, prop: "H" },
  3449. { start: 65496, end: 65497, prop: "N" },
  3450. { start: 65498, end: 65500, prop: "H" },
  3451. { start: 65501, end: 65503, prop: "N" },
  3452. { start: 65504, end: 65510, prop: "F" },
  3453. { start: 65511, end: 65511, prop: "N" },
  3454. { start: 65512, end: 65518, prop: "H" },
  3455. { start: 65519, end: 65532, prop: "N" },
  3456. { start: 65533, end: 65533, prop: "A" },
  3457. { start: 65534, end: 94175, prop: "N" },
  3458. { start: 94176, end: 94177, prop: "W" },
  3459. { start: 94178, end: 94207, prop: "N" },
  3460. { start: 94208, end: 100332, prop: "W" },
  3461. { start: 100333, end: 100351, prop: "N" },
  3462. { start: 100352, end: 101106, prop: "W" },
  3463. { start: 101107, end: 110591, prop: "N" },
  3464. { start: 110592, end: 110878, prop: "W" },
  3465. { start: 110879, end: 110959, prop: "N" },
  3466. { start: 110960, end: 111355, prop: "W" },
  3467. { start: 111356, end: 126979, prop: "N" },
  3468. { start: 126980, end: 126980, prop: "W" },
  3469. { start: 126981, end: 127182, prop: "N" },
  3470. { start: 127183, end: 127183, prop: "W" },
  3471. { start: 127184, end: 127231, prop: "N" },
  3472. { start: 127232, end: 127242, prop: "A" },
  3473. { start: 127243, end: 127247, prop: "N" },
  3474. { start: 127248, end: 127277, prop: "A" },
  3475. { start: 127278, end: 127279, prop: "N" },
  3476. { start: 127280, end: 127337, prop: "A" },
  3477. { start: 127338, end: 127343, prop: "N" },
  3478. { start: 127344, end: 127373, prop: "A" },
  3479. { start: 127374, end: 127374, prop: "W" },
  3480. { start: 127375, end: 127376, prop: "A" },
  3481. { start: 127377, end: 127386, prop: "W" },
  3482. { start: 127387, end: 127404, prop: "A" },
  3483. { start: 127405, end: 127487, prop: "N" },
  3484. { start: 127488, end: 127490, prop: "W" },
  3485. { start: 127491, end: 127503, prop: "N" },
  3486. { start: 127504, end: 127547, prop: "W" },
  3487. { start: 127548, end: 127551, prop: "N" },
  3488. { start: 127552, end: 127560, prop: "W" },
  3489. { start: 127561, end: 127567, prop: "N" },
  3490. { start: 127568, end: 127569, prop: "W" },
  3491. { start: 127570, end: 127583, prop: "N" },
  3492. { start: 127584, end: 127589, prop: "W" },
  3493. { start: 127590, end: 127743, prop: "N" },
  3494. { start: 127744, end: 127776, prop: "W" },
  3495. { start: 127777, end: 127788, prop: "N" },
  3496. { start: 127789, end: 127797, prop: "W" },
  3497. { start: 127798, end: 127798, prop: "N" },
  3498. { start: 127799, end: 127868, prop: "W" },
  3499. { start: 127869, end: 127869, prop: "N" },
  3500. { start: 127870, end: 127891, prop: "W" },
  3501. { start: 127892, end: 127903, prop: "N" },
  3502. { start: 127904, end: 127946, prop: "W" },
  3503. { start: 127947, end: 127950, prop: "N" },
  3504. { start: 127951, end: 127955, prop: "W" },
  3505. { start: 127956, end: 127967, prop: "N" },
  3506. { start: 127968, end: 127984, prop: "W" },
  3507. { start: 127985, end: 127987, prop: "N" },
  3508. { start: 127988, end: 127988, prop: "W" },
  3509. { start: 127989, end: 127991, prop: "N" },
  3510. { start: 127992, end: 128062, prop: "W" },
  3511. { start: 128063, end: 128063, prop: "N" },
  3512. { start: 128064, end: 128064, prop: "W" },
  3513. { start: 128065, end: 128065, prop: "N" },
  3514. { start: 128066, end: 128252, prop: "W" },
  3515. { start: 128253, end: 128254, prop: "N" },
  3516. { start: 128255, end: 128317, prop: "W" },
  3517. { start: 128318, end: 128330, prop: "N" },
  3518. { start: 128331, end: 128334, prop: "W" },
  3519. { start: 128335, end: 128335, prop: "N" },
  3520. { start: 128336, end: 128359, prop: "W" },
  3521. { start: 128360, end: 128377, prop: "N" },
  3522. { start: 128378, end: 128378, prop: "W" },
  3523. { start: 128379, end: 128404, prop: "N" },
  3524. { start: 128405, end: 128406, prop: "W" },
  3525. { start: 128407, end: 128419, prop: "N" },
  3526. { start: 128420, end: 128420, prop: "W" },
  3527. { start: 128421, end: 128506, prop: "N" },
  3528. { start: 128507, end: 128591, prop: "W" },
  3529. { start: 128592, end: 128639, prop: "N" },
  3530. { start: 128640, end: 128709, prop: "W" },
  3531. { start: 128710, end: 128715, prop: "N" },
  3532. { start: 128716, end: 128716, prop: "W" },
  3533. { start: 128717, end: 128719, prop: "N" },
  3534. { start: 128720, end: 128722, prop: "W" },
  3535. { start: 128723, end: 128746, prop: "N" },
  3536. { start: 128747, end: 128748, prop: "W" },
  3537. { start: 128749, end: 128755, prop: "N" },
  3538. { start: 128756, end: 128760, prop: "W" },
  3539. { start: 128761, end: 129295, prop: "N" },
  3540. { start: 129296, end: 129342, prop: "W" },
  3541. { start: 129343, end: 129343, prop: "N" },
  3542. { start: 129344, end: 129356, prop: "W" },
  3543. { start: 129357, end: 129359, prop: "N" },
  3544. { start: 129360, end: 129387, prop: "W" },
  3545. { start: 129388, end: 129407, prop: "N" },
  3546. { start: 129408, end: 129431, prop: "W" },
  3547. { start: 129432, end: 129471, prop: "N" },
  3548. { start: 129472, end: 129472, prop: "W" },
  3549. { start: 129473, end: 129487, prop: "N" },
  3550. { start: 129488, end: 129510, prop: "W" },
  3551. { start: 129511, end: 131071, prop: "N" },
  3552. { start: 131072, end: 196605, prop: "W" },
  3553. { start: 196606, end: 196607, prop: "N" },
  3554. { start: 196608, end: 262141, prop: "W" },
  3555. { start: 262142, end: 917759, prop: "N" },
  3556. { start: 917760, end: 917999, prop: "A" },
  3557. { start: 918000, end: 983039, prop: "N" },
  3558. { start: 983040, end: 1048573, prop: "A" },
  3559. { start: 1048574, end: 1048575, prop: "N" },
  3560. { start: 1048576, end: 1114109, prop: "A" },
  3561. { start: 1114110, end: 1114111, prop: "N" }
  3562. ];
  3563. /* END */
  3564. /**
  3565. * Returns The EAW property of a code point.
  3566. * @private
  3567. * @param {string} codePoint A code point
  3568. * @return {string} The EAW property of the specified code point
  3569. */
  3570. function _getEAWOfCodePoint(codePoint) {
  3571. let min = 0;
  3572. let max = defs.length - 1;
  3573. while (min !== max) {
  3574. const i = min + ((max - min) >> 1);
  3575. const def = defs[i];
  3576. if (codePoint < def.start) {
  3577. max = i - 1;
  3578. }
  3579. else if (codePoint > def.end) {
  3580. min = i + 1;
  3581. }
  3582. else {
  3583. return def.prop;
  3584. }
  3585. }
  3586. return defs[min].prop;
  3587. }
  3588. /**
  3589. * Returns the EAW property of a character.
  3590. * @param {string} str A string in which the character is contained
  3591. * @param {number} [at = 0] The position (in code unit) of the character in the string
  3592. * @return {string} The EAW property of the specified character
  3593. * @example
  3594. * import { getEAW } from "meaw";
  3595. *
  3596. * // Narrow
  3597. * assert(getEAW("A") === "Na");
  3598. * // Wide
  3599. * assert(getEAW("あ") === "W");
  3600. * assert(getEAW("安") === "W");
  3601. * assert(getEAW("🍣") === "W");
  3602. * // Fullwidth
  3603. * assert(getEAW("A") === "F");
  3604. * // Halfwidth
  3605. * assert(getEAW("ア") === "H");
  3606. * // Ambiguous
  3607. * assert(getEAW("∀") === "A");
  3608. * assert(getEAW("→") === "A");
  3609. * assert(getEAW("Ω") === "A");
  3610. * assert(getEAW("Я") === "A");
  3611. * // Neutral
  3612. * assert(getEAW("ℵ") === "N");
  3613. *
  3614. * // a position (in code unit) can be specified
  3615. * assert(getEAW("ℵAあAア∀", 2) === "W");
  3616. */
  3617. function getEAW(str, at) {
  3618. const codePoint = str.codePointAt(at || 0);
  3619. return codePoint === undefined
  3620. ? undefined
  3621. : _getEAWOfCodePoint(codePoint);
  3622. }
  3623. const defaultWidthMap = {
  3624. "N" : 1,
  3625. "Na": 1,
  3626. "W" : 2,
  3627. "F" : 2,
  3628. "H" : 1,
  3629. "A" : 1
  3630. };
  3631. /**
  3632. * Computes width of a string based on the EAW properties of its characters.
  3633. * By default characters with property Wide (W) or Fullwidth (F) are treated as wide (= 2)
  3634. * and the others are as narrow (= 1)
  3635. * @param {string} str A string to compute width
  3636. * @param {Object<string, number> | undefined} [widthMap = undefined]
  3637. * An object which represents a map from an EAW property to a character width
  3638. * @return {number} The computed width
  3639. * @example
  3640. * import { computeWidth } from "meaw";
  3641. *
  3642. * assert(computeWidth("Aあ🍣Ω") === 6);
  3643. * // custom widths can be specified by an object
  3644. * assert(computeWidth("Aあ🍣Ω", { "A": 2 }) === 7);
  3645. */
  3646. function computeWidth(str, widthMap) {
  3647. const map = widthMap
  3648. ? Object.assign({}, defaultWidthMap, widthMap)
  3649. : defaultWidthMap;
  3650. let width = 0;
  3651. for (const char of str) {
  3652. width += map[getEAW(char)];
  3653. }
  3654. return width;
  3655. }
  3656. //# sourceMappingURL=meaw.es.js.map
  3657. /***/ })
  3658. /******/ ]);
  3659. });