├── dist ├── index.d.ts ├── libs │ ├── UnicodeToGSM.d.ts │ ├── SmartEncodingMap.d.ts │ ├── UserDataHeader.d.ts │ ├── UserDataHeader.js.map │ ├── EncodedChar.d.ts │ ├── Segment.d.ts │ ├── UserDataHeader.js │ ├── EncodedChar.js.map │ ├── Segment.js.map │ ├── EncodedChar.js │ ├── Segment.js │ ├── SegmentedMessage.d.ts │ ├── UnicodeToGSM.js.map │ ├── UnicodeToGSM.js │ ├── SegmentedMessage.js.map │ ├── SmartEncodingMap.js.map │ ├── SmartEncodingMap.js │ └── SegmentedMessage.js ├── index.js.map └── index.js ├── .prettierrc.js ├── src ├── index.ts └── libs │ ├── UserDataHeader.ts │ ├── EncodedChar.ts │ ├── Segment.ts │ ├── UnicodeToGSM.ts │ ├── SegmentedMessage.ts │ └── SmartEncodingMap.ts ├── .eslintrc ├── CONTRIBUTING.md ├── tests ├── methods.test.js ├── segments.test.js └── index.test.js ├── tsconfig.json ├── .releaserc.json ├── .gitignore ├── webpack.config.js ├── .github └── workflows │ ├── test.js.yml │ └── release.js.yml ├── LICENSE ├── package.json ├── CHANGELOG.md ├── playground └── index.js ├── CODE_OF_CONDUCT.md ├── README.md └── docs ├── styles └── main.css ├── scripts ├── segments_viewer.js └── segmentsCalculator.js └── index.html /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { SegmentedMessage } from './libs/SegmentedMessage'; 2 | export { SegmentedMessage }; 3 | -------------------------------------------------------------------------------- /dist/libs/UnicodeToGSM.d.ts: -------------------------------------------------------------------------------- 1 | declare const UnicodeToGsm: Record>; 2 | export default UnicodeToGsm; 3 | -------------------------------------------------------------------------------- /dist/libs/SmartEncodingMap.d.ts: -------------------------------------------------------------------------------- 1 | declare const SmartEncodingMap: { 2 | [key: string]: string; 3 | }; 4 | export default SmartEncodingMap; 5 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('./node_modules/eslint-config-twilio/rules/prettier'); 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | }; -------------------------------------------------------------------------------- /dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4DAA2D;AAGlD,iGAHA,mCAAgB,OAGA"} -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { SegmentedMessage } from './libs/SegmentedMessage'; 2 | 3 | // eslint-disable-next-line import/no-unused-modules 4 | export { SegmentedMessage }; 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["twilio-ts"], 3 | "ignorePatterns": ["docs/*", "*.js"], 4 | "rules": { 5 | "@typescript-eslint/member-ordering": "off" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Twilio 2 | 3 | All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. 4 | -------------------------------------------------------------------------------- /dist/libs/UserDataHeader.d.ts: -------------------------------------------------------------------------------- 1 | declare class UserDataHeader { 2 | isReservedChar: boolean; 3 | isUserDataHeader: boolean; 4 | constructor(); 5 | static codeUnitSizeInBits(): number; 6 | sizeInBits(): number; 7 | } 8 | export default UserDataHeader; 9 | -------------------------------------------------------------------------------- /tests/methods.test.js: -------------------------------------------------------------------------------- 1 | const { SegmentedMessage } = require('../dist'); 2 | 3 | describe('Test SegmentedMessage methods', () => { 4 | it('getNonGsmCharacters()', () => { 5 | const testMessage = 'más'; 6 | const segmentedMessage = new SegmentedMessage(testMessage); 7 | expect(segmentedMessage.getNonGsmCharacters()).toEqual(['á']); 8 | }) 9 | }); 10 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.SegmentedMessage = void 0; 4 | var SegmentedMessage_1 = require("./libs/SegmentedMessage"); 5 | Object.defineProperty(exports, "SegmentedMessage", { enumerable: true, get: function () { return SegmentedMessage_1.SegmentedMessage; } }); 6 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "declaration": true, 5 | "module": "commonjs", 6 | "sourceMap": true, 7 | "outDir": "dist", 8 | "esModuleInterop": true, 9 | "downlevelIteration": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "strict": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dist/libs/UserDataHeader.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"UserDataHeader.js","sourceRoot":"","sources":["../../src/libs/UserDataHeader.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH;IAKE;QACE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAC/B,CAAC;IAEM,iCAAkB,GAAzB;QACE,OAAO,CAAC,CAAC;IACX,CAAC;IAED,mCAAU,GAAV;QACE,OAAO,CAAC,CAAC;IACX,CAAC;IACH,qBAAC;AAAD,CAAC,AAjBD,IAiBC;AAED,kBAAe,cAAc,CAAC"} -------------------------------------------------------------------------------- /dist/libs/EncodedChar.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Encoded Character Classes 3 | * Utility classes to represent a character in a given encoding. 4 | */ 5 | declare class EncodedChar { 6 | raw: string; 7 | codeUnits: number[]; 8 | isGSM7: boolean; 9 | encoding: 'GSM-7' | 'UCS-2'; 10 | constructor(char: string, encoding: 'GSM-7' | 'UCS-2'); 11 | codeUnitSizeInBits(): number; 12 | sizeInBits(): number; 13 | } 14 | export default EncodedChar; 15 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branch": "main", 3 | "plugins": [ 4 | "@semantic-release/release-notes-generator", 5 | "@semantic-release/changelog", 6 | "@semantic-release/npm", 7 | "@semantic-release/github", 8 | [ 9 | "@semantic-release/git", 10 | { 11 | "assets": ["docs/scripts/segmentsCalculator.js", "dist/**", "package.json", "CHANGELOG.md"], 12 | "message": "chore(release): Release ${nextRelease.version} [skip ci]" 13 | } 14 | ] 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /dist/libs/Segment.d.ts: -------------------------------------------------------------------------------- 1 | import EncodedChar from './EncodedChar'; 2 | /** 3 | * Segment Class 4 | * A modified array representing one segment and add some helper functions 5 | */ 6 | declare class Segment extends Array { 7 | hasTwilioReservedBits: boolean; 8 | hasUserDataHeader: boolean; 9 | constructor(withUserDataHeader?: boolean); 10 | sizeInBits(): number; 11 | messageSizeInBits(): number; 12 | freeSizeInBits(): number; 13 | addHeader(): EncodedChar[]; 14 | } 15 | export default Segment; 16 | -------------------------------------------------------------------------------- /src/libs/UserDataHeader.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Represent a User Data Header https://en.wikipedia.org/wiki/User_Data_Header 3 | * Twilio messages reserve 6 of this per segment in a concatenated message 4 | */ 5 | 6 | class UserDataHeader { 7 | isReservedChar: boolean; 8 | 9 | isUserDataHeader: boolean; 10 | 11 | constructor() { 12 | this.isReservedChar = true; 13 | this.isUserDataHeader = true; 14 | } 15 | 16 | static codeUnitSizeInBits(): number { 17 | return 8; 18 | } 19 | 20 | sizeInBits(): number { 21 | return 8; 22 | } 23 | } 24 | 25 | export default UserDataHeader; 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Dependency directories 15 | **/node_modules 16 | 17 | # TypeScript v1 declaration files 18 | typings/ 19 | 20 | # Optional npm cache directory 21 | .npm 22 | 23 | # Optional eslint cache 24 | .eslintcache 25 | 26 | # Optional REPL history 27 | .node_repl_history 28 | 29 | # Output of 'npm pack' 30 | *.tgz 31 | 32 | # Yarn Integrity file 33 | .yarn-integrity 34 | 35 | # dotenv environment variables file 36 | .env 37 | 38 | .DS_Store -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/index.ts', 5 | module: { 6 | rules: [ 7 | { 8 | test: /\.tsx?$/, 9 | use: 'ts-loader', 10 | exclude: /node_modules/, 11 | }, 12 | ], 13 | }, 14 | resolve: { 15 | extensions: ['.tsx', '.ts', '.js'], 16 | }, 17 | mode: 'production', 18 | output: { 19 | filename: 'segmentsCalculator.js', 20 | path: path.resolve(__dirname, 'docs/scripts/'), 21 | libraryTarget: "var", 22 | libraryExport: "SegmentedMessage", 23 | library: "SegmentedMessage" 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /dist/libs/UserDataHeader.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | * Represent a User Data Header https://en.wikipedia.org/wiki/User_Data_Header 4 | * Twilio messages reserve 6 of this per segment in a concatenated message 5 | */ 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | var UserDataHeader = /** @class */ (function () { 8 | function UserDataHeader() { 9 | this.isReservedChar = true; 10 | this.isUserDataHeader = true; 11 | } 12 | UserDataHeader.codeUnitSizeInBits = function () { 13 | return 8; 14 | }; 15 | UserDataHeader.prototype.sizeInBits = function () { 16 | return 8; 17 | }; 18 | return UserDataHeader; 19 | }()); 20 | exports.default = UserDataHeader; 21 | //# sourceMappingURL=UserDataHeader.js.map -------------------------------------------------------------------------------- /.github/workflows/test.js.yml: -------------------------------------------------------------------------------- 1 | name: Automated test 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | 7 | jobs: 8 | test: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | strategy: 13 | matrix: 14 | node-version: [14.x, 16.x, 18.x, 19.x] 15 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@v3 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | cache: 'npm' 25 | 26 | - name: Install npm dependencies 27 | run: npm install 28 | 29 | - name: Lint 30 | run: npm run lint 31 | 32 | - name: Test 33 | run: npm test -------------------------------------------------------------------------------- /dist/libs/EncodedChar.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"EncodedChar.js","sourceRoot":"","sources":["../../src/libs/EncodedChar.ts"],"names":[],"mappings":";;;;;AAAA,gEAA0C;AAE1C;;;GAGG;AAEH;IAaE,qBAAY,IAAY,EAAE,QAA2B;QACnD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,sBAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,SAAS,GAAG,sBAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;SACnD;aAAM;YACL,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACpC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;aACzC;SACF;IACH,CAAC;IAED,wCAAkB,GAAlB;QACE,OAAO,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED,gCAAU,GAAV;QACE,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE;YAC5C,4DAA4D;YAC5D,OAAO,EAAE,CAAC;SACX;QACD,IAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,OAAO,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;IAC9C,CAAC;IACH,kBAAC;AAAD,CAAC,AAvCD,IAuCC;AAED,kBAAe,WAAW,CAAC"} -------------------------------------------------------------------------------- /.github/workflows/release.js.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Prepare release and publish package to NPM 3 | 4 | on: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | release: 11 | if: "!contains(github.event.commits[0].message, '[skip ci]')" 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-node@v3 17 | with: 18 | node-version: '18' 19 | 20 | - name: Install npm dependencies 21 | run: npm install 22 | 23 | - name: Lint 24 | run: npm run lint 25 | 26 | - name: Test 27 | run: npm test 28 | 29 | - name: Build 30 | run: npm run release 31 | 32 | - name: Run automated release process with semantic-release 33 | if: github.event_name == 'push' 34 | uses: cycjimmy/semantic-release-action@v3 35 | with: 36 | extra_plugins: | 37 | @semantic-release/changelog 38 | @semantic-release/git 39 | branch: main 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 42 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Twilio Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sms-segments-calculator", 3 | "version": "1.2.0", 4 | "description": "SMS segments calculator", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/TwilioDevEd/message-segment-calculator" 8 | }, 9 | "keywords": [ 10 | "sms", 11 | "segments" 12 | ], 13 | "main": "./dist/index.js", 14 | "types": "./dist/index.d.ts", 15 | "files": [ 16 | "dist/**", 17 | "src/**" 18 | ], 19 | "scripts": { 20 | "test": "tsc && jest", 21 | "build": "tsc", 22 | "dev": "tsc -w", 23 | "lint": "eslint --ext ts src/", 24 | "lint:fix": "npm run lint -- --fix", 25 | "webpack": "webpack --config webpack.config.js", 26 | "release": "tsc && webpack --config webpack.config.js" 27 | }, 28 | "author": "gverni", 29 | "homepage": "https://twiliodeved.github.io/message-segment-calculator/", 30 | "license": "MIT", 31 | "dependencies": { 32 | "grapheme-splitter": "^1.0.4" 33 | }, 34 | "devDependencies": { 35 | "@types/node": "^18.11.18", 36 | "chalk": "^5.2.0", 37 | "eslint": "^8.31.0", 38 | "eslint-config-twilio-ts": "^2.0.0", 39 | "jest": "^29.3.1", 40 | "ts-loader": "^9.2.5", 41 | "ts-node": "^10.2.0", 42 | "typescript": "^4.3.5", 43 | "webpack": "^5.75.0", 44 | "webpack-cli": "^5.0.1" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/libs/EncodedChar.ts: -------------------------------------------------------------------------------- 1 | import UnicodeToGsm from './UnicodeToGSM'; 2 | 3 | /** 4 | * Encoded Character Classes 5 | * Utility classes to represent a character in a given encoding. 6 | */ 7 | 8 | class EncodedChar { 9 | // Raw character (grapheme) as passed in the constructor 10 | raw: string; 11 | 12 | // Array of 8 bits number rapresenting the encoded character 13 | codeUnits: number[]; 14 | 15 | // True if the character is a GSM7 one 16 | isGSM7: boolean; 17 | 18 | // Which encoding to use for this char 19 | encoding: 'GSM-7' | 'UCS-2'; 20 | 21 | constructor(char: string, encoding: 'GSM-7' | 'UCS-2') { 22 | this.raw = char; 23 | this.encoding = encoding; 24 | this.isGSM7 = Boolean(char && char.length === 1 && UnicodeToGsm[char.charCodeAt(0)]); 25 | if (this.isGSM7) { 26 | this.codeUnits = UnicodeToGsm[char.charCodeAt(0)]; 27 | } else { 28 | this.codeUnits = []; 29 | for (let i = 0; i < char.length; i++) { 30 | this.codeUnits.push(char.charCodeAt(i)); 31 | } 32 | } 33 | } 34 | 35 | codeUnitSizeInBits(): number { 36 | return this.encoding === 'GSM-7' ? 7 : 8; 37 | } 38 | 39 | sizeInBits(): number { 40 | if (this.encoding === 'UCS-2' && this.isGSM7) { 41 | // GSM characters are always using 16 bits in UCS-2 encoding 42 | return 16; 43 | } 44 | const bitsPerUnits = this.encoding === 'GSM-7' ? 7 : 16; 45 | return bitsPerUnits * this.codeUnits.length; 46 | } 47 | } 48 | 49 | export default EncodedChar; 50 | -------------------------------------------------------------------------------- /dist/libs/Segment.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"Segment.js","sourceRoot":"","sources":["../../src/libs/Segment.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,oEAA8C;AAG9C;;;GAGG;AAEH;IAAsB,2BAAK;IAKzB,iBAAY,kBAAmC;QAAnC,mCAAA,EAAA,0BAAmC;QAA/C,YACE,iBAAO,SAUR;QATC,0DAA0D;QAC1D,MAAM,CAAC,cAAc,CAAC,KAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC9D,KAAI,CAAC,qBAAqB,GAAG,kBAAkB,CAAC;QAChD,KAAI,CAAC,iBAAiB,GAAG,kBAAkB,CAAC;QAC5C,IAAI,kBAAkB,EAAE;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;gBAC1B,KAAI,CAAC,IAAI,CAAC,IAAI,wBAAc,EAAE,CAAC,CAAC;aACjC;SACF;;IACH,CAAC;IAED,yDAAyD;IACzD,4BAAU,GAAV;QACE,OAAO,IAAI,CAAC,MAAM,CAAC,UAAC,WAAmB,EAAE,WAAoB,IAAK,OAAA,WAAW,GAAG,WAAW,CAAC,UAAU,EAAE,EAAtC,CAAsC,EAAE,CAAC,CAAC,CAAC;IAC/G,CAAC;IAED,yDAAyD;IACzD,mCAAiB,GAAjB;QACE,OAAO,IAAI,CAAC,MAAM,CAChB,UAAC,WAAmB,EAAE,WAAoB;YACxC,OAAA,WAAW,GAAG,CAAC,WAAW,YAAY,wBAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QAApF,CAAoF,EACtF,CAAC,CACF,CAAC;IACJ,CAAC;IAED,gCAAc,GAAd;QACE,IAAM,gBAAgB,GAAG,IAAI,CAAC,CAAC,6DAA6D;QAC5F,OAAO,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IAC9C,CAAC;IAED,2BAAS,GAAT;QACE,IAAI,IAAI,CAAC,iBAAiB,EAAE;YAC1B,OAAO,EAAE,CAAC;SACX;QACD,IAAM,YAAY,GAAkB,EAAE,CAAC;QACvC,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC;QAClC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,wBAAc,EAAE,CAAC,CAAC;SACpC;QACD,oBAAoB;QACpB,OAAO,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,EAAE;YAChC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;SAClC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IACH,cAAC;AAAD,CAAC,AArDD,CAAsB,KAAK,GAqD1B;AAED,kBAAe,OAAO,CAAC"} -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [1.2.0](https://github.com/TwilioDevEd/message-segment-calculator/compare/v1.1.1...v1.2.0) (2022-10-04) 2 | 3 | 4 | ### Features 5 | 6 | * **SmartEncoding:** Add support for Twilio's current SmartEncoding ([79fbec5](https://github.com/TwilioDevEd/message-segment-calculator/commit/79fbec565e237008221ca5aca24fce47bf5d4e70)) 7 | * **SmartEncoding:** Hyperlink "Smart Encoding" and prevent unreadable contrast issue ([d3410eb](https://github.com/TwilioDevEd/message-segment-calculator/commit/d3410ebb60178b1dc69affd2c337079756c3709e)) 8 | 9 | ## [1.1.1](https://github.com/TwilioDevEd/message-segment-calculator/compare/v1.1.0...v1.1.1) (2021-10-12) 10 | 11 | 12 | ### Bug Fixes 13 | 14 | * GSM-7 special character size calculation in UCS-2 encoding ([636ed81](https://github.com/TwilioDevEd/message-segment-calculator/commit/636ed814ed8b9de5b28002692df3d3acae2fc1b9)) 15 | 16 | # [1.1.0](https://github.com/TwilioDevEd/message-segment-calculator/compare/v1.0.2...v1.1.0) (2021-08-27) 17 | 18 | 19 | ### Features 20 | 21 | * **core:** Add `getNonGsmCharacters()` method ([#11](https://github.com/TwilioDevEd/message-segment-calculator/issues/11)) ([159c838](https://github.com/TwilioDevEd/message-segment-calculator/commit/159c8383f3ab0d74ffb7c2c67cda13e61e39683e)), closes [#9](https://github.com/TwilioDevEd/message-segment-calculator/issues/9) 22 | 23 | ## [1.0.2](https://github.com/TwilioDevEd/message-segment-calculator/compare/v1.0.1...v1.0.2) (2021-08-19) 24 | 25 | 26 | ### Bug Fixes 27 | 28 | * Bug in calculating one char UCS-2 ([f489fa2](https://github.com/TwilioDevEd/message-segment-calculator/commit/f489fa25bc2c13f1bf4c6e48f6c3bb2b0512b5af)) 29 | -------------------------------------------------------------------------------- /dist/libs/EncodedChar.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | var UnicodeToGSM_1 = __importDefault(require("./UnicodeToGSM")); 7 | /** 8 | * Encoded Character Classes 9 | * Utility classes to represent a character in a given encoding. 10 | */ 11 | var EncodedChar = /** @class */ (function () { 12 | function EncodedChar(char, encoding) { 13 | this.raw = char; 14 | this.encoding = encoding; 15 | this.isGSM7 = Boolean(char && char.length === 1 && UnicodeToGSM_1.default[char.charCodeAt(0)]); 16 | if (this.isGSM7) { 17 | this.codeUnits = UnicodeToGSM_1.default[char.charCodeAt(0)]; 18 | } 19 | else { 20 | this.codeUnits = []; 21 | for (var i = 0; i < char.length; i++) { 22 | this.codeUnits.push(char.charCodeAt(i)); 23 | } 24 | } 25 | } 26 | EncodedChar.prototype.codeUnitSizeInBits = function () { 27 | return this.encoding === 'GSM-7' ? 7 : 8; 28 | }; 29 | EncodedChar.prototype.sizeInBits = function () { 30 | if (this.encoding === 'UCS-2' && this.isGSM7) { 31 | // GSM characters are always using 16 bits in UCS-2 encoding 32 | return 16; 33 | } 34 | var bitsPerUnits = this.encoding === 'GSM-7' ? 7 : 16; 35 | return bitsPerUnits * this.codeUnits.length; 36 | }; 37 | return EncodedChar; 38 | }()); 39 | exports.default = EncodedChar; 40 | //# sourceMappingURL=EncodedChar.js.map -------------------------------------------------------------------------------- /tests/segments.test.js: -------------------------------------------------------------------------------- 1 | 2 | const { SegmentedMessage } = require('../dist'); 3 | 4 | describe('GSM-7 Segements analysis', () => { 5 | const testMessage = 6 | '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567'; 7 | const segmentedMessage = new SegmentedMessage(testMessage); 8 | test('Check User Data Header', () => { 9 | for (var segmentIndex = 0; segmentIndex <= 2; segmentIndex++) { 10 | for (var index = 0; index < 6; index++) { 11 | expect(segmentedMessage.segments[segmentIndex][index].isUserDataHeader).toBe(true); 12 | } 13 | } 14 | }); 15 | 16 | test('Check last segment has only 1 character', () => { 17 | expect(segmentedMessage.segments[2].length).toBe(7); 18 | expect(segmentedMessage.segments[2][6].raw).toBe('7'); 19 | }); 20 | }); 21 | 22 | describe('UCS-2 Segements analysis', () => { 23 | const testMessage = 24 | '😜2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234'; 25 | const segmentedMessage = new SegmentedMessage(testMessage); 26 | test('Check User Data Header', () => { 27 | for (var segmentIndex = 0; segmentIndex <= 2; segmentIndex++) { 28 | for (var index = 0; index < 6; index++) { 29 | expect(segmentedMessage.segments[segmentIndex][index].isUserDataHeader).toBe(true); 30 | } 31 | } 32 | }); 33 | 34 | test('Check last segment has only 1 character', () => { 35 | expect(segmentedMessage.segments[2].length).toBe(7); 36 | expect(segmentedMessage.segments[2][6].raw).toBe('4'); 37 | }); 38 | }); -------------------------------------------------------------------------------- /src/libs/Segment.ts: -------------------------------------------------------------------------------- 1 | import UserDataHeader from './UserDataHeader'; 2 | import EncodedChar from './EncodedChar'; 3 | 4 | /** 5 | * Segment Class 6 | * A modified array representing one segment and add some helper functions 7 | */ 8 | 9 | class Segment extends Array { 10 | hasTwilioReservedBits: boolean; 11 | 12 | hasUserDataHeader: boolean; 13 | 14 | constructor(withUserDataHeader: boolean = false) { 15 | super(); 16 | // TODO: Refactor this. Bad practice to extend basic types 17 | Object.setPrototypeOf(this, Object.create(Segment.prototype)); 18 | this.hasTwilioReservedBits = withUserDataHeader; 19 | this.hasUserDataHeader = withUserDataHeader; 20 | if (withUserDataHeader) { 21 | for (let i = 0; i < 6; i++) { 22 | this.push(new UserDataHeader()); 23 | } 24 | } 25 | } 26 | 27 | // Size in bits *including* User Data Header (if present) 28 | sizeInBits(): number { 29 | return this.reduce((accumulator: number, encodedChar: Segment) => accumulator + encodedChar.sizeInBits(), 0); 30 | } 31 | 32 | // Size in bits *excluding* User Data Header (if present) 33 | messageSizeInBits(): number { 34 | return this.reduce( 35 | (accumulator: number, encodedChar: Segment) => 36 | accumulator + (encodedChar instanceof UserDataHeader ? 0 : encodedChar.sizeInBits()), 37 | 0, 38 | ); 39 | } 40 | 41 | freeSizeInBits(): number { 42 | const maxBitsInSegment = 1120; // max size of a SMS is 140 octets -> 140 * 8bits = 1120 bits 43 | return maxBitsInSegment - this.sizeInBits(); 44 | } 45 | 46 | addHeader(): EncodedChar[] { 47 | if (this.hasUserDataHeader) { 48 | return []; 49 | } 50 | const leftOverChar: EncodedChar[] = []; 51 | this.hasTwilioReservedBits = true; 52 | this.hasUserDataHeader = false; 53 | for (let i = 0; i < 6; i++) { 54 | this.unshift(new UserDataHeader()); 55 | } 56 | // Remove characters 57 | while (this.freeSizeInBits() < 0) { 58 | leftOverChar.unshift(this.pop()); 59 | } 60 | return leftOverChar; 61 | } 62 | } 63 | 64 | export default Segment; 65 | -------------------------------------------------------------------------------- /playground/index.js: -------------------------------------------------------------------------------- 1 | const { SegmentedMessage } = require('../dist'); 2 | const chalk = require('chalk'); 3 | 4 | const encodingColors = { 5 | 'GSM-7': chalk.green, 6 | 'UCS-2': chalk.yellow, 7 | UDH: chalk.grey, 8 | }; 9 | 10 | if (!process.argv[2]) { 11 | console.log(` 12 | Usage: 13 | node index.js "" 14 | 15 | Example: 16 | node index.js "👋 Hello World 🌍" 17 | `); 18 | return; 19 | } 20 | 21 | const message = process.argv[2]; 22 | const segmentedMessage = new SegmentedMessage(message); 23 | 24 | function serializeSegment(segment) { 25 | let result = []; 26 | segment.forEach((char) => { 27 | if (char.codeUnits) { 28 | char.codeUnits.forEach((codeUnit) => { 29 | result.push({ 30 | value: `0x${codeUnit.toString(16)}`, 31 | type: char.isGSM7 ? 'GSM-7' : 'UCS-2', 32 | }); 33 | }); 34 | } else { 35 | result.push({ value: 'UDH', type: 'UDH' }); 36 | } 37 | }); 38 | return result; 39 | } 40 | 41 | console.log(` 42 | Encoding: ${chalk.magenta(segmentedMessage.encodingName)} 43 | Number of Segment: ${chalk.magenta(segmentedMessage.segmentsCount)} 44 | Message Size: ${chalk.magenta(segmentedMessage.messageSize)} 45 | Total Size: ${chalk.magenta(segmentedMessage.totalSize)} 46 | Number of Unicode Scalars: ${chalk.magenta(segmentedMessage.numberOfUnicodeScalars)} 47 | Number of Characters: ${chalk.magenta(segmentedMessage.numberOfCharacters)} 48 | 49 | ${chalk.blue('Segments encoding')}`); 50 | 51 | segmentedMessage.segments.forEach((segment, index) => { 52 | console.log(chalk.cyan(`\nSegment ${index + 1}\n`)); 53 | let serializedSegment = serializeSegment(segment); 54 | let byteIndex = 0; 55 | while (byteIndex < serializedSegment.length) { 56 | let byteRow = `${byteIndex}\t`; 57 | for (let col = 0; col < 10; col++) { 58 | let byte = serializedSegment[byteIndex]; 59 | if (byte) { 60 | byteRow += `${encodingColors[byte.type](byte.value)}\t`; 61 | } 62 | byteIndex += 1; 63 | } 64 | console.log(byteRow); 65 | } 66 | }); 67 | 68 | console.log(`\n`); 69 | -------------------------------------------------------------------------------- /dist/libs/Segment.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | if (typeof b !== "function" && b !== null) 11 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); 12 | extendStatics(d, b); 13 | function __() { this.constructor = d; } 14 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 15 | }; 16 | })(); 17 | var __importDefault = (this && this.__importDefault) || function (mod) { 18 | return (mod && mod.__esModule) ? mod : { "default": mod }; 19 | }; 20 | Object.defineProperty(exports, "__esModule", { value: true }); 21 | var UserDataHeader_1 = __importDefault(require("./UserDataHeader")); 22 | /** 23 | * Segment Class 24 | * A modified array representing one segment and add some helper functions 25 | */ 26 | var Segment = /** @class */ (function (_super) { 27 | __extends(Segment, _super); 28 | function Segment(withUserDataHeader) { 29 | if (withUserDataHeader === void 0) { withUserDataHeader = false; } 30 | var _this = _super.call(this) || this; 31 | // TODO: Refactor this. Bad practice to extend basic types 32 | Object.setPrototypeOf(_this, Object.create(Segment.prototype)); 33 | _this.hasTwilioReservedBits = withUserDataHeader; 34 | _this.hasUserDataHeader = withUserDataHeader; 35 | if (withUserDataHeader) { 36 | for (var i = 0; i < 6; i++) { 37 | _this.push(new UserDataHeader_1.default()); 38 | } 39 | } 40 | return _this; 41 | } 42 | // Size in bits *including* User Data Header (if present) 43 | Segment.prototype.sizeInBits = function () { 44 | return this.reduce(function (accumulator, encodedChar) { return accumulator + encodedChar.sizeInBits(); }, 0); 45 | }; 46 | // Size in bits *excluding* User Data Header (if present) 47 | Segment.prototype.messageSizeInBits = function () { 48 | return this.reduce(function (accumulator, encodedChar) { 49 | return accumulator + (encodedChar instanceof UserDataHeader_1.default ? 0 : encodedChar.sizeInBits()); 50 | }, 0); 51 | }; 52 | Segment.prototype.freeSizeInBits = function () { 53 | var maxBitsInSegment = 1120; // max size of a SMS is 140 octets -> 140 * 8bits = 1120 bits 54 | return maxBitsInSegment - this.sizeInBits(); 55 | }; 56 | Segment.prototype.addHeader = function () { 57 | if (this.hasUserDataHeader) { 58 | return []; 59 | } 60 | var leftOverChar = []; 61 | this.hasTwilioReservedBits = true; 62 | this.hasUserDataHeader = false; 63 | for (var i = 0; i < 6; i++) { 64 | this.unshift(new UserDataHeader_1.default()); 65 | } 66 | // Remove characters 67 | while (this.freeSizeInBits() < 0) { 68 | leftOverChar.unshift(this.pop()); 69 | } 70 | return leftOverChar; 71 | }; 72 | return Segment; 73 | }(Array)); 74 | exports.default = Segment; 75 | //# sourceMappingURL=Segment.js.map -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at open-source@twilio.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /src/libs/UnicodeToGSM.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * In order to avoid confusion here is a list of terms 3 | * used throughout this code: 4 | * - octet: represent a byte or 8bits 5 | * - septet: represent 7bits 6 | * - character: a text unit, think one char is one glyph (Warning: this is an oversimplification and not always true) 7 | * - code point: a character value in a given encoding 8 | * - code unit: a single "block" used to encode a character 9 | * UCS-2 is of fixed length and every character is 2 code units long 10 | * GSM-7 is of variable length and require 1 or 2 code unit per character 11 | */ 12 | 13 | // Map of Javascript code points to GSM-7 14 | const UnicodeToGsm: Record> = { 15 | 0x000a: [0x0a], 16 | 0x000c: [0x1b, 0x0a], 17 | 0x000d: [0x0d], 18 | 0x0020: [0x20], 19 | 0x0021: [0x21], 20 | 0x0022: [0x22], 21 | 0x0023: [0x23], 22 | 0x0024: [0x02], 23 | 0x0025: [0x25], 24 | 0x0026: [0x26], 25 | 0x0027: [0x27], 26 | 0x0028: [0x28], 27 | 0x0029: [0x29], 28 | 0x002a: [0x2a], 29 | 0x002b: [0x2b], 30 | 0x002c: [0x2c], 31 | 0x002d: [0x2d], 32 | 0x002e: [0x2e], 33 | 0x002f: [0x2f], 34 | 0x0030: [0x30], 35 | 0x0031: [0x31], 36 | 0x0032: [0x32], 37 | 0x0033: [0x33], 38 | 0x0034: [0x34], 39 | 0x0035: [0x35], 40 | 0x0036: [0x36], 41 | 0x0037: [0x37], 42 | 0x0038: [0x38], 43 | 0x0039: [0x39], 44 | 0x003a: [0x3a], 45 | 0x003b: [0x3b], 46 | 0x003c: [0x3c], 47 | 0x003d: [0x3d], 48 | 0x003e: [0x3e], 49 | 0x003f: [0x3f], 50 | 0x0040: [0x00], 51 | 0x0041: [0x41], 52 | 0x0042: [0x42], 53 | 0x0043: [0x43], 54 | 0x0044: [0x44], 55 | 0x0045: [0x45], 56 | 0x0046: [0x46], 57 | 0x0047: [0x47], 58 | 0x0048: [0x48], 59 | 0x0049: [0x49], 60 | 0x004a: [0x4a], 61 | 0x004b: [0x4b], 62 | 0x004c: [0x4c], 63 | 0x004d: [0x4d], 64 | 0x004e: [0x4e], 65 | 0x004f: [0x4f], 66 | 0x0050: [0x50], 67 | 0x0051: [0x51], 68 | 0x0052: [0x52], 69 | 0x0053: [0x53], 70 | 0x0054: [0x54], 71 | 0x0055: [0x55], 72 | 0x0056: [0x56], 73 | 0x0057: [0x57], 74 | 0x0058: [0x58], 75 | 0x0059: [0x59], 76 | 0x005a: [0x5a], 77 | 0x005b: [0x1b, 0x3c], 78 | 0x005c: [0x1b, 0x2f], 79 | 0x005d: [0x1b, 0x3e], 80 | 0x005e: [0x1b, 0x14], 81 | 0x005f: [0x11], 82 | 0x0061: [0x61], 83 | 0x0062: [0x62], 84 | 0x0063: [0x63], 85 | 0x0064: [0x64], 86 | 0x0065: [0x65], 87 | 0x0066: [0x66], 88 | 0x0067: [0x67], 89 | 0x0068: [0x68], 90 | 0x0069: [0x69], 91 | 0x006a: [0x6a], 92 | 0x006b: [0x6b], 93 | 0x006c: [0x6c], 94 | 0x006d: [0x6d], 95 | 0x006e: [0x6e], 96 | 0x006f: [0x6f], 97 | 0x0070: [0x70], 98 | 0x0071: [0x71], 99 | 0x0072: [0x72], 100 | 0x0073: [0x73], 101 | 0x0074: [0x74], 102 | 0x0075: [0x75], 103 | 0x0076: [0x76], 104 | 0x0077: [0x77], 105 | 0x0078: [0x78], 106 | 0x0079: [0x79], 107 | 0x007a: [0x7a], 108 | 0x007b: [0x1b, 0x28], 109 | 0x007c: [0x1b, 0x40], 110 | 0x007d: [0x1b, 0x29], 111 | 0x007e: [0x1b, 0x3d], 112 | 0x00a1: [0x40], 113 | 0x00a3: [0x01], 114 | 0x00a4: [0x24], 115 | 0x00a5: [0x03], 116 | 0x00a7: [0x5f], 117 | 0x00bf: [0x60], 118 | 0x00c4: [0x5b], 119 | 0x00c5: [0x0e], 120 | 0x00c6: [0x1c], 121 | 0x00c9: [0x1f], 122 | 0x00d1: [0x5d], 123 | 0x00d6: [0x5c], 124 | 0x00d8: [0x0b], 125 | 0x00dc: [0x5e], 126 | 0x00df: [0x1e], 127 | 0x00e0: [0x7f], 128 | 0x00e4: [0x7b], 129 | 0x00e5: [0x0f], 130 | 0x00e6: [0x1d], 131 | 0x00c7: [0x09], 132 | 0x00e8: [0x04], 133 | 0x00e9: [0x05], 134 | 0x00ec: [0x07], 135 | 0x00f1: [0x7d], 136 | 0x00f2: [0x08], 137 | 0x00f6: [0x7c], 138 | 0x00f8: [0x0c], 139 | 0x00f9: [0x06], 140 | 0x00fc: [0x7e], 141 | 0x0393: [0x13], 142 | 0x0394: [0x10], 143 | 0x0398: [0x19], 144 | 0x039b: [0x14], 145 | 0x039e: [0x1a], 146 | 0x03a0: [0x16], 147 | 0x03a3: [0x18], 148 | 0x03a6: [0x12], 149 | 0x03a8: [0x17], 150 | 0x03a9: [0x15], 151 | 0x20ac: [0x1b, 0x65], 152 | }; 153 | 154 | export default UnicodeToGsm; 155 | -------------------------------------------------------------------------------- /dist/libs/SegmentedMessage.d.ts: -------------------------------------------------------------------------------- 1 | import Segment from './Segment'; 2 | import EncodedChar from './EncodedChar'; 3 | type SmsEncoding = 'GSM-7' | 'UCS-2'; 4 | type EncodedChars = Array; 5 | declare type LineBreakStyle = 'LF' | 'CRLF' | 'LF+CRLF' | undefined; 6 | /** 7 | * Class representing a segmented SMS 8 | */ 9 | export declare class SegmentedMessage { 10 | encoding: SmsEncoding | 'auto'; 11 | segments: Segment[]; 12 | graphemes: string[]; 13 | encodingName: SmsEncoding; 14 | numberOfUnicodeScalars: number; 15 | numberOfCharacters: number; 16 | encodedChars: EncodedChars; 17 | lineBreakStyle: LineBreakStyle; 18 | warnings: string[]; 19 | /** 20 | * 21 | * Create a new segmented message from a string 22 | * 23 | * @param {string} message Body of the message 24 | * @param {boolean} [encoding] Optional: encoding. It can be 'GSM-7', 'UCS-2', 'auto'. Default value: 'auto' 25 | * @param {boolean} smartEncoding Optional: whether or not Twilio's [Smart Encoding](https://www.twilio.com/docs/messaging/services#smart-encoding) is emulated. Default value: false 26 | * @property {number} numberOfUnicodeScalars Number of Unicode Scalars (i.e. unicode pairs) the message is made of 27 | * 28 | */ 29 | constructor(message: string, encoding?: SmsEncoding | 'auto', smartEncoding?: boolean); 30 | /** 31 | * Internal method to check if the message has any non-GSM7 characters 32 | * 33 | * @param {string[]} graphemes Message body 34 | * @returns {boolean} True if there are non-GSM-7 characters 35 | * @private 36 | */ 37 | _hasAnyUCSCharacters(graphemes: string[]): boolean; 38 | /** 39 | * Internal method used to build message's segment(s) 40 | * 41 | * @param {object[]} encodedChars Array of EncodedChar 42 | * @returns {object[]} Array of Segment 43 | * @private 44 | */ 45 | _buildSegments(encodedChars: EncodedChars): Segment[]; 46 | /** 47 | * Return the encoding of the message segment 48 | * 49 | * @returns {string} Encoding for the message segment(s) 50 | */ 51 | getEncodingName(): string; 52 | /** 53 | * Internal method to create an array of EncodedChar from a string 54 | * 55 | * @param {string[]} graphemes Array of graphemes representing the message 56 | * @returns {object[]} Array of EncodedChar 57 | * @private 58 | */ 59 | _encodeChars(graphemes: string[]): EncodedChars; 60 | /** 61 | * Internal method to count the total number of code units of the message 62 | * 63 | * @param {EncodedChar[]} encodedChars Encoded message body 64 | * @returns {number} The total number of code units 65 | * @private 66 | */ 67 | _countCodeUnits(encodedChars: EncodedChar[]): number; 68 | /** 69 | * @returns {number} Total size of the message in bits (including User Data Header if present) 70 | */ 71 | get totalSize(): number; 72 | /** 73 | * @returns {number} Total size of the message in bits (excluding User Data Header if present) 74 | */ 75 | get messageSize(): number; 76 | /** 77 | * 78 | * @returns {number} Number of segments 79 | */ 80 | get segmentsCount(): number; 81 | /** 82 | * 83 | * @returns {string[]} Array of characters representing the non GSM-7 characters in the message body 84 | */ 85 | getNonGsmCharacters(): string[]; 86 | /** 87 | * Internal method to check the line break styled used in the passed message 88 | * 89 | * @param {string} message Message body 90 | * @returns {LineBreakStyle} The libre break style name LF or CRLF 91 | * @private 92 | */ 93 | _detectLineBreakStyle(message: string): LineBreakStyle; 94 | /** 95 | * Internal method to check the line break styled used in the passed message 96 | * 97 | * @returns {string[]} The libre break style name LF or CRLF 98 | * @private 99 | */ 100 | _checkForWarnings(): string[]; 101 | } 102 | export {}; 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SMS Segment Calculator 2 | 3 | This repo contains a package for an SMS segments calculator. The package is released as a nodeJS package as well as a browser script. 4 | A browser demo for this package can be accessed [here](https://twiliodeved.github.io/message-segment-calculator/) 5 | 6 | ## Usage 7 | 8 | ### nodeJS 9 | 10 | The package can be installed using: 11 | 12 | ```shell 13 | npm install --save sms-segments-calculator 14 | ``` 15 | 16 | Sample usage: 17 | 18 | ```javascript 19 | const { SegmentedMessage } = require('sms-segments-calculator'); 20 | 21 | const segmentedMessage = new SegmentedMessage('Hello World'); 22 | 23 | console.log(segmentedMessage.encodingName); // "GSM-7" 24 | console.log(segmentedMessage.segmentsCount); // "1" 25 | ``` 26 | 27 | ### Browser 28 | 29 | You can add the library to your page using the CDN file: 30 | 31 | ```html 32 | 33 | ``` 34 | 35 | Alternatively you can add the library to your page using the file [`segmentsCalculator.js`](https://github.com/TwilioDevEd/message-segment-calculator/blob/main/docs/scripts/segmentsCalculator.js) provided in `docs/scripts/` and adding it to your page: 36 | 37 | ```html 38 | 39 | ``` 40 | 41 | And example of usage can be find in [`docs/index.html`](https://github.com/TwilioDevEd/message-segment-calculator/blob/main/docs/index.html) 42 | 43 | ## Documentation 44 | ### `SegmentedMessage` class 45 | 46 | This is the main class exposed by the package 47 | 48 | #### [`constructor(message, encoding)`](https://github.com/TwilioDevEd/message-segment-calculator/blob/403313a44ed406b3669cf3c57f32ca98fd92b1e1/src/libs/SegmentedMessage.ts#L37) 49 | Arguments: 50 | * `message`: Body of the SMS 51 | * `encoding`: Optional: encoding. It can be `GSM-7`, `UCS-2`, `auto`. Default value: `auto` 52 | 53 | ##### `encodingName` 54 | 55 | Returns the name of the calculated encoding for the message: `GSM-7` or `UCS-2` 56 | 57 | #### [`totalSize`](https://github.com/TwilioDevEd/message-segment-calculator/blob/403313a44ed406b3669cf3c57f32ca98fd92b1e1/src/libs/SegmentedMessage.ts#L161) 58 | 59 | Total size of the message in bits (including User Data Header if present) 60 | 61 | #### [`messageSize`](https://github.com/TwilioDevEd/message-segment-calculator/blob/403313a44ed406b3669cf3c57f32ca98fd92b1e1/src/libs/SegmentedMessage.ts#L172) 62 | 63 | Total size of the message in bits (excluding User Data Header if present) 64 | 65 | #### [`segmentsCount`](https://github.com/TwilioDevEd/message-segment-calculator/blob/403313a44ed406b3669cf3c57f32ca98fd92b1e1/src/libs/SegmentedMessage.ts#L184) 66 | 67 | Number of segment(s) 68 | 69 | ### [`getNonGsmCharacters()`] 70 | 71 | Return an array with the non GSM-7 characters in the body. It can be used to replace character and reduce the number of segments 72 | 73 | ## Try the library 74 | 75 | If you want to test the library you can use the script provided in `playground/index.js`. Install the dependencies (`npm install`) and then run: 76 | 77 | ```shell 78 | $ node playground/index.js "👋 Hello World 🌍" 79 | ``` 80 | 81 | ## Contributing 82 | 83 | This code is open source and welcomes contributions. All contributions are subject to our [Code of Conduct](https://github.com/twilio-labs/.github/blob/master/CODE_OF_CONDUCT.md). 84 | 85 | The source code for the library is all contained in the `src` folder. Before submitting a PR: 86 | 87 | * Run linter using `npm run lint` command and make sure there are no linter error 88 | * Compile the code using `npm run build` command and make sure there are no errors 89 | * Execute the test using `npm test` and make sure all tests pass 90 | * Transpile the code using `npm run webpack` and test the web page in `docs/index.html` 91 | 92 | ## License 93 | 94 | [MIT](http://www.opensource.org/licenses/mit-license.html) 95 | 96 | ## Disclaimer 97 | 98 | No warranty expressed or implied. Software is as is. 99 | 100 | [twilio]: https://www.twilio.com 101 | -------------------------------------------------------------------------------- /dist/libs/UnicodeToGSM.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"UnicodeToGSM.js","sourceRoot":"","sources":["../../src/libs/UnicodeToGSM.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAEH,yCAAyC;AACzC,IAAM,YAAY,GAAkC;IAClD,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB,CAAC;AAEF,kBAAe,YAAY,CAAC"} -------------------------------------------------------------------------------- /dist/libs/UnicodeToGSM.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | * In order to avoid confusion here is a list of terms 4 | * used throughout this code: 5 | * - octet: represent a byte or 8bits 6 | * - septet: represent 7bits 7 | * - character: a text unit, think one char is one glyph (Warning: this is an oversimplification and not always true) 8 | * - code point: a character value in a given encoding 9 | * - code unit: a single "block" used to encode a character 10 | * UCS-2 is of fixed length and every character is 2 code units long 11 | * GSM-7 is of variable length and require 1 or 2 code unit per character 12 | */ 13 | Object.defineProperty(exports, "__esModule", { value: true }); 14 | // Map of Javascript code points to GSM-7 15 | var UnicodeToGsm = { 16 | 0x000a: [0x0a], 17 | 0x000c: [0x1b, 0x0a], 18 | 0x000d: [0x0d], 19 | 0x0020: [0x20], 20 | 0x0021: [0x21], 21 | 0x0022: [0x22], 22 | 0x0023: [0x23], 23 | 0x0024: [0x02], 24 | 0x0025: [0x25], 25 | 0x0026: [0x26], 26 | 0x0027: [0x27], 27 | 0x0028: [0x28], 28 | 0x0029: [0x29], 29 | 0x002a: [0x2a], 30 | 0x002b: [0x2b], 31 | 0x002c: [0x2c], 32 | 0x002d: [0x2d], 33 | 0x002e: [0x2e], 34 | 0x002f: [0x2f], 35 | 0x0030: [0x30], 36 | 0x0031: [0x31], 37 | 0x0032: [0x32], 38 | 0x0033: [0x33], 39 | 0x0034: [0x34], 40 | 0x0035: [0x35], 41 | 0x0036: [0x36], 42 | 0x0037: [0x37], 43 | 0x0038: [0x38], 44 | 0x0039: [0x39], 45 | 0x003a: [0x3a], 46 | 0x003b: [0x3b], 47 | 0x003c: [0x3c], 48 | 0x003d: [0x3d], 49 | 0x003e: [0x3e], 50 | 0x003f: [0x3f], 51 | 0x0040: [0x00], 52 | 0x0041: [0x41], 53 | 0x0042: [0x42], 54 | 0x0043: [0x43], 55 | 0x0044: [0x44], 56 | 0x0045: [0x45], 57 | 0x0046: [0x46], 58 | 0x0047: [0x47], 59 | 0x0048: [0x48], 60 | 0x0049: [0x49], 61 | 0x004a: [0x4a], 62 | 0x004b: [0x4b], 63 | 0x004c: [0x4c], 64 | 0x004d: [0x4d], 65 | 0x004e: [0x4e], 66 | 0x004f: [0x4f], 67 | 0x0050: [0x50], 68 | 0x0051: [0x51], 69 | 0x0052: [0x52], 70 | 0x0053: [0x53], 71 | 0x0054: [0x54], 72 | 0x0055: [0x55], 73 | 0x0056: [0x56], 74 | 0x0057: [0x57], 75 | 0x0058: [0x58], 76 | 0x0059: [0x59], 77 | 0x005a: [0x5a], 78 | 0x005b: [0x1b, 0x3c], 79 | 0x005c: [0x1b, 0x2f], 80 | 0x005d: [0x1b, 0x3e], 81 | 0x005e: [0x1b, 0x14], 82 | 0x005f: [0x11], 83 | 0x0061: [0x61], 84 | 0x0062: [0x62], 85 | 0x0063: [0x63], 86 | 0x0064: [0x64], 87 | 0x0065: [0x65], 88 | 0x0066: [0x66], 89 | 0x0067: [0x67], 90 | 0x0068: [0x68], 91 | 0x0069: [0x69], 92 | 0x006a: [0x6a], 93 | 0x006b: [0x6b], 94 | 0x006c: [0x6c], 95 | 0x006d: [0x6d], 96 | 0x006e: [0x6e], 97 | 0x006f: [0x6f], 98 | 0x0070: [0x70], 99 | 0x0071: [0x71], 100 | 0x0072: [0x72], 101 | 0x0073: [0x73], 102 | 0x0074: [0x74], 103 | 0x0075: [0x75], 104 | 0x0076: [0x76], 105 | 0x0077: [0x77], 106 | 0x0078: [0x78], 107 | 0x0079: [0x79], 108 | 0x007a: [0x7a], 109 | 0x007b: [0x1b, 0x28], 110 | 0x007c: [0x1b, 0x40], 111 | 0x007d: [0x1b, 0x29], 112 | 0x007e: [0x1b, 0x3d], 113 | 0x00a1: [0x40], 114 | 0x00a3: [0x01], 115 | 0x00a4: [0x24], 116 | 0x00a5: [0x03], 117 | 0x00a7: [0x5f], 118 | 0x00bf: [0x60], 119 | 0x00c4: [0x5b], 120 | 0x00c5: [0x0e], 121 | 0x00c6: [0x1c], 122 | 0x00c9: [0x1f], 123 | 0x00d1: [0x5d], 124 | 0x00d6: [0x5c], 125 | 0x00d8: [0x0b], 126 | 0x00dc: [0x5e], 127 | 0x00df: [0x1e], 128 | 0x00e0: [0x7f], 129 | 0x00e4: [0x7b], 130 | 0x00e5: [0x0f], 131 | 0x00e6: [0x1d], 132 | 0x00c7: [0x09], 133 | 0x00e8: [0x04], 134 | 0x00e9: [0x05], 135 | 0x00ec: [0x07], 136 | 0x00f1: [0x7d], 137 | 0x00f2: [0x08], 138 | 0x00f6: [0x7c], 139 | 0x00f8: [0x0c], 140 | 0x00f9: [0x06], 141 | 0x00fc: [0x7e], 142 | 0x0393: [0x13], 143 | 0x0394: [0x10], 144 | 0x0398: [0x19], 145 | 0x039b: [0x14], 146 | 0x039e: [0x1a], 147 | 0x03a0: [0x16], 148 | 0x03a3: [0x18], 149 | 0x03a6: [0x12], 150 | 0x03a8: [0x17], 151 | 0x03a9: [0x15], 152 | 0x20ac: [0x1b, 0x65], 153 | }; 154 | exports.default = UnicodeToGsm; 155 | //# sourceMappingURL=UnicodeToGSM.js.map -------------------------------------------------------------------------------- /dist/libs/SegmentedMessage.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"SegmentedMessage.js","sourceRoot":"","sources":["../../src/libs/SegmentedMessage.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wEAAiD;AAEjD,sDAAgC;AAChC,8DAAwC;AACxC,gEAA0C;AAC1C,wEAAkD;AAMlD,IAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAIvD;;GAEG;AACH;IAmBE;;;;;;;;;OASG;IACH,0BAAY,OAAe,EAAE,QAAuC,EAAE,aAA8B;QAAvE,yBAAA,EAAA,iBAAuC;QAAE,8BAAA,EAAA,qBAA8B;QAClG,IAAM,QAAQ,GAAG,IAAI,2BAAgB,EAAE,CAAC;QAExC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YAC3C,MAAM,IAAI,KAAK,CACb,mBAAY,QAAQ,2DAAiD,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAE,CACtG,CAAC;SACH;QAED,IAAI,aAAa,EAAE;YACjB,OAAO,GAAG,yBAAI,OAAO,UAClB,GAAG,CAAS,UAAC,IAAI,IAAK,OAAA,CAAC,0BAAgB,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,0BAAgB,CAAC,IAAI,CAAC,CAAC,EAAtE,CAAsE,CAAC;iBAC7F,IAAI,CAAC,EAAE,CAAC,CAAC;SACb;QAED;;WAEG;QACH,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,UAAC,WAAqB,EAAE,QAAgB;YAC/F,IAAM,MAAM,GAAG,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACrE,OAAO,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC,EAAE,EAAE,CAAC,CAAC;QACP;;;WAGG;QACH,IAAI,CAAC,sBAAsB,GAAG,yBAAI,OAAO,UAAE,MAAM,CAAC;QAClD;;;WAGG;QACH,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,EAAE;YAC5B;;eAEG;YACH,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;SACnF;aAAM;YACL,IAAI,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;gBACrE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;aAC5E;YACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC;SACnC;QAED;;WAEG;QACH,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtD;;;WAGG;QACH,IAAI,CAAC,kBAAkB;YACrB,IAAI,CAAC,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAElG;;WAEG;QACH,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEvD;;WAEG;QACH,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAE1D;;WAEG;QACH,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,+CAAoB,GAApB,UAAqB,SAAmB;;QACtC,IAAI,MAAM,GAAG,KAAK,CAAC;;YACnB,KAAuB,IAAA,cAAA,SAAA,SAAS,CAAA,oCAAA,2DAAE;gBAA7B,IAAM,QAAQ,sBAAA;gBACjB,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,sBAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;oBAC5F,MAAM,GAAG,IAAI,CAAC;oBACd,MAAM;iBACP;aACF;;;;;;;;;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IAEH,yCAAc,GAAd,UAAe,YAA0B;;QACvC,IAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAO,EAAE,CAAC,CAAC;QAC7B,IAAI,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;;YAEjC,KAA0B,IAAA,iBAAA,SAAA,YAAY,CAAA,0CAAA,oEAAE;gBAAnC,IAAM,WAAW,yBAAA;gBACpB,IAAI,cAAc,CAAC,cAAc,EAAE,GAAG,WAAW,CAAC,UAAU,EAAE,EAAE;oBAC9D,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAO,CAAC,IAAI,CAAC,CAAC,CAAC;oBACjC,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBAC/C,IAAM,eAAe,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBAEtD,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE;wBACtC,IAAM,YAAY,GAAG,eAAe,CAAC,SAAS,EAAE,CAAC;wBACjD,wCAAwC;wBACxC,YAAY,CAAC,OAAO,CAAC,UAAC,IAAI,IAAK,OAAA,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAzB,CAAyB,CAAC,CAAC;qBAC3D;iBACF;gBACD,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aAClC;;;;;;;;;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACH,0CAAe,GAAf;QACE,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACH,uCAAY,GAAZ,UAAa,SAAmB;;QAC9B,IAAM,YAAY,GAAiB,EAAE,CAAC;;YAEtC,KAAuB,IAAA,cAAA,SAAA,SAAS,CAAA,oCAAA,2DAAE;gBAA7B,IAAM,QAAQ,sBAAA;gBACjB,YAAY,CAAC,IAAI,CAAC,IAAI,qBAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;aACjE;;;;;;;;;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;;;;;OAMG;IACH,0CAAe,GAAf,UAAgB,YAA2B;QACzC,OAAO,YAAY,CAAC,MAAM,CACxB,UAAC,UAAkB,EAAE,eAA4B,IAAK,OAAA,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,EAA7C,CAA6C,EACnG,CAAC,CACF,CAAC;IACJ,CAAC;IAKD,sBAAI,uCAAS;QAHb;;WAEG;aACH;;YACE,IAAI,IAAI,GAAG,CAAC,CAAC;;gBACb,KAAsB,IAAA,KAAA,SAAA,IAAI,CAAC,QAAQ,CAAA,gBAAA,4BAAE;oBAAhC,IAAM,OAAO,WAAA;oBAChB,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;iBAC9B;;;;;;;;;YACD,OAAO,IAAI,CAAC;QACd,CAAC;;;OAAA;IAKD,sBAAI,yCAAW;QAHf;;WAEG;aACH;;YACE,IAAI,IAAI,GAAG,CAAC,CAAC;;gBACb,KAAsB,IAAA,KAAA,SAAA,IAAI,CAAC,QAAQ,CAAA,gBAAA,4BAAE;oBAAhC,IAAM,OAAO,WAAA;oBAChB,IAAI,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;iBACrC;;;;;;;;;YACD,OAAO,IAAI,CAAC;QACd,CAAC;;;OAAA;IAMD,sBAAI,2CAAa;QAJjB;;;WAGG;aACH;YACE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC9B,CAAC;;;OAAA;IAED;;;OAGG;IACH,8CAAmB,GAAnB;QACE,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,UAAC,WAAW,IAAK,OAAA,CAAC,WAAW,CAAC,MAAM,EAAnB,CAAmB,CAAC,CAAC,GAAG,CAAC,UAAC,WAAW,IAAK,OAAA,WAAW,CAAC,GAAG,EAAf,CAAe,CAAC,CAAC;IAC9G,CAAC;IAED;;;;;;OAMG;IACH,gDAAqB,GAArB,UAAsB,OAAe;QACnC,IAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjD,IAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAM,UAAU,GAAG,eAAe,IAAI,YAAY,CAAC;QACnD,IAAM,WAAW,GAAG,CAAC,eAAe,IAAI,CAAC,YAAY,CAAC;QAEtD,IAAI,WAAW,EAAE;YACf,OAAO,SAAS,CAAC;SAClB;QACD,IAAI,UAAU,EAAE;YACd,OAAO,SAAS,CAAC;SAClB;QACD,OAAO,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IACtC,CAAC;IAED;;;;;OAKG;IACH,4CAAiB,GAAjB;QACE,IAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,cAAc,EAAE;YACvB,QAAQ,CAAC,IAAI,CACX,4HAA4H,CAC7H,CAAC;SACH;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACH,uBAAC;AAAD,CAAC,AAzQD,IAyQC;AAzQY,4CAAgB"} -------------------------------------------------------------------------------- /dist/libs/SmartEncodingMap.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"SmartEncodingMap.js","sourceRoot":"","sources":["../../src/libs/SmartEncodingMap.ts"],"names":[],"mappings":";;AAAA,IAAM,gBAAgB,GAElB;IACF,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,KAAK;IACf,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,GAAG,EAAE,SAAS;CACzB,CAAC;AAEF,kBAAe,gBAAgB,CAAC"} -------------------------------------------------------------------------------- /docs/styles/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 100%; 3 | font-family: "Helvetica", sans-serif; 4 | font-size: 11pt; 5 | } 6 | 7 | h1 { 8 | width: 100%; 9 | text-align: center; 10 | } 11 | 12 | #calculator-header { 13 | background-color: #233659; 14 | padding: 10px; 15 | } 16 | 17 | #calculator-header a { 18 | /* default blue/purples would be unreadable against blue background */ 19 | color: inherit; 20 | } 21 | 22 | #message-box { 23 | color: white; 24 | margin-bottom: 10px; 25 | } 26 | 27 | #message-box > textarea { 28 | resize: vertical; 29 | width: 100%; 30 | box-sizing: border-box; 31 | min-height: 5em; 32 | } 33 | 34 | #information-box { 35 | display: grid; 36 | grid-template-columns: repeat(5, auto); 37 | column-gap: 10px; 38 | grid-auto-flow: column; 39 | grid-template-rows: auto auto; 40 | justify-content: space-between; 41 | } 42 | #information-box > .label { 43 | padding-top: 5px; 44 | text-align: center; 45 | font-size: small; 46 | font-variant: all-petite-caps; 47 | background-color: #233659; 48 | color: white; 49 | } 50 | #information-box > .value { 51 | padding-top: 5px; 52 | font-size: medium; 53 | text-align: center; 54 | background-color: #233659; 55 | color: white; 56 | margin-bottom: 0; 57 | } 58 | 59 | #viewers { 60 | background-color: #F9F9F9; 61 | padding-top: 20px; 62 | } 63 | #viewers-inner { 64 | color: black; 65 | padding: 5px; 66 | margin-bottom: 10px; 67 | } 68 | 69 | .label { 70 | display: block; 71 | font-size: small; 72 | font-variant: all-petite-caps; 73 | padding-bottom: 5px; 74 | } 75 | .value { 76 | display: block; 77 | margin-bottom: 20px; 78 | } 79 | 80 | #message-viewer, #segments-viewer { 81 | line-height: 0.8; 82 | } 83 | 84 | .block { 85 | align-items: center; 86 | color: black; 87 | display: inline-flex; 88 | font-family: monospace; 89 | justify-content: center; 90 | text-align: center; 91 | vertical-align: middle; 92 | } 93 | .block.selected { 94 | color: white; 95 | } 96 | .block > span { 97 | cursor: default; 98 | } 99 | .block > span.invisible::before { 100 | content: "•"; 101 | } 102 | 103 | #message-viewer > .block { 104 | font-size: 12px; 105 | height: 2em; 106 | } 107 | #message-viewer > .block.error { 108 | background-color: red; 109 | } 110 | 111 | #segments-viewer > .block { 112 | border-bottom: 1px solid rgba(0, 0, 0, 0.2); 113 | border-right: 1px solid rgba(0, 0, 0, 0.2); 114 | font-size: 10px; 115 | height: 1em; 116 | padding: 4px; 117 | width: 6ch; 118 | } 119 | #segments-viewer > .block.twilio > img { 120 | display: inline; 121 | height: 1em; 122 | } 123 | 124 | /********************************/ 125 | /* GSM-7 Segments Color Palette */ 126 | /********************************/ 127 | [data-encoding="GSM-7"] .segment-type-0 { 128 | background-color: #CCE4FF; 129 | } 130 | [data-encoding="GSM-7"] .segment-type-0.selected { 131 | background-color: #0263E0; 132 | } 133 | 134 | [data-encoding="GSM-7"] .segment-type-1 { 135 | background-color: #D1FAE0; 136 | } 137 | [data-encoding="GSM-7"] .segment-type-1.selected { 138 | background-color: #14B053; 139 | } 140 | 141 | [data-encoding="GSM-7"] .segment-type-2 { 142 | background-color: #FDDCC4; 143 | } 144 | [data-encoding="GSM-7"] .segment-type-2.selected { 145 | background-color: #F47C22; 146 | } 147 | 148 | [data-encoding="GSM-7"] .segment-type-3 { 149 | background-color: #FFF1B3; 150 | } 151 | [data-encoding="GSM-7"] .segment-type-3.selected { 152 | background-color: #E8B407; 153 | } 154 | 155 | [data-encoding="GSM-7"] .segment-type-4 { 156 | background-color: #E7DCFA; 157 | } 158 | [data-encoding="GSM-7"] .segment-type-4.selected { 159 | background-color: #6D2ED1; 160 | } 161 | 162 | /********************************/ 163 | /* UCS-2 Segments Color Palette */ 164 | /********************************/ 165 | [data-encoding="UCS-2"] .segment-type-0 { 166 | background-color: #FFF1B3; 167 | } 168 | [data-encoding="UCS-2"] .segment-type-0.selected { 169 | background-color: #E8B407; 170 | } 171 | 172 | [data-encoding="UCS-2"] .segment-type-1 { 173 | background-color: #E7DCFA; 174 | } 175 | [data-encoding="UCS-2"] .segment-type-1.selected { 176 | background-color: #6D2ED1; 177 | } 178 | 179 | [data-encoding="UCS-2"] .segment-type-2 { 180 | background-color: #CCE4FF; 181 | } 182 | [data-encoding="UCS-2"] .segment-type-2.selected { 183 | background-color: #0263E0; 184 | } 185 | 186 | [data-encoding="UCS-2"] .segment-type-3 { 187 | background-color: #D1FAE0; 188 | } 189 | [data-encoding="UCS-2"] .segment-type-3.selected { 190 | background-color: #14B053; 191 | } 192 | 193 | [data-encoding="UCS-2"] .segment-type-4 { 194 | background-color: #FDDCC4; 195 | } 196 | [data-encoding="UCS-2"] .segment-type-4.selected { 197 | background-color: #F47C22; 198 | } 199 | 200 | .block.non-gsm { 201 | color: red; 202 | } 203 | 204 | .recently-changed { 205 | animation: pulseHighlight 1s ease-out infinite; 206 | } 207 | 208 | @keyframes pulseHighlight { 209 | 0% { 210 | color: yellow; 211 | } 212 | 100% { 213 | color: white; 214 | } 215 | } 216 | 217 | /********************************/ 218 | /* Legend */ 219 | /********************************/ 220 | .legend { 221 | font-size: 10px; 222 | background-color: #f9f9f9; 223 | padding: 0px 0px 5px 5px; 224 | } 225 | 226 | .legend-block { 227 | display: inline; 228 | border: 1px solid rgba(0, 0, 0, 0.2); 229 | font-size: 10px; 230 | height: 1em; 231 | padding: 4px; 232 | width: 6ch; 233 | vertical-align: middle; 234 | font-family: monospace; 235 | } 236 | 237 | #warnings-viewer { 238 | font-size: 10px; 239 | } 240 | -------------------------------------------------------------------------------- /dist/libs/SmartEncodingMap.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var SmartEncodingMap = { 4 | '\u00ab': '"', 5 | '\u00bb': '"', 6 | '\u201c': '"', 7 | '\u201d': '"', 8 | '\u02ba': '"', 9 | '\u02ee': '"', 10 | '\u201f': '"', 11 | '\u275d': '"', 12 | '\u275e': '"', 13 | '\u301d': '"', 14 | '\u301e': '"', 15 | '\uff02': '"', 16 | '\u2018': "'", 17 | '\u2019': "'", 18 | '\u02BB': "'", 19 | '\u02c8': "'", 20 | '\u02bc': "'", 21 | '\u02bd': "'", 22 | '\u02b9': "'", 23 | '\u201b': "'", 24 | '\uff07': "'", 25 | '\u00b4': "'", 26 | '\u02ca': "'", 27 | '\u0060': "'", 28 | '\u02cb': "'", 29 | '\u275b': "'", 30 | '\u275c': "'", 31 | '\u0313': "'", 32 | '\u0314': "'", 33 | '\ufe10': "'", 34 | '\ufe11': "'", 35 | '\u00F7': '/', 36 | '\u00bc': '1/4', 37 | '\u00bd': '1/2', 38 | '\u00be': '3/4', 39 | '\u29f8': '/', 40 | '\u0337': '/', 41 | '\u0338': '/', 42 | '\u2044': '/', 43 | '\u2215': '/', 44 | '\uff0f': '/', 45 | '\u29f9': '\\', 46 | '\u29f5': '\\', 47 | '\u20e5': '\\', 48 | '\ufe68': '\\', 49 | '\uff3c': '\\', 50 | '\u0332': '_', 51 | '\uff3f': '_', 52 | '\u20d2': '|', 53 | '\u20d3': '|', 54 | '\u2223': '|', 55 | '\uff5c': '|', 56 | '\u23b8': '|', 57 | '\u23b9': '|', 58 | '\u23d0': '|', 59 | '\u239c': '|', 60 | '\u239f': '|', 61 | '\u23bc': '-', 62 | '\u23bd': '-', 63 | '\u2015': '-', 64 | '\ufe63': '-', 65 | '\uff0d': '-', 66 | '\u2010': '-', 67 | '\u2043': '-', 68 | '\ufe6b': '@', 69 | '\uff20': '@', 70 | '\ufe69': '$', 71 | '\uff04': '$', 72 | '\u01c3': '!', 73 | '\ufe15': '!', 74 | '\ufe57': '!', 75 | '\uff01': '!', 76 | '\ufe5f': '#', 77 | '\uff03': '#', 78 | '\ufe6a': '%', 79 | '\uff05': '%', 80 | '\ufe60': '&', 81 | '\uff06': '&', 82 | '\u201a': ',', 83 | '\u0326': ',', 84 | '\ufe50': ',', 85 | '\ufe51': ',', 86 | '\uff0c': ',', 87 | '\uff64': ',', 88 | '\u2768': '(', 89 | '\u276a': '(', 90 | '\ufe59': '(', 91 | '\uff08': '(', 92 | '\u27ee': '(', 93 | '\u2985': '(', 94 | '\u2769': ')', 95 | '\u276b': ')', 96 | '\ufe5a': ')', 97 | '\uff09': ')', 98 | '\u27ef': ')', 99 | '\u2986': ')', 100 | '\u204e': '*', 101 | '\u2217': '*', 102 | '\u229B': '*', 103 | '\u2722': '*', 104 | '\u2723': '*', 105 | '\u2724': '*', 106 | '\u2725': '*', 107 | '\u2731': '*', 108 | '\u2732': '*', 109 | '\u2733': '*', 110 | '\u273a': '*', 111 | '\u273b': '*', 112 | '\u273c': '*', 113 | '\u273d': '*', 114 | '\u2743': '*', 115 | '\u2749': '*', 116 | '\u274a': '*', 117 | '\u274b': '*', 118 | '\u29c6': '*', 119 | '\ufe61': '*', 120 | '\uff0a': '*', 121 | '\u02d6': '+', 122 | '\ufe62': '+', 123 | '\uff0b': '+', 124 | '\u3002': '.', 125 | '\ufe52': '.', 126 | '\uff0e': '.', 127 | '\uff61': '.', 128 | '\uff10': '0', 129 | '\uff11': '1', 130 | '\uff12': '2', 131 | '\uff13': '3', 132 | '\uff14': '4', 133 | '\uff15': '5', 134 | '\uff16': '6', 135 | '\uff17': '7', 136 | '\uff18': '8', 137 | '\uff19': '9', 138 | '\u02d0': ':', 139 | '\u02f8': ':', 140 | '\u2982': ':', 141 | '\ua789': ':', 142 | '\ufe13': ':', 143 | '\uff1a': ':', 144 | '\u204f': ';', 145 | '\ufe14': ';', 146 | '\ufe54': ';', 147 | '\uff1b': ';', 148 | '\ufe64': '<', 149 | '\uff1c': '<', 150 | '\u0347': '=', 151 | '\ua78a': '=', 152 | '\ufe66': '=', 153 | '\uff1d': '=', 154 | '\ufe65': '>', 155 | '\uff1e': '>', 156 | '\ufe16': '?', 157 | '\ufe56': '?', 158 | '\uff1f': '?', 159 | '\uff21': 'A', 160 | '\u1d00': 'A', 161 | '\uff22': 'B', 162 | '\u0299': 'B', 163 | '\uff23': 'C', 164 | '\u1d04': 'C', 165 | '\uff24': 'D', 166 | '\u1d05': 'D', 167 | '\uff25': 'E', 168 | '\u1d07': 'E', 169 | '\uff26': 'F', 170 | '\ua730': 'F', 171 | '\uff27': 'G', 172 | '\u0262': 'G', 173 | '\uff28': 'H', 174 | '\u029c': 'H', 175 | '\uff29': 'I', 176 | '\u026a': 'I', 177 | '\uff2a': 'J', 178 | '\u1d0a': 'J', 179 | '\uff2b': 'K', 180 | '\u1d0b': 'K', 181 | '\uff2c': 'L', 182 | '\u029f': 'L', 183 | '\uff2d': 'M', 184 | '\u1d0d': 'M', 185 | '\uff2e': 'N', 186 | '\u0274': 'N', 187 | '\uff2f': 'O', 188 | '\u1d0f': 'O', 189 | '\uff30': 'P', 190 | '\u1d18': 'P', 191 | '\uff31': 'Q', 192 | '\uff32': 'R', 193 | '\u0280': 'R', 194 | '\uff33': 'S', 195 | '\ua731': 'S', 196 | '\uff34': 'T', 197 | '\u1d1b': 'T', 198 | '\uff35': 'U', 199 | '\u1d1c': 'U', 200 | '\uff36': 'V', 201 | '\u1d20': 'V', 202 | '\uff37': 'W', 203 | '\u1d21': 'W', 204 | '\uff38': 'X', 205 | '\uff39': 'Y', 206 | '\u028f': 'Y', 207 | '\uff3a': 'Z', 208 | '\u1d22': 'Z', 209 | '\u02c6': '^', 210 | '\u0302': '^', 211 | '\uff3e': '^', 212 | '\u1dcd': '^', 213 | '\u2774': '{', 214 | '\ufe5b': '{', 215 | '\uff5b': '{', 216 | '\u2775': '}', 217 | '\ufe5c': '}', 218 | '\uff5d': '}', 219 | '\uff3b': '[', 220 | '\uff3d': ']', 221 | '\u02dc': '~', 222 | '\u02f7': '~', 223 | '\u0303': '~', 224 | '\u0330': '~', 225 | '\u0334': '~', 226 | '\u223c': '~', 227 | '\uff5e': '~', 228 | '\u00a0': ' ', 229 | '\u2000': ' ', 230 | '\u2002': ' ', 231 | '\u2003': ' ', 232 | '\u2004': ' ', 233 | '\u2005': ' ', 234 | '\u2006': ' ', 235 | '\u2007': ' ', 236 | '\u2008': ' ', 237 | '\u2009': ' ', 238 | '\u200a': ' ', 239 | '\u202f': ' ', 240 | '\u205f': ' ', 241 | '\u3000': ' ', 242 | '\u008d': ' ', 243 | '\u009f': ' ', 244 | '\u0080': ' ', 245 | '\u0090': ' ', 246 | '\u009b': ' ', 247 | '\u0010': '', 248 | '\u0009': ' ', 249 | '\u0000': '', 250 | '\u0003': '', 251 | '\u0004': '', 252 | '\u0017': '', 253 | '\u0019': '', 254 | '\u0011': '', 255 | '\u0012': '', 256 | '\u0013': '', 257 | '\u0014': '', 258 | '\u2060': '', 259 | '\u2017': "'", 260 | '\u2014': '-', 261 | '\u2013': '-', 262 | '\u2039': '>', 263 | '\u203A': '<', 264 | '\u203C': '!!', 265 | '\u201E': '"', 266 | '\u2028': ' ', 267 | '\u2029': ' ', 268 | '\u2026': '...', 269 | '\u2001': ' ', 270 | '\u200b': '', 271 | '\u3001': ',', 272 | '\uFEFF': '', 273 | '\u2022': '-', // Bullet 274 | }; 275 | exports.default = SmartEncodingMap; 276 | //# sourceMappingURL=SmartEncodingMap.js.map -------------------------------------------------------------------------------- /docs/scripts/segments_viewer.js: -------------------------------------------------------------------------------- 1 | class SegmentsViewer { 2 | constructor(node, segmentTypesCount) { 3 | this.node = node; 4 | this.segmentTypesCount = segmentTypesCount; 5 | this.twilioLogo = this.createTwilioLogo(); 6 | this.blockMap = new Map(); 7 | this.selectedBlocks = []; 8 | } 9 | 10 | createTwilioLogo() { 11 | let img = document.createElement('img'); 12 | const twilio_logo = ''; 13 | img.setAttribute("src", "data:image/svg+xml;base64," + btoa(twilio_logo)); 14 | return img; 15 | } 16 | 17 | createTwilioReservedCodeUnitBlock(segmentType) { 18 | let block = document.createElement("div"); 19 | block.setAttribute("class", `block twilio ${segmentType}`); 20 | let twilioLogo = this.twilioLogo.cloneNode(); 21 | block.appendChild(twilioLogo); 22 | return block; 23 | } 24 | 25 | createCodeUnitBlock(codeUnit, segmentType, mapKey, isGSM7) { 26 | let block = document.createElement('div'); 27 | block.setAttribute('class', `block ${segmentType} ${isGSM7 ? '' : 'non-gsm'}`); 28 | 29 | block.setAttribute("data-key", mapKey); 30 | this.blockMap.get(mapKey).push(block); 31 | 32 | let span = document.createElement('span'); 33 | span.textContent = "0x" + codeUnit.toString(16).padStart(4, '0').toUpperCase(); 34 | 35 | block.appendChild(span); 36 | return block; 37 | } 38 | 39 | update(segmentedMessage) { 40 | this.blockMap.clear(); 41 | 42 | let newSegments = document.createElement("div"); 43 | newSegments.setAttribute("id", "segments-viewer"); 44 | 45 | for (let segmentIndex = 0; segmentIndex < segmentedMessage.segments.length; segmentIndex++) { 46 | const segmentType = `segment-type-${segmentIndex % this.segmentTypesCount}`; 47 | const segment = segmentedMessage.segments[segmentIndex]; 48 | 49 | for (let charIndex = 0; charIndex < segment.length; charIndex++) { 50 | const encodedChar = segment[charIndex]; 51 | const mapKey = `${segmentIndex}-${charIndex}`; 52 | this.blockMap.set(mapKey, []); 53 | 54 | if (encodedChar.isReservedChar) { 55 | newSegments.appendChild(this.createTwilioReservedCodeUnitBlock(segmentType)); 56 | } else { 57 | if (encodedChar.codeUnits) { 58 | for (const codeUnit of encodedChar.codeUnits) { 59 | newSegments.appendChild( 60 | this.createCodeUnitBlock(codeUnit, segmentType, mapKey, encodedChar.isGSM7) 61 | ); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | this.node.replaceWith(newSegments); 69 | this.node = newSegments; 70 | } 71 | 72 | select(mapKey) { 73 | this.clearSelection(); 74 | 75 | for (let block of this.blockMap.get(mapKey)) { 76 | block.classList.add("selected"); 77 | this.selectedBlocks.push(block); 78 | } 79 | } 80 | 81 | clearSelection() { 82 | for (let block of this.selectedBlocks) { 83 | block.classList.remove("selected"); 84 | } 85 | 86 | this.selectedBlocks.length = 0; 87 | } 88 | } 89 | 90 | 91 | class MessageViewer { 92 | constructor(node, segmentTypesCount) { 93 | this.node = node; 94 | this.segmentTypesCount = segmentTypesCount; 95 | this.blockMap = new Map(); 96 | this.selectedBlock = null; 97 | } 98 | 99 | createCharBlock(encodedChar, segmentType, mapKey) { 100 | let block = document.createElement('div'); 101 | block.setAttribute('class', `block ${segmentType}`); 102 | if (!encodedChar.codeUnits) { 103 | block.classList.add('error'); 104 | } 105 | 106 | block.setAttribute("data-key", mapKey); 107 | this.blockMap.set(mapKey, block); 108 | 109 | let span = document.createElement('span'); 110 | span.textContent = encodedChar.raw.replace(' ', '\u00A0'); 111 | block.appendChild(span); 112 | return block; 113 | } 114 | 115 | update(segmentedMessage) { 116 | this.blockMap.clear(); 117 | let newMessage = document.createElement("div"); 118 | newMessage.setAttribute("id", "message-viewer"); 119 | 120 | for (let segmentIndex = 0; segmentIndex < segmentedMessage.segments.length; segmentIndex++) { 121 | const segmentType = `segment-type-${segmentIndex % this.segmentTypesCount}`; 122 | const segment = segmentedMessage.segments[segmentIndex]; 123 | 124 | for (let charIndex = 0; charIndex < segment.length; charIndex++) { 125 | const encodedChar = segment[charIndex]; 126 | const mapKey = `${segmentIndex}-${charIndex}`; 127 | 128 | if (!(encodedChar.isReservedChar)) { 129 | newMessage.appendChild(this.createCharBlock(encodedChar, segmentType, mapKey)); 130 | } 131 | } 132 | } 133 | 134 | this.node.replaceWith(newMessage); 135 | this.node = newMessage; 136 | 137 | this.markInvisibleCharacters(); 138 | } 139 | 140 | markInvisibleCharacters() { 141 | for (let span of this.node.querySelectorAll("span")) { 142 | if (span.offsetWidth === 0) { 143 | span.classList.add("invisible"); 144 | } 145 | } 146 | } 147 | 148 | select(mapKey) { 149 | this.clearSelection(); 150 | 151 | this.selectedBlock = this.blockMap.get(mapKey); 152 | this.selectedBlock.classList.add("selected"); 153 | } 154 | 155 | clearSelection() { 156 | if (this.selectedBlock) { 157 | this.selectedBlock.classList.remove("selected"); 158 | } 159 | this.selectedBlock = null; 160 | } 161 | } 162 | 163 | class WarningsViewer { 164 | constructor(node) { 165 | this.node = node; 166 | } 167 | 168 | createWarningBlock(warning){ 169 | const warningParagraph = document.createElement("p"); 170 | warningParagraph.innerText = warning; 171 | return warningParagraph; 172 | } 173 | 174 | update(warnings){ 175 | this.node.innerHTML = ''; 176 | warnings.forEach(warning => { 177 | this.node.appendChild(this.createWarningBlock(warning)) 178 | }); 179 | } 180 | } -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Messaging Segment Calculator 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |

Messaging Segment Calculator

21 |
22 |
23 |
24 | 25 | 26 |
27 | 28 |
29 | Use Smart Encoding? 30 |
31 | 35 |
36 | Encoding 37 |
38 | 43 |
44 | 45 | Encoding Used 46 | 47 | 48 | Number of segments 49 | 50 | 51 | Number of characters 52 | 53 | 54 | Number of Unicode scalars 55 | 56 | 57 | Message size 58 | 59 | 60 | Total size sent 61 | 62 |
63 |
64 | 65 |
66 |
67 | 68 | Message Parsed 69 | 70 | 71 |
72 |
73 |
74 | 75 | Segments 76 | 77 | 78 |
79 |
80 |
81 | 82 | Warnings 83 | 84 | 85 |
86 |
87 |
88 |
89 |
90 | 91 |
92 |

Legend

93 |

 - SMS Header

94 |

0xFFFF - Character block

95 |

0xFFFF - Non GSM-7 character block

96 |
97 |
98 | 99 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /src/libs/SegmentedMessage.ts: -------------------------------------------------------------------------------- 1 | import GraphemeSplitter from 'grapheme-splitter'; 2 | 3 | import Segment from './Segment'; 4 | import EncodedChar from './EncodedChar'; 5 | import UnicodeToGsm from './UnicodeToGSM'; 6 | import SmartEncodingMap from './SmartEncodingMap'; 7 | 8 | type SmsEncoding = 'GSM-7' | 'UCS-2'; 9 | 10 | type EncodedChars = Array; 11 | 12 | const validEncodingValues = ['GSM-7', 'UCS-2', 'auto']; 13 | 14 | declare type LineBreakStyle = 'LF' | 'CRLF' | 'LF+CRLF' | undefined; 15 | 16 | /** 17 | * Class representing a segmented SMS 18 | */ 19 | export class SegmentedMessage { 20 | encoding: SmsEncoding | 'auto'; 21 | 22 | segments: Segment[]; 23 | 24 | graphemes: string[]; 25 | 26 | encodingName: SmsEncoding; 27 | 28 | numberOfUnicodeScalars: number; 29 | 30 | numberOfCharacters: number; 31 | 32 | encodedChars: EncodedChars; 33 | 34 | lineBreakStyle: LineBreakStyle; 35 | 36 | warnings: string[]; 37 | 38 | /** 39 | * 40 | * Create a new segmented message from a string 41 | * 42 | * @param {string} message Body of the message 43 | * @param {boolean} [encoding] Optional: encoding. It can be 'GSM-7', 'UCS-2', 'auto'. Default value: 'auto' 44 | * @param {boolean} smartEncoding Optional: whether or not Twilio's [Smart Encoding](https://www.twilio.com/docs/messaging/services#smart-encoding) is emulated. Default value: false 45 | * @property {number} numberOfUnicodeScalars Number of Unicode Scalars (i.e. unicode pairs) the message is made of 46 | * 47 | */ 48 | constructor(message: string, encoding: SmsEncoding | 'auto' = 'auto', smartEncoding: boolean = false) { 49 | const splitter = new GraphemeSplitter(); 50 | 51 | if (!validEncodingValues.includes(encoding)) { 52 | throw new Error( 53 | `Encoding ${encoding} not supported. Valid values for encoding are ${validEncodingValues.join(', ')}`, 54 | ); 55 | } 56 | 57 | if (smartEncoding) { 58 | message = [...message] 59 | .map((char) => (SmartEncodingMap[char] === undefined ? char : SmartEncodingMap[char])) 60 | .join(''); 61 | } 62 | 63 | /** 64 | * @property {string[]} graphemes Graphemes (array of strings) the message have been split into 65 | */ 66 | this.graphemes = splitter.splitGraphemes(message).reduce((accumulator: string[], grapheme: string) => { 67 | const result = grapheme === '\r\n' ? grapheme.split('') : [grapheme]; 68 | return accumulator.concat(result); 69 | }, []); 70 | /** 71 | * @property {number} numberOfUnicodeScalars Number of Unicode Scalars (i.e. unicode pairs) the message is made of 72 | * Some characters (e.g. extended emoji) can be made of more than one unicode pair 73 | */ 74 | this.numberOfUnicodeScalars = [...message].length; 75 | /** 76 | * @property {string} encoding Encoding set in the constructor for the message. Allowed values: 'GSM-7', 'UCS-2', 'auto'. 77 | * @private 78 | */ 79 | this.encoding = encoding; 80 | 81 | if (this.encoding === 'auto') { 82 | /** 83 | * @property {string} encodingName Calculated encoding name. It can be: "GSM-7" or "UCS-2" 84 | */ 85 | this.encodingName = this._hasAnyUCSCharacters(this.graphemes) ? 'UCS-2' : 'GSM-7'; 86 | } else { 87 | if (encoding === 'GSM-7' && this._hasAnyUCSCharacters(this.graphemes)) { 88 | throw new Error('The string provided is incompatible with GSM-7 encoding'); 89 | } 90 | this.encodingName = this.encoding; 91 | } 92 | 93 | /** 94 | * @property {string[]} encodedChars Array of encoded characters composing the message 95 | */ 96 | this.encodedChars = this._encodeChars(this.graphemes); 97 | 98 | /** 99 | * @property {number} numberOfCharacters Number of characters in the message. Each character count as 1 except for 100 | * the characters in the GSM extension character set. 101 | */ 102 | this.numberOfCharacters = 103 | this.encodingName === 'UCS-2' ? this.graphemes.length : this._countCodeUnits(this.encodedChars); 104 | 105 | /** 106 | * @property {object[]} segments Array of segment(s) the message have been segmented into 107 | */ 108 | this.segments = this._buildSegments(this.encodedChars); 109 | 110 | /** 111 | * @property {LineBreakStyle} lineBreakStyle message line break style 112 | */ 113 | this.lineBreakStyle = this._detectLineBreakStyle(message); 114 | 115 | /** 116 | * @property {string[]} warnings message line break style 117 | */ 118 | this.warnings = this._checkForWarnings(); 119 | } 120 | 121 | /** 122 | * Internal method to check if the message has any non-GSM7 characters 123 | * 124 | * @param {string[]} graphemes Message body 125 | * @returns {boolean} True if there are non-GSM-7 characters 126 | * @private 127 | */ 128 | _hasAnyUCSCharacters(graphemes: string[]): boolean { 129 | let result = false; 130 | for (const grapheme of graphemes) { 131 | if (grapheme.length >= 2 || (grapheme.length === 1 && !UnicodeToGsm[grapheme.charCodeAt(0)])) { 132 | result = true; 133 | break; 134 | } 135 | } 136 | return result; 137 | } 138 | 139 | /** 140 | * Internal method used to build message's segment(s) 141 | * 142 | * @param {object[]} encodedChars Array of EncodedChar 143 | * @returns {object[]} Array of Segment 144 | * @private 145 | */ 146 | 147 | _buildSegments(encodedChars: EncodedChars): Segment[] { 148 | const segments: Segment[] = []; 149 | segments.push(new Segment()); 150 | let currentSegment = segments[0]; 151 | 152 | for (const encodedChar of encodedChars) { 153 | if (currentSegment.freeSizeInBits() < encodedChar.sizeInBits()) { 154 | segments.push(new Segment(true)); 155 | currentSegment = segments[segments.length - 1]; 156 | const previousSegment = segments[segments.length - 2]; 157 | 158 | if (!previousSegment.hasUserDataHeader) { 159 | const removedChars = previousSegment.addHeader(); 160 | // eslint-disable-next-line no-loop-func 161 | removedChars.forEach((char) => currentSegment.push(char)); 162 | } 163 | } 164 | currentSegment.push(encodedChar); 165 | } 166 | 167 | return segments; 168 | } 169 | 170 | /** 171 | * Return the encoding of the message segment 172 | * 173 | * @returns {string} Encoding for the message segment(s) 174 | */ 175 | getEncodingName(): string { 176 | return this.encodingName; 177 | } 178 | 179 | /** 180 | * Internal method to create an array of EncodedChar from a string 181 | * 182 | * @param {string[]} graphemes Array of graphemes representing the message 183 | * @returns {object[]} Array of EncodedChar 184 | * @private 185 | */ 186 | _encodeChars(graphemes: string[]): EncodedChars { 187 | const encodedChars: EncodedChars = []; 188 | 189 | for (const grapheme of graphemes) { 190 | encodedChars.push(new EncodedChar(grapheme, this.encodingName)); 191 | } 192 | return encodedChars; 193 | } 194 | 195 | /** 196 | * Internal method to count the total number of code units of the message 197 | * 198 | * @param {EncodedChar[]} encodedChars Encoded message body 199 | * @returns {number} The total number of code units 200 | * @private 201 | */ 202 | _countCodeUnits(encodedChars: EncodedChar[]): number { 203 | return encodedChars.reduce( 204 | (acumulator: number, nextEncodedChar: EncodedChar) => acumulator + nextEncodedChar.codeUnits.length, 205 | 0, 206 | ); 207 | } 208 | 209 | /** 210 | * @returns {number} Total size of the message in bits (including User Data Header if present) 211 | */ 212 | get totalSize(): number { 213 | let size = 0; 214 | for (const segment of this.segments) { 215 | size += segment.sizeInBits(); 216 | } 217 | return size; 218 | } 219 | 220 | /** 221 | * @returns {number} Total size of the message in bits (excluding User Data Header if present) 222 | */ 223 | get messageSize(): number { 224 | let size = 0; 225 | for (const segment of this.segments) { 226 | size += segment.messageSizeInBits(); 227 | } 228 | return size; 229 | } 230 | 231 | /** 232 | * 233 | * @returns {number} Number of segments 234 | */ 235 | get segmentsCount(): number { 236 | return this.segments.length; 237 | } 238 | 239 | /** 240 | * 241 | * @returns {string[]} Array of characters representing the non GSM-7 characters in the message body 242 | */ 243 | getNonGsmCharacters(): string[] { 244 | return this.encodedChars.filter((encodedChar) => !encodedChar.isGSM7).map((encodedChar) => encodedChar.raw); 245 | } 246 | 247 | /** 248 | * Internal method to check the line break styled used in the passed message 249 | * 250 | * @param {string} message Message body 251 | * @returns {LineBreakStyle} The libre break style name LF or CRLF 252 | * @private 253 | */ 254 | _detectLineBreakStyle(message: string): LineBreakStyle { 255 | const hasWindowsStyle = message.includes('\r\n'); 256 | const HasUnixStyle = message.includes('\n'); 257 | const mixedStyle = hasWindowsStyle && HasUnixStyle; 258 | const noBreakLine = !hasWindowsStyle && !HasUnixStyle; 259 | 260 | if (noBreakLine) { 261 | return undefined; 262 | } 263 | if (mixedStyle) { 264 | return 'LF+CRLF'; 265 | } 266 | return HasUnixStyle ? 'LF' : 'CRLF'; 267 | } 268 | 269 | /** 270 | * Internal method to check the line break styled used in the passed message 271 | * 272 | * @returns {string[]} The libre break style name LF or CRLF 273 | * @private 274 | */ 275 | _checkForWarnings(): string[] { 276 | const warnings = []; 277 | if (this.lineBreakStyle) { 278 | warnings.push( 279 | 'The message has line breaks, the web page utility only supports LF style. If you insert a CRLF it will be converted to LF.', 280 | ); 281 | } 282 | return warnings; 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /tests/index.test.js: -------------------------------------------------------------------------------- 1 | const expectExport = require('expect'); 2 | const { SegmentedMessage } = require('../dist'); 3 | const SmartEncodingMap = require('../dist/libs/SmartEncodingMap').default; 4 | 5 | const GSM7EscapeChars = ['|', '^', '€', '{', '}', '[', ']', '~', '\\']; 6 | 7 | const TestData = [ 8 | { 9 | testDescription: 'GSM-7 in one segment', 10 | body: '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890', 11 | encoding: 'GSM-7', 12 | segments: 1, 13 | messageSize: 1120, 14 | totalSize: 1120, 15 | characters: 160, 16 | unicodeScalars: 160, 17 | }, 18 | { 19 | testDescription: 'GSM-7 in two segments', 20 | body: '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901', 21 | encoding: 'GSM-7', 22 | segments: 2, 23 | messageSize: 1127, 24 | totalSize: 1223, 25 | characters: 161, 26 | unicodeScalars: 161, 27 | }, 28 | { 29 | testDescription: 'GSM-7 in three segments', 30 | body: '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567', 31 | encoding: 'GSM-7', 32 | segments: 3, 33 | messageSize: 2149, 34 | totalSize: 2293, 35 | characters: 307, 36 | unicodeScalars: 307, 37 | }, 38 | { 39 | testDescription: 'UCS-2 message in one segment', 40 | body: '😜23456789012345678901234567890123456789012345678901234567890123456789', 41 | encoding: 'UCS-2', 42 | segments: 1, 43 | messageSize: 1120, 44 | totalSize: 1120, 45 | characters: 69, 46 | unicodeScalars: 69, 47 | }, 48 | { 49 | testDescription: 'UCS-2 message in two segments', 50 | body: '😜234567890123456789012345678901234567890123456789012345678901234567890', 51 | encoding: 'UCS-2', 52 | segments: 2, 53 | messageSize: 1136, 54 | totalSize: 1232, 55 | characters: 70, 56 | unicodeScalars: 70, 57 | }, 58 | { 59 | testDescription: 'UCS-2 message in three segments', 60 | body: '😜2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234', 61 | encoding: 'UCS-2', 62 | segments: 3, 63 | messageSize: 2160, 64 | totalSize: 2304, 65 | characters: 134, 66 | unicodeScalars: 134, 67 | }, 68 | { 69 | testDescription: 'UCS-2 with two bytes extended characters in one segments boundary', 70 | body: '🇮🇹234567890123456789012345678901234567890123456789012345678901234567', 71 | encoding: 'UCS-2', 72 | segments: 1, 73 | messageSize: 1120, 74 | totalSize: 1120, 75 | characters: 67, 76 | unicodeScalars: 68, 77 | }, 78 | { 79 | testDescription: 'UCS-2 with extended characters in two segments boundary', 80 | body: '🇮🇹2345678901234567890123456789012345678901234567890123456789012345678', 81 | encoding: 'UCS-2', 82 | segments: 2, 83 | messageSize: 1136, 84 | totalSize: 1232, 85 | characters: 68, 86 | unicodeScalars: 69, 87 | }, 88 | { 89 | testDescription: 'UCS-2 with four bytes extended characters in one segments boundary', 90 | body: '🏳️‍🌈2345678901234567890123456789012345678901234567890123456789012345', 91 | encoding: 'UCS-2', 92 | segments: 1, 93 | messageSize: 1120, 94 | totalSize: 1120, 95 | characters: 65, 96 | unicodeScalars: 68, 97 | }, 98 | { 99 | testDescription: 'UCS-2 with four bytes extended characters in two segments boundary', 100 | body: '🏳️‍🌈23456789012345678901234567890123456789012345678901234567890123456', 101 | encoding: 'UCS-2', 102 | segments: 2, 103 | messageSize: 1136, 104 | totalSize: 1232, 105 | characters: 66, 106 | unicodeScalars: 69, 107 | }, 108 | ]; 109 | 110 | describe('Smart Encoding', () => { 111 | test.each(Object.entries(SmartEncodingMap))('With Smart Encoding enabled - maps %s to %s', (key, value) => { 112 | const segmentedMessage = new SegmentedMessage(key, 'auto', true); 113 | expect(segmentedMessage.graphemes.join('')).toBe(value); 114 | }); 115 | test.each(Object.entries(SmartEncodingMap))('With Smart Encoding disabled - does not modify %s', (key) => { 116 | const segmentedMessage = new SegmentedMessage(key, 'auto', false); 117 | expect(segmentedMessage.graphemes.join('')).toBe(key); 118 | }); 119 | test('Replace all Smart Encoding chars at once', () => { 120 | const testString = Object.keys(SmartEncodingMap).join(''); 121 | const expected = Object.values(SmartEncodingMap).join(''); 122 | const segmentedMessage = new SegmentedMessage(testString, 'auto', true); 123 | expect(segmentedMessage.graphemes.join('')).toBe(expected); 124 | }); 125 | }); 126 | 127 | describe('Basic tests', () => { 128 | TestData.forEach((testMessage) => { 129 | test(testMessage.testDescription, () => { 130 | const segmentedMessage = new SegmentedMessage(testMessage.body); 131 | expect(segmentedMessage.encodingName).toBe(testMessage.encoding); 132 | expect(segmentedMessage.segments.length).toBe(testMessage.segments); 133 | expect(segmentedMessage.segmentsCount).toBe(testMessage.segments); 134 | expect(segmentedMessage.messageSize).toBe(testMessage.messageSize); 135 | expect(segmentedMessage.totalSize).toBe(testMessage.totalSize); 136 | expect(segmentedMessage.numberOfUnicodeScalars).toBe(testMessage.unicodeScalars); 137 | expect(segmentedMessage.numberOfCharacters).toBe(testMessage.characters); 138 | }); 139 | }); 140 | }); 141 | 142 | describe('GSM-7 Escape Characters', () => { 143 | GSM7EscapeChars.forEach((escapeChar) => { 144 | test(`One segment with escape character ${escapeChar}`, () => { 145 | const segmentedMessage = new SegmentedMessage( 146 | `${escapeChar}12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678`, 147 | ); 148 | expect(segmentedMessage.encodingName).toBe('GSM-7'); 149 | expect(segmentedMessage.segments.length).toBe(1); 150 | expect(segmentedMessage.segmentsCount).toBe(1); 151 | expect(segmentedMessage.messageSize).toBe(1120); 152 | expect(segmentedMessage.totalSize).toBe(1120); 153 | }); 154 | test(`Two segments with escape character ${escapeChar}`, () => { 155 | const segmentedMessage = new SegmentedMessage( 156 | `${escapeChar}123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789`, 157 | ); 158 | expect(segmentedMessage.encodingName).toBe('GSM-7'); 159 | expect(segmentedMessage.segments.length).toBe(2); 160 | expect(segmentedMessage.segmentsCount).toBe(2); 161 | expect(segmentedMessage.messageSize).toBe(1127); 162 | expect(segmentedMessage.totalSize).toBe(1223); 163 | }); 164 | }); 165 | }); 166 | 167 | describe('One grapheme UCS-2 characters', () => { 168 | const testCharacters = ['Á', 'Ú', 'ú', 'ç', 'í', 'Í', 'ó', 'Ó']; 169 | testCharacters.forEach((character) => { 170 | test(`One segment, 70 characters of "${character}"`, () => { 171 | const testMessage = Array(70).fill(character).join(''); 172 | const segmentedMessage = new SegmentedMessage(testMessage); 173 | expect(segmentedMessage.segmentsCount).toBe(1); 174 | segmentedMessage.encodedChars.forEach((encodedChar) => { 175 | expect(encodedChar.isGSM7).toBe(false); 176 | }); 177 | }); 178 | }); 179 | 180 | testCharacters.forEach((character) => { 181 | test(`Two segments, 71 characters of "${character}"`, () => { 182 | const testMessage = Array(71).fill(character).join(''); 183 | const segmentedMessage = new SegmentedMessage(testMessage); 184 | expect(segmentedMessage.segmentsCount).toBe(2); 185 | segmentedMessage.encodedChars.forEach((encodedChar) => { 186 | expect(encodedChar.isGSM7).toBe(false); 187 | }); 188 | }); 189 | }); 190 | }); 191 | 192 | describe('Special tests', () => { 193 | test('UCS2 message with special GSM characters in one segment', () => { 194 | // Issue #18: wrong segmnent calculation using GSM special characters 195 | const testMessage = '😀]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'; 196 | const segmentedMessage = new SegmentedMessage(testMessage); 197 | expect(segmentedMessage.segmentsCount).toBe(1); 198 | }); 199 | 200 | test('UCS2 message with special GSM characters in two segment', () => { 201 | const testMessage = '😀]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'; 202 | const segmentedMessage = new SegmentedMessage(testMessage); 203 | expect(segmentedMessage.segmentsCount).toBe(2); 204 | }); 205 | }); 206 | 207 | describe('Line break styles tests', () => { 208 | test('Message with CRLF line break style and auto line break style detection', () => { 209 | const testMessage = '\rabcde\r\n123'; 210 | const segmentedMessage = new SegmentedMessage(testMessage); 211 | expect(segmentedMessage.numberOfCharacters).toBe(11); 212 | }); 213 | 214 | test('Message with LF line break style and auto line break style detection', () => { 215 | const testMessage = '\nabcde\n\n123\n'; 216 | const segmentedMessage = new SegmentedMessage(testMessage); 217 | expect(segmentedMessage.numberOfCharacters).toBe(12); 218 | }); 219 | 220 | test('Triple accents characters - Unicode test', () => { 221 | const testMessage = 'é́́'; 222 | const segmentedMessage = new SegmentedMessage(testMessage); 223 | expect(segmentedMessage.numberOfCharacters).toBe(1); 224 | expect(segmentedMessage.numberOfUnicodeScalars).toBe(4); 225 | }); 226 | 227 | // Test for https://github.com/TwilioDevEd/message-segment-calculator/issues/17 228 | test('Triple accents characters - One Segment test', () => { 229 | const testMessage = 'é́́aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 230 | const segmentedMessage = new SegmentedMessage(testMessage); 231 | expect(segmentedMessage.segmentsCount).toBe(1); 232 | }); 233 | 234 | test('Triple accents characters - Two Segments test', () => { 235 | const testMessage = 'é́́aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 236 | const segmentedMessage = new SegmentedMessage(testMessage); 237 | expect(segmentedMessage.segmentsCount).toBe(2); 238 | }); 239 | }); 240 | -------------------------------------------------------------------------------- /src/libs/SmartEncodingMap.ts: -------------------------------------------------------------------------------- 1 | const SmartEncodingMap: { 2 | [key: string]: string; 3 | } = { 4 | '\u00ab': '"', // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 5 | '\u00bb': '"', // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 6 | '\u201c': '"', // LEFT DOUBLE QUOTATION MARK 7 | '\u201d': '"', // RIGHT DOUBLE QUOTATION MARK 8 | '\u02ba': '"', // MODIFIER LETTER DOUBLE PRIME 9 | '\u02ee': '"', // MODIFIER LETTER DOUBLE APOSTROPHE 10 | '\u201f': '"', // DOUBLE HIGH-REVERSED-9 QUOTATION MARK 11 | '\u201E': '"', // DOUBLE LOW-9 QUOTATION MARK 12 | '\u275d': '"', // HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT 13 | '\u275e': '"', // HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT 14 | '\u301d': '"', // REVERSED DOUBLE PRIME QUOTATION MARK 15 | '\u301e': '"', // DOUBLE PRIME QUOTATION MARK 16 | '\uff02': '"', // FULLWIDTH QUOTATION MARK 17 | '\u2018': "'", // LEFT SINGLE QUOTATION MARK 18 | '\u2019': "'", // RIGHT SINGLE QUOTATION MARK 19 | '\u02BB': "'", // MODIFIER LETTER TURNED COMMA 20 | '\u02c8': "'", // MODIFIER LETTER VERTICAL LINE 21 | '\u02bc': "'", // MODIFIER LETTER APOSTROPHE 22 | '\u02bd': "'", // MODIFIER LETTER REVERSED COMMA 23 | '\u02b9': "'", // MODIFIER LETTER PRIME 24 | '\u201b': "'", // SINGLE HIGH-REVERSED-9 QUOTATION MARK 25 | '\uff07': "'", // FULLWIDTH APOSTROPHE 26 | '\u00b4': "'", // ACUTE ACCENT 27 | '\u02ca': "'", // MODIFIER LETTER ACUTE ACCENT 28 | '\u0060': "'", // GRAVE ACCENT 29 | '\u02cb': "'", // MODIFIER LETTER GRAVE ACCENT 30 | '\u275b': "'", // HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT 31 | '\u275c': "'", // HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT 32 | '\u0313': "'", // COMBINING COMMA ABOVE 33 | '\u0314': "'", // COMBINING REVERSED COMMA ABOVE 34 | '\ufe10': "'", // PRESENTATION FORM FOR VERTICAL COMMA 35 | '\ufe11': "'", // PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA 36 | '\u00F7': '/', // DIVISION SIGN 37 | '\u00bc': '1/4', // VULGAR FRACTION ONE QUARTER 38 | '\u00bd': '1/2', // VULGAR FRACTION ONE HALF 39 | '\u00be': '3/4', // VULGAR FRACTION THREE QUARTERS 40 | '\u29f8': '/', // BIG SOLIDUS 41 | '\u0337': '/', // COMBINING SHORT SOLIDUS OVERLAY 42 | '\u0338': '/', // COMBINING LONG SOLIDUS OVERLAY 43 | '\u2044': '/', // FRACTION SLASH 44 | '\u2215': '/', // DIVISION SLASH 45 | '\uff0f': '/', // FULLWIDTH SOLIDUS 46 | '\u29f9': '\\', // BIG REVERSE SOLIDUS 47 | '\u29f5': '\\', // REVERSE SOLIDUS OPERATOR 48 | '\u20e5': '\\', // COMBINING REVERSE SOLIDUS OVERLAY 49 | '\ufe68': '\\', // SMALL REVERSE SOLIDUS 50 | '\uff3c': '\\', // FULLWIDTH REVERSE SOLIDUS 51 | '\u0332': '_', // COMBINING LOW LINE 52 | '\uff3f': '_', // FULLWIDTH LOW LINE 53 | '\u20d2': '|', // COMBINING LONG VERTICAL LINE OVERLAY 54 | '\u20d3': '|', // COMBINING SHORT VERTICAL LINE OVERLAY 55 | '\u2223': '|', // DIVIDES 56 | '\uff5c': '|', // FULLWIDTH VERTICAL LINE 57 | '\u23b8': '|', // LEFT VERTICAL BOX LINE 58 | '\u23b9': '|', // RIGHT VERTICAL BOX LINE 59 | '\u23d0': '|', // VERTICAL LINE EXTENSION 60 | '\u239c': '|', // LEFT PARENTHESIS EXTENSION 61 | '\u239f': '|', // RIGHT PARENTHESIS EXTENSION 62 | '\u23bc': '-', // HORIZONTAL SCAN LINE-7 63 | '\u23bd': '-', // HORIZONTAL SCAN LINE-9 64 | '\u2015': '-', // HORIZONTAL BAR 65 | '\ufe63': '-', // SMALL HYPHEN-MINUS 66 | '\uff0d': '-', // FULLWIDTH HYPHEN-MINUS 67 | '\u2010': '-', // HYPHEN 68 | '\u2043': '-', // HYPHEN BULLET 69 | '\ufe6b': '@', // SMALL COMMERCIAL AT 70 | '\uff20': '@', // FULLWIDTH COMMERCIAL AT 71 | '\ufe69': '$', // SMALL DOLLAR SIGN 72 | '\uff04': '$', // FULLWIDTH DOLLAR SIGN 73 | '\u01c3': '!', // LATIN LETTER RETROFLEX CLICK 74 | '\ufe15': '!', // PRESENTATION FORM FOR VERTICAL EXLAMATION MARK 75 | '\ufe57': '!', // SMALL EXCLAMATION MARK 76 | '\uff01': '!', // FULLWIDTH EXCLAMATION MARK 77 | '\ufe5f': '#', // SMALL NUMBER SIGN 78 | '\uff03': '#', // FULLWIDTH NUMBER SIGN 79 | '\ufe6a': '%', // SMALL PERCENT SIGN 80 | '\uff05': '%', // FULLWIDTH PERCENT SIGN 81 | '\ufe60': '&', // SMALL AMPERSAND 82 | '\uff06': '&', // FULLWIDTH AMPERSAND 83 | '\u201a': ',', // SINGLE LOW-9 QUOTATION MARK 84 | '\u0326': ',', // COMBINING COMMA BELOW 85 | '\ufe50': ',', // SMALL COMMA 86 | '\ufe51': ',', // SMALL IDEOGRAPHIC COMMA 87 | '\uff0c': ',', // FULLWIDTH COMMA 88 | '\uff64': ',', // HALFWIDTH IDEOGRAPHIC COMMA 89 | '\u2768': '(', // MEDIUM LEFT PARENTHESIS ORNAMENT 90 | '\u276a': '(', // MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT 91 | '\ufe59': '(', // SMALL LEFT PARENTHESIS 92 | '\uff08': '(', // FULLWIDTH LEFT PARENTHESIS 93 | '\u27ee': '(', // MATHEMATICAL LEFT FLATTENED PARENTHESIS 94 | '\u2985': '(', // LEFT WHITE PARENTHESIS 95 | '\u2769': ')', // MEDIUM RIGHT PARENTHESIS ORNAMENT 96 | '\u276b': ')', // MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT 97 | '\ufe5a': ')', // SMALL RIGHT PARENTHESIS 98 | '\uff09': ')', // FULLWIDTH RIGHT PARENTHESIS 99 | '\u27ef': ')', // MATHEMATICAL RIGHT FLATTENED PARENTHESIS 100 | '\u2986': ')', // RIGHT WHITE PARENTHESIS 101 | '\u204e': '*', // LOW ASTERISK 102 | '\u2217': '*', // ASTERISK OPERATOR 103 | '\u229B': '*', // CIRCLED ASTERISK OPERATOR 104 | '\u2722': '*', // FOUR TEARDROP-SPOKED ASTERISK 105 | '\u2723': '*', // FOUR BALLOON-SPOKED ASTERISK 106 | '\u2724': '*', // HEAVY FOUR BALLOON-SPOKED ASTERISK 107 | '\u2725': '*', // FOUR CLUB-SPOKED ASTERISK 108 | '\u2731': '*', // HEAVY ASTERISK 109 | '\u2732': '*', // OPEN CENTRE ASTERISK 110 | '\u2733': '*', // EIGHT SPOKED ASTERISK 111 | '\u273a': '*', // SIXTEEN POINTED ASTERISK 112 | '\u273b': '*', // TEARDROP-SPOKED ASTERISK 113 | '\u273c': '*', // OPEN CENTRE TEARDROP-SPOKED ASTERISK 114 | '\u273d': '*', // HEAVY TEARDROP-SPOKED ASTERISK 115 | '\u2743': '*', // HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK 116 | '\u2749': '*', // BALLOON-SPOKED ASTERISK 117 | '\u274a': '*', // EIGHT TEARDROP-SPOKED PROPELLER ASTERISK 118 | '\u274b': '*', // HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK 119 | '\u29c6': '*', // SQUARED ASTERISK 120 | '\ufe61': '*', // SMALL ASTERISK 121 | '\uff0a': '*', // FULLWIDTH ASTERISK 122 | '\u02d6': '+', // MODIFIER LETTER PLUS SIGN 123 | '\ufe62': '+', // SMALL PLUS SIGN 124 | '\uff0b': '+', // FULLWIDTH PLUS SIGN 125 | '\u3002': '.', // IDEOGRAPHIC FULL STOP 126 | '\ufe52': '.', // SMALL FULL STOP 127 | '\uff0e': '.', // FULLWIDTH FULL STOP 128 | '\uff61': '.', // HALFWIDTH IDEOGRAPHIC FULL STOP 129 | '\uff10': '0', // FULLWIDTH DIGIT ZERO 130 | '\uff11': '1', // FULLWIDTH DIGIT ONE 131 | '\uff12': '2', // FULLWIDTH DIGIT TWO 132 | '\uff13': '3', // FULLWIDTH DIGIT THREE 133 | '\uff14': '4', // FULLWIDTH DIGIT FOUR 134 | '\uff15': '5', // FULLWIDTH DIGIT FIVE 135 | '\uff16': '6', // FULLWIDTH DIGIT SIX 136 | '\uff17': '7', // FULLWIDTH DIGIT SEVEN 137 | '\uff18': '8', // FULLWIDTH DIGIT EIGHT 138 | '\uff19': '9', // FULLWIDTH DIGIT NINE 139 | '\u02d0': ':', // MODIFIER LETTER TRIANGULAR COLON 140 | '\u02f8': ':', // MODIFIER LETTER RAISED COLON 141 | '\u2982': ':', // Z NOTATION TYPE COLON 142 | '\ua789': ':', // MODIFIER LETTER COLON 143 | '\ufe13': ':', // PRESENTATION FORM FOR VERTICAL COLON 144 | '\uff1a': ':', // FULLWIDTH COLON 145 | '\u204f': ';', // REVERSED SEMICOLON 146 | '\ufe14': ';', // PRESENTATION FORM FOR VERTICAL SEMICOLON 147 | '\ufe54': ';', // SMALL SEMICOLON 148 | '\uff1b': ';', // FULLWIDTH SEMICOLON 149 | '\ufe64': '<', // SMALL LESS-THAN SIGN 150 | '\uff1c': '<', // FULLWIDTH LESS-THAN SIGN 151 | '\u0347': '=', // COMBINING EQUALS SIGN BELOW 152 | '\ua78a': '=', // MODIFIER LETTER SHORT EQUALS SIGN 153 | '\ufe66': '=', // SMALL EQUALS SIGN 154 | '\uff1d': '=', // FULLWIDTH EQUALS SIGN 155 | '\ufe65': '>', // SMALL GREATER-THAN SIGN 156 | '\uff1e': '>', // FULLWIDTH GREATER-THAN SIGN 157 | '\ufe16': '?', // PRESENTATION FORM FOR VERTICAL QUESTION MARK 158 | '\ufe56': '?', // SMALL QUESTION MARK 159 | '\uff1f': '?', // FULLWIDTH QUESTION MARK 160 | '\uff21': 'A', // FULLWIDTH LATIN CAPITAL LETTER A 161 | '\u1d00': 'A', // LATIN LETTER SMALL CAPITAL A 162 | '\uff22': 'B', // FULLWIDTH LATIN CAPITAL LETTER B 163 | '\u0299': 'B', // LATIN LETTER SMALL CAPITAL B 164 | '\uff23': 'C', // FULLWIDTH LATIN CAPITAL LETTER C 165 | '\u1d04': 'C', // LATIN LETTER SMALL CAPITAL C 166 | '\uff24': 'D', // FULLWIDTH LATIN CAPITAL LETTER D 167 | '\u1d05': 'D', // LATIN LETTER SMALL CAPITAL D 168 | '\uff25': 'E', // FULLWIDTH LATIN CAPITAL LETTER E 169 | '\u1d07': 'E', // LATIN LETTER SMALL CAPITAL E 170 | '\uff26': 'F', // FULLWIDTH LATIN CAPITAL LETTER F 171 | '\ua730': 'F', // LATIN LETTER SMALL CAPITAL F 172 | '\uff27': 'G', // FULLWIDTH LATIN CAPITAL LETTER G 173 | '\u0262': 'G', // LATIN LETTER SMALL CAPITAL G 174 | '\uff28': 'H', // FULLWIDTH LATIN CAPITAL LETTER H 175 | '\u029c': 'H', // LATIN LETTER SMALL CAPITAL H 176 | '\uff29': 'I', // FULLWIDTH LATIN CAPITAL LETTER I 177 | '\u026a': 'I', // LATIN LETTER SMALL CAPITAL I 178 | '\uff2a': 'J', // FULLWIDTH LATIN CAPITAL LETTER J 179 | '\u1d0a': 'J', // LATIN LETTER SMALL CAPITAL J 180 | '\uff2b': 'K', // FULLWIDTH LATIN CAPITAL LETTER K 181 | '\u1d0b': 'K', // LATIN LETTER SMALL CAPITAL K 182 | '\uff2c': 'L', // FULLWIDTH LATIN CAPITAL LETTER L 183 | '\u029f': 'L', // LATIN LETTER SMALL CAPITAL L 184 | '\uff2d': 'M', // FULLWIDTH LATIN CAPITAL LETTER M 185 | '\u1d0d': 'M', // LATIN LETTER SMALL CAPITAL M 186 | '\uff2e': 'N', // FULLWIDTH LATIN CAPITAL LETTER N 187 | '\u0274': 'N', // LATIN LETTER SMALL CAPITAL N 188 | '\uff2f': 'O', // FULLWIDTH LATIN CAPITAL LETTER O 189 | '\u1d0f': 'O', // LATIN LETTER SMALL CAPITAL O 190 | '\uff30': 'P', // FULLWIDTH LATIN CAPITAL LETTER P 191 | '\u1d18': 'P', // LATIN LETTER SMALL CAPITAL P 192 | '\uff31': 'Q', // FULLWIDTH LATIN CAPITAL LETTER Q 193 | '\uff32': 'R', // FULLWIDTH LATIN CAPITAL LETTER R 194 | '\u0280': 'R', // LATIN LETTER SMALL CAPITAL R 195 | '\uff33': 'S', // FULLWIDTH LATIN CAPITAL LETTER S 196 | '\ua731': 'S', // LATIN LETTER SMALL CAPITAL S 197 | '\uff34': 'T', // FULLWIDTH LATIN CAPITAL LETTER T 198 | '\u1d1b': 'T', // LATIN LETTER SMALL CAPITAL T 199 | '\uff35': 'U', // FULLWIDTH LATIN CAPITAL LETTER U 200 | '\u1d1c': 'U', // LATIN LETTER SMALL CAPITAL U 201 | '\uff36': 'V', // FULLWIDTH LATIN CAPITAL LETTER V 202 | '\u1d20': 'V', // LATIN LETTER SMALL CAPITAL V 203 | '\uff37': 'W', // FULLWIDTH LATIN CAPITAL LETTER W 204 | '\u1d21': 'W', // LATIN LETTER SMALL CAPITAL W 205 | '\uff38': 'X', // FULLWIDTH LATIN CAPITAL LETTER X 206 | '\uff39': 'Y', // FULLWIDTH LATIN CAPITAL LETTER Y 207 | '\u028f': 'Y', // LATIN LETTER SMALL CAPITAL Y 208 | '\uff3a': 'Z', // FULLWIDTH LATIN CAPITAL LETTER Z 209 | '\u1d22': 'Z', // LATIN LETTER SMALL CAPITAL Z 210 | '\u02c6': '^', // MODIFIER LETTER CIRCUMFLEX ACCENT 211 | '\u0302': '^', // COMBINING CIRCUMFLEX ACCENT 212 | '\uff3e': '^', // FULLWIDTH CIRCUMFLEX ACCENT 213 | '\u1dcd': '^', // COMBINING DOUBLE CIRCUMFLEX ABOVE 214 | '\u2774': '{', // MEDIUM LEFT CURLY BRACKET ORNAMENT 215 | '\ufe5b': '{', // SMALL LEFT CURLY BRACKET 216 | '\uff5b': '{', // FULLWIDTH LEFT CURLY BRACKET 217 | '\u2775': '}', // MEDIUM RIGHT CURLY BRACKET ORNAMENT 218 | '\ufe5c': '}', // SMALL RIGHT CURLY BRACKET 219 | '\uff5d': '}', // FULLWIDTH RIGHT CURLY BRACKET 220 | '\uff3b': '[', // FULLWIDTH LEFT SQUARE BRACKET 221 | '\uff3d': ']', // FULLWIDTH RIGHT SQUARE BRACKET 222 | '\u02dc': '~', // SMALL TILDE 223 | '\u02f7': '~', // MODIFIER LETTER LOW TILDE 224 | '\u0303': '~', // COMBINING TILDE 225 | '\u0330': '~', // COMBINING TILDE BELOW 226 | '\u0334': '~', // COMBINING TILDE OVERLAY 227 | '\u223c': '~', // TILDE OPERATOR 228 | '\uff5e': '~', // FULLWIDTH TILDE 229 | '\u00a0': ' ', // NO-BREAK SPACE 230 | '\u2000': ' ', // EN QUAD 231 | '\u2002': ' ', // EN SPACE 232 | '\u2003': ' ', // EM SPACE 233 | '\u2004': ' ', // THREE-PER-EM SPACE 234 | '\u2005': ' ', // FOUR-PER-EM SPACE 235 | '\u2006': ' ', // SIX-PER-EM SPACE 236 | '\u2007': ' ', // FIGURE SPACE 237 | '\u2008': ' ', // PUNCTUATION SPACE 238 | '\u2009': ' ', // THIN SPACE 239 | '\u200a': ' ', // HAIR SPACE 240 | '\u202f': ' ', // NARROW NO-BREAK SPACE 241 | '\u205f': ' ', // MEDIUM MATHEMATICAL SPACE 242 | '\u3000': ' ', // IDEOGRAHPIC SPACE 243 | '\u008d': ' ', // REVERSE LINE FEED (standard LF looks like \n, this looks like a space) 244 | '\u009f': ' ', // 245 | '\u0080': ' ', // C1 CONTROL CODES 246 | '\u0090': ' ', // DEVICE CONTROL STRING 247 | '\u009b': ' ', // CONTROL SEQUENCE INTRODUCER 248 | '\u0010': '', // ESCAPE, DATA LINK (not visible) 249 | '\u0009': ' ', // TAB (7 spaces based on print statement in Python interpreter) 250 | '\u0000': '', // NULL 251 | '\u0003': '', // END OF TEXT 252 | '\u0004': '', // END OF TRANSMISSION 253 | '\u0017': '', // END OF TRANSMISSION BLOCK 254 | '\u0019': '', // END OF MEDIUM 255 | '\u0011': '', // DEVICE CONTROL ONE 256 | '\u0012': '', // DEVICE CONTROL TWO 257 | '\u0013': '', // DEVICE CONTROL THREE 258 | '\u0014': '', // DEVICE CONTROL FOUR 259 | '\u2060': '', // WORD JOINER 260 | '\u2017': '_', // DOUBLE LOW LINE 261 | '\u2014': '-', // EM DASH 262 | '\u2013': '-', // EN DASH 263 | '\u2039': '>', // Single left-pointing angle quotation mark 264 | '\u203A': '<', // Single right-pointing angle quotation mark 265 | '\u203C': '!!', // Double exclamation mark 266 | '\u2028': ' ', // Whitespace: Line Separator 267 | '\u2029': ' ', // Whitespace: Paragraph Separator 268 | '\u2026': '...', // Whitespace: Narrow No-Break Space 269 | '\u2001': ' ', // Whitespace: Medium Mathematical Space 270 | '\u200b': '', // ZERO WIDTH SPACE 271 | '\u3001': ',', // IDEOGRAPHIC COMMA 272 | '\uFEFF': '', // ZERO WIDTH NO-BREAK SPACE 273 | '\u2022': '-', // Bullet 274 | }; 275 | 276 | export default SmartEncodingMap; 277 | -------------------------------------------------------------------------------- /dist/libs/SegmentedMessage.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __read = (this && this.__read) || function (o, n) { 3 | var m = typeof Symbol === "function" && o[Symbol.iterator]; 4 | if (!m) return o; 5 | var i = m.call(o), r, ar = [], e; 6 | try { 7 | while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); 8 | } 9 | catch (error) { e = { error: error }; } 10 | finally { 11 | try { 12 | if (r && !r.done && (m = i["return"])) m.call(i); 13 | } 14 | finally { if (e) throw e.error; } 15 | } 16 | return ar; 17 | }; 18 | var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { 19 | if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { 20 | if (ar || !(i in from)) { 21 | if (!ar) ar = Array.prototype.slice.call(from, 0, i); 22 | ar[i] = from[i]; 23 | } 24 | } 25 | return to.concat(ar || Array.prototype.slice.call(from)); 26 | }; 27 | var __values = (this && this.__values) || function(o) { 28 | var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; 29 | if (m) return m.call(o); 30 | if (o && typeof o.length === "number") return { 31 | next: function () { 32 | if (o && i >= o.length) o = void 0; 33 | return { value: o && o[i++], done: !o }; 34 | } 35 | }; 36 | throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); 37 | }; 38 | var __importDefault = (this && this.__importDefault) || function (mod) { 39 | return (mod && mod.__esModule) ? mod : { "default": mod }; 40 | }; 41 | Object.defineProperty(exports, "__esModule", { value: true }); 42 | exports.SegmentedMessage = void 0; 43 | var grapheme_splitter_1 = __importDefault(require("grapheme-splitter")); 44 | var Segment_1 = __importDefault(require("./Segment")); 45 | var EncodedChar_1 = __importDefault(require("./EncodedChar")); 46 | var UnicodeToGSM_1 = __importDefault(require("./UnicodeToGSM")); 47 | var SmartEncodingMap_1 = __importDefault(require("./SmartEncodingMap")); 48 | var validEncodingValues = ['GSM-7', 'UCS-2', 'auto']; 49 | /** 50 | * Class representing a segmented SMS 51 | */ 52 | var SegmentedMessage = /** @class */ (function () { 53 | /** 54 | * 55 | * Create a new segmented message from a string 56 | * 57 | * @param {string} message Body of the message 58 | * @param {boolean} [encoding] Optional: encoding. It can be 'GSM-7', 'UCS-2', 'auto'. Default value: 'auto' 59 | * @param {boolean} smartEncoding Optional: whether or not Twilio's [Smart Encoding](https://www.twilio.com/docs/messaging/services#smart-encoding) is emulated. Default value: false 60 | * @property {number} numberOfUnicodeScalars Number of Unicode Scalars (i.e. unicode pairs) the message is made of 61 | * 62 | */ 63 | function SegmentedMessage(message, encoding, smartEncoding) { 64 | if (encoding === void 0) { encoding = 'auto'; } 65 | if (smartEncoding === void 0) { smartEncoding = false; } 66 | var splitter = new grapheme_splitter_1.default(); 67 | if (!validEncodingValues.includes(encoding)) { 68 | throw new Error("Encoding ".concat(encoding, " not supported. Valid values for encoding are ").concat(validEncodingValues.join(', '))); 69 | } 70 | if (smartEncoding) { 71 | message = __spreadArray([], __read(message), false).map(function (char) { return (SmartEncodingMap_1.default[char] === undefined ? char : SmartEncodingMap_1.default[char]); }) 72 | .join(''); 73 | } 74 | /** 75 | * @property {string[]} graphemes Graphemes (array of strings) the message have been split into 76 | */ 77 | this.graphemes = splitter.splitGraphemes(message).reduce(function (accumulator, grapheme) { 78 | var result = grapheme === '\r\n' ? grapheme.split('') : [grapheme]; 79 | return accumulator.concat(result); 80 | }, []); 81 | /** 82 | * @property {number} numberOfUnicodeScalars Number of Unicode Scalars (i.e. unicode pairs) the message is made of 83 | * Some characters (e.g. extended emoji) can be made of more than one unicode pair 84 | */ 85 | this.numberOfUnicodeScalars = __spreadArray([], __read(message), false).length; 86 | /** 87 | * @property {string} encoding Encoding set in the constructor for the message. Allowed values: 'GSM-7', 'UCS-2', 'auto'. 88 | * @private 89 | */ 90 | this.encoding = encoding; 91 | if (this.encoding === 'auto') { 92 | /** 93 | * @property {string} encodingName Calculated encoding name. It can be: "GSM-7" or "UCS-2" 94 | */ 95 | this.encodingName = this._hasAnyUCSCharacters(this.graphemes) ? 'UCS-2' : 'GSM-7'; 96 | } 97 | else { 98 | if (encoding === 'GSM-7' && this._hasAnyUCSCharacters(this.graphemes)) { 99 | throw new Error('The string provided is incompatible with GSM-7 encoding'); 100 | } 101 | this.encodingName = this.encoding; 102 | } 103 | /** 104 | * @property {string[]} encodedChars Array of encoded characters composing the message 105 | */ 106 | this.encodedChars = this._encodeChars(this.graphemes); 107 | /** 108 | * @property {number} numberOfCharacters Number of characters in the message. Each character count as 1 except for 109 | * the characters in the GSM extension character set. 110 | */ 111 | this.numberOfCharacters = 112 | this.encodingName === 'UCS-2' ? this.graphemes.length : this._countCodeUnits(this.encodedChars); 113 | /** 114 | * @property {object[]} segments Array of segment(s) the message have been segmented into 115 | */ 116 | this.segments = this._buildSegments(this.encodedChars); 117 | /** 118 | * @property {LineBreakStyle} lineBreakStyle message line break style 119 | */ 120 | this.lineBreakStyle = this._detectLineBreakStyle(message); 121 | /** 122 | * @property {string[]} warnings message line break style 123 | */ 124 | this.warnings = this._checkForWarnings(); 125 | } 126 | /** 127 | * Internal method to check if the message has any non-GSM7 characters 128 | * 129 | * @param {string[]} graphemes Message body 130 | * @returns {boolean} True if there are non-GSM-7 characters 131 | * @private 132 | */ 133 | SegmentedMessage.prototype._hasAnyUCSCharacters = function (graphemes) { 134 | var e_1, _a; 135 | var result = false; 136 | try { 137 | for (var graphemes_1 = __values(graphemes), graphemes_1_1 = graphemes_1.next(); !graphemes_1_1.done; graphemes_1_1 = graphemes_1.next()) { 138 | var grapheme = graphemes_1_1.value; 139 | if (grapheme.length >= 2 || (grapheme.length === 1 && !UnicodeToGSM_1.default[grapheme.charCodeAt(0)])) { 140 | result = true; 141 | break; 142 | } 143 | } 144 | } 145 | catch (e_1_1) { e_1 = { error: e_1_1 }; } 146 | finally { 147 | try { 148 | if (graphemes_1_1 && !graphemes_1_1.done && (_a = graphemes_1.return)) _a.call(graphemes_1); 149 | } 150 | finally { if (e_1) throw e_1.error; } 151 | } 152 | return result; 153 | }; 154 | /** 155 | * Internal method used to build message's segment(s) 156 | * 157 | * @param {object[]} encodedChars Array of EncodedChar 158 | * @returns {object[]} Array of Segment 159 | * @private 160 | */ 161 | SegmentedMessage.prototype._buildSegments = function (encodedChars) { 162 | var e_2, _a; 163 | var segments = []; 164 | segments.push(new Segment_1.default()); 165 | var currentSegment = segments[0]; 166 | try { 167 | for (var encodedChars_1 = __values(encodedChars), encodedChars_1_1 = encodedChars_1.next(); !encodedChars_1_1.done; encodedChars_1_1 = encodedChars_1.next()) { 168 | var encodedChar = encodedChars_1_1.value; 169 | if (currentSegment.freeSizeInBits() < encodedChar.sizeInBits()) { 170 | segments.push(new Segment_1.default(true)); 171 | currentSegment = segments[segments.length - 1]; 172 | var previousSegment = segments[segments.length - 2]; 173 | if (!previousSegment.hasUserDataHeader) { 174 | var removedChars = previousSegment.addHeader(); 175 | // eslint-disable-next-line no-loop-func 176 | removedChars.forEach(function (char) { return currentSegment.push(char); }); 177 | } 178 | } 179 | currentSegment.push(encodedChar); 180 | } 181 | } 182 | catch (e_2_1) { e_2 = { error: e_2_1 }; } 183 | finally { 184 | try { 185 | if (encodedChars_1_1 && !encodedChars_1_1.done && (_a = encodedChars_1.return)) _a.call(encodedChars_1); 186 | } 187 | finally { if (e_2) throw e_2.error; } 188 | } 189 | return segments; 190 | }; 191 | /** 192 | * Return the encoding of the message segment 193 | * 194 | * @returns {string} Encoding for the message segment(s) 195 | */ 196 | SegmentedMessage.prototype.getEncodingName = function () { 197 | return this.encodingName; 198 | }; 199 | /** 200 | * Internal method to create an array of EncodedChar from a string 201 | * 202 | * @param {string[]} graphemes Array of graphemes representing the message 203 | * @returns {object[]} Array of EncodedChar 204 | * @private 205 | */ 206 | SegmentedMessage.prototype._encodeChars = function (graphemes) { 207 | var e_3, _a; 208 | var encodedChars = []; 209 | try { 210 | for (var graphemes_2 = __values(graphemes), graphemes_2_1 = graphemes_2.next(); !graphemes_2_1.done; graphemes_2_1 = graphemes_2.next()) { 211 | var grapheme = graphemes_2_1.value; 212 | encodedChars.push(new EncodedChar_1.default(grapheme, this.encodingName)); 213 | } 214 | } 215 | catch (e_3_1) { e_3 = { error: e_3_1 }; } 216 | finally { 217 | try { 218 | if (graphemes_2_1 && !graphemes_2_1.done && (_a = graphemes_2.return)) _a.call(graphemes_2); 219 | } 220 | finally { if (e_3) throw e_3.error; } 221 | } 222 | return encodedChars; 223 | }; 224 | /** 225 | * Internal method to count the total number of code units of the message 226 | * 227 | * @param {EncodedChar[]} encodedChars Encoded message body 228 | * @returns {number} The total number of code units 229 | * @private 230 | */ 231 | SegmentedMessage.prototype._countCodeUnits = function (encodedChars) { 232 | return encodedChars.reduce(function (acumulator, nextEncodedChar) { return acumulator + nextEncodedChar.codeUnits.length; }, 0); 233 | }; 234 | Object.defineProperty(SegmentedMessage.prototype, "totalSize", { 235 | /** 236 | * @returns {number} Total size of the message in bits (including User Data Header if present) 237 | */ 238 | get: function () { 239 | var e_4, _a; 240 | var size = 0; 241 | try { 242 | for (var _b = __values(this.segments), _c = _b.next(); !_c.done; _c = _b.next()) { 243 | var segment = _c.value; 244 | size += segment.sizeInBits(); 245 | } 246 | } 247 | catch (e_4_1) { e_4 = { error: e_4_1 }; } 248 | finally { 249 | try { 250 | if (_c && !_c.done && (_a = _b.return)) _a.call(_b); 251 | } 252 | finally { if (e_4) throw e_4.error; } 253 | } 254 | return size; 255 | }, 256 | enumerable: false, 257 | configurable: true 258 | }); 259 | Object.defineProperty(SegmentedMessage.prototype, "messageSize", { 260 | /** 261 | * @returns {number} Total size of the message in bits (excluding User Data Header if present) 262 | */ 263 | get: function () { 264 | var e_5, _a; 265 | var size = 0; 266 | try { 267 | for (var _b = __values(this.segments), _c = _b.next(); !_c.done; _c = _b.next()) { 268 | var segment = _c.value; 269 | size += segment.messageSizeInBits(); 270 | } 271 | } 272 | catch (e_5_1) { e_5 = { error: e_5_1 }; } 273 | finally { 274 | try { 275 | if (_c && !_c.done && (_a = _b.return)) _a.call(_b); 276 | } 277 | finally { if (e_5) throw e_5.error; } 278 | } 279 | return size; 280 | }, 281 | enumerable: false, 282 | configurable: true 283 | }); 284 | Object.defineProperty(SegmentedMessage.prototype, "segmentsCount", { 285 | /** 286 | * 287 | * @returns {number} Number of segments 288 | */ 289 | get: function () { 290 | return this.segments.length; 291 | }, 292 | enumerable: false, 293 | configurable: true 294 | }); 295 | /** 296 | * 297 | * @returns {string[]} Array of characters representing the non GSM-7 characters in the message body 298 | */ 299 | SegmentedMessage.prototype.getNonGsmCharacters = function () { 300 | return this.encodedChars.filter(function (encodedChar) { return !encodedChar.isGSM7; }).map(function (encodedChar) { return encodedChar.raw; }); 301 | }; 302 | /** 303 | * Internal method to check the line break styled used in the passed message 304 | * 305 | * @param {string} message Message body 306 | * @returns {LineBreakStyle} The libre break style name LF or CRLF 307 | * @private 308 | */ 309 | SegmentedMessage.prototype._detectLineBreakStyle = function (message) { 310 | var hasWindowsStyle = message.includes('\r\n'); 311 | var HasUnixStyle = message.includes('\n'); 312 | var mixedStyle = hasWindowsStyle && HasUnixStyle; 313 | var noBreakLine = !hasWindowsStyle && !HasUnixStyle; 314 | if (noBreakLine) { 315 | return undefined; 316 | } 317 | if (mixedStyle) { 318 | return 'LF+CRLF'; 319 | } 320 | return HasUnixStyle ? 'LF' : 'CRLF'; 321 | }; 322 | /** 323 | * Internal method to check the line break styled used in the passed message 324 | * 325 | * @returns {string[]} The libre break style name LF or CRLF 326 | * @private 327 | */ 328 | SegmentedMessage.prototype._checkForWarnings = function () { 329 | var warnings = []; 330 | if (this.lineBreakStyle) { 331 | warnings.push('The message has line breaks, the web page utility only supports LF style. If you insert a CRLF it will be converted to LF.'); 332 | } 333 | return warnings; 334 | }; 335 | return SegmentedMessage; 336 | }()); 337 | exports.SegmentedMessage = SegmentedMessage; 338 | //# sourceMappingURL=SegmentedMessage.js.map -------------------------------------------------------------------------------- /docs/scripts/segmentsCalculator.js: -------------------------------------------------------------------------------- 1 | var SegmentedMessage;(()=>{var e={323:e=>{e.exports&&(e.exports=function(){var e=3,t=4,r=12,n=13,i=16,o=17;function s(e,t){void 0===t&&(t=0);var r=e.charCodeAt(t);if(55296<=r&&r<=56319&&t=1){var i=r;return 55296<=(n=e.charCodeAt(t-1))&&n<=56319?1024*(n-55296)+(i-56320)+65536:i}return r}function a(s,a,u){var c=[s].concat(a).concat([u]),f=c[c.length-2],l=u,h=c.lastIndexOf(14);if(h>1&&c.slice(1,h).every((function(t){return t==e}))&&-1==[e,n,o].indexOf(s))return 2;var d=c.lastIndexOf(t);if(d>0&&c.slice(1,d).every((function(e){return e==t}))&&-1==[r,t].indexOf(f))return c.filter((function(e){return e==t})).length%2==1?3:4;if(0==f&&1==l)return 0;if(2==f||0==f||1==f)return 14==l&&a.every((function(t){return t==e}))?2:1;if(2==l||0==l||1==l)return 1;if(6==f&&(6==l||7==l||9==l||10==l))return 0;if(!(9!=f&&7!=f||7!=l&&8!=l))return 0;if((10==f||8==f)&&8==l)return 0;if(l==e||15==l)return 0;if(5==l)return 0;if(f==r)return 0;var p=-1!=c.indexOf(e)?c.lastIndexOf(e)-1:c.length-2;return-1!=[n,o].indexOf(c[p])&&c.slice(p+1,-1).every((function(t){return t==e}))&&14==l||15==f&&-1!=[i,o].indexOf(l)?0:-1!=a.indexOf(t)?2:f==t&&l==t?0:1}function u(s){return 1536<=s&&s<=1541||1757==s||1807==s||2274==s||3406==s||69821==s||70082<=s&&s<=70083||72250==s||72326<=s&&s<=72329||73030==s?r:13==s?0:10==s?1:0<=s&&s<=9||11<=s&&s<=12||14<=s&&s<=31||127<=s&&s<=159||173==s||1564==s||6158==s||8203==s||8206<=s&&s<=8207||8232==s||8233==s||8234<=s&&s<=8238||8288<=s&&s<=8292||8293==s||8294<=s&&s<=8303||55296<=s&&s<=57343||65279==s||65520<=s&&s<=65528||65529<=s&&s<=65531||113824<=s&&s<=113827||119155<=s&&s<=119162||917504==s||917505==s||917506<=s&&s<=917535||917632<=s&&s<=917759||918e3<=s&&s<=921599?2:768<=s&&s<=879||1155<=s&&s<=1159||1160<=s&&s<=1161||1425<=s&&s<=1469||1471==s||1473<=s&&s<=1474||1476<=s&&s<=1477||1479==s||1552<=s&&s<=1562||1611<=s&&s<=1631||1648==s||1750<=s&&s<=1756||1759<=s&&s<=1764||1767<=s&&s<=1768||1770<=s&&s<=1773||1809==s||1840<=s&&s<=1866||1958<=s&&s<=1968||2027<=s&&s<=2035||2070<=s&&s<=2073||2075<=s&&s<=2083||2085<=s&&s<=2087||2089<=s&&s<=2093||2137<=s&&s<=2139||2260<=s&&s<=2273||2275<=s&&s<=2306||2362==s||2364==s||2369<=s&&s<=2376||2381==s||2385<=s&&s<=2391||2402<=s&&s<=2403||2433==s||2492==s||2494==s||2497<=s&&s<=2500||2509==s||2519==s||2530<=s&&s<=2531||2561<=s&&s<=2562||2620==s||2625<=s&&s<=2626||2631<=s&&s<=2632||2635<=s&&s<=2637||2641==s||2672<=s&&s<=2673||2677==s||2689<=s&&s<=2690||2748==s||2753<=s&&s<=2757||2759<=s&&s<=2760||2765==s||2786<=s&&s<=2787||2810<=s&&s<=2815||2817==s||2876==s||2878==s||2879==s||2881<=s&&s<=2884||2893==s||2902==s||2903==s||2914<=s&&s<=2915||2946==s||3006==s||3008==s||3021==s||3031==s||3072==s||3134<=s&&s<=3136||3142<=s&&s<=3144||3146<=s&&s<=3149||3157<=s&&s<=3158||3170<=s&&s<=3171||3201==s||3260==s||3263==s||3266==s||3270==s||3276<=s&&s<=3277||3285<=s&&s<=3286||3298<=s&&s<=3299||3328<=s&&s<=3329||3387<=s&&s<=3388||3390==s||3393<=s&&s<=3396||3405==s||3415==s||3426<=s&&s<=3427||3530==s||3535==s||3538<=s&&s<=3540||3542==s||3551==s||3633==s||3636<=s&&s<=3642||3655<=s&&s<=3662||3761==s||3764<=s&&s<=3769||3771<=s&&s<=3772||3784<=s&&s<=3789||3864<=s&&s<=3865||3893==s||3895==s||3897==s||3953<=s&&s<=3966||3968<=s&&s<=3972||3974<=s&&s<=3975||3981<=s&&s<=3991||3993<=s&&s<=4028||4038==s||4141<=s&&s<=4144||4146<=s&&s<=4151||4153<=s&&s<=4154||4157<=s&&s<=4158||4184<=s&&s<=4185||4190<=s&&s<=4192||4209<=s&&s<=4212||4226==s||4229<=s&&s<=4230||4237==s||4253==s||4957<=s&&s<=4959||5906<=s&&s<=5908||5938<=s&&s<=5940||5970<=s&&s<=5971||6002<=s&&s<=6003||6068<=s&&s<=6069||6071<=s&&s<=6077||6086==s||6089<=s&&s<=6099||6109==s||6155<=s&&s<=6157||6277<=s&&s<=6278||6313==s||6432<=s&&s<=6434||6439<=s&&s<=6440||6450==s||6457<=s&&s<=6459||6679<=s&&s<=6680||6683==s||6742==s||6744<=s&&s<=6750||6752==s||6754==s||6757<=s&&s<=6764||6771<=s&&s<=6780||6783==s||6832<=s&&s<=6845||6846==s||6912<=s&&s<=6915||6964==s||6966<=s&&s<=6970||6972==s||6978==s||7019<=s&&s<=7027||7040<=s&&s<=7041||7074<=s&&s<=7077||7080<=s&&s<=7081||7083<=s&&s<=7085||7142==s||7144<=s&&s<=7145||7149==s||7151<=s&&s<=7153||7212<=s&&s<=7219||7222<=s&&s<=7223||7376<=s&&s<=7378||7380<=s&&s<=7392||7394<=s&&s<=7400||7405==s||7412==s||7416<=s&&s<=7417||7616<=s&&s<=7673||7675<=s&&s<=7679||8204==s||8400<=s&&s<=8412||8413<=s&&s<=8416||8417==s||8418<=s&&s<=8420||8421<=s&&s<=8432||11503<=s&&s<=11505||11647==s||11744<=s&&s<=11775||12330<=s&&s<=12333||12334<=s&&s<=12335||12441<=s&&s<=12442||42607==s||42608<=s&&s<=42610||42612<=s&&s<=42621||42654<=s&&s<=42655||42736<=s&&s<=42737||43010==s||43014==s||43019==s||43045<=s&&s<=43046||43204<=s&&s<=43205||43232<=s&&s<=43249||43302<=s&&s<=43309||43335<=s&&s<=43345||43392<=s&&s<=43394||43443==s||43446<=s&&s<=43449||43452==s||43493==s||43561<=s&&s<=43566||43569<=s&&s<=43570||43573<=s&&s<=43574||43587==s||43596==s||43644==s||43696==s||43698<=s&&s<=43700||43703<=s&&s<=43704||43710<=s&&s<=43711||43713==s||43756<=s&&s<=43757||43766==s||44005==s||44008==s||44013==s||64286==s||65024<=s&&s<=65039||65056<=s&&s<=65071||65438<=s&&s<=65439||66045==s||66272==s||66422<=s&&s<=66426||68097<=s&&s<=68099||68101<=s&&s<=68102||68108<=s&&s<=68111||68152<=s&&s<=68154||68159==s||68325<=s&&s<=68326||69633==s||69688<=s&&s<=69702||69759<=s&&s<=69761||69811<=s&&s<=69814||69817<=s&&s<=69818||69888<=s&&s<=69890||69927<=s&&s<=69931||69933<=s&&s<=69940||70003==s||70016<=s&&s<=70017||70070<=s&&s<=70078||70090<=s&&s<=70092||70191<=s&&s<=70193||70196==s||70198<=s&&s<=70199||70206==s||70367==s||70371<=s&&s<=70378||70400<=s&&s<=70401||70460==s||70462==s||70464==s||70487==s||70502<=s&&s<=70508||70512<=s&&s<=70516||70712<=s&&s<=70719||70722<=s&&s<=70724||70726==s||70832==s||70835<=s&&s<=70840||70842==s||70845==s||70847<=s&&s<=70848||70850<=s&&s<=70851||71087==s||71090<=s&&s<=71093||71100<=s&&s<=71101||71103<=s&&s<=71104||71132<=s&&s<=71133||71219<=s&&s<=71226||71229==s||71231<=s&&s<=71232||71339==s||71341==s||71344<=s&&s<=71349||71351==s||71453<=s&&s<=71455||71458<=s&&s<=71461||71463<=s&&s<=71467||72193<=s&&s<=72198||72201<=s&&s<=72202||72243<=s&&s<=72248||72251<=s&&s<=72254||72263==s||72273<=s&&s<=72278||72281<=s&&s<=72283||72330<=s&&s<=72342||72344<=s&&s<=72345||72752<=s&&s<=72758||72760<=s&&s<=72765||72767==s||72850<=s&&s<=72871||72874<=s&&s<=72880||72882<=s&&s<=72883||72885<=s&&s<=72886||73009<=s&&s<=73014||73018==s||73020<=s&&s<=73021||73023<=s&&s<=73029||73031==s||92912<=s&&s<=92916||92976<=s&&s<=92982||94095<=s&&s<=94098||113821<=s&&s<=113822||119141==s||119143<=s&&s<=119145||119150<=s&&s<=119154||119163<=s&&s<=119170||119173<=s&&s<=119179||119210<=s&&s<=119213||119362<=s&&s<=119364||121344<=s&&s<=121398||121403<=s&&s<=121452||121461==s||121476==s||121499<=s&&s<=121503||121505<=s&&s<=121519||122880<=s&&s<=122886||122888<=s&&s<=122904||122907<=s&&s<=122913||122915<=s&&s<=122916||122918<=s&&s<=122922||125136<=s&&s<=125142||125252<=s&&s<=125258||917536<=s&&s<=917631||917760<=s&&s<=917999?e:127462<=s&&s<=127487?t:2307==s||2363==s||2366<=s&&s<=2368||2377<=s&&s<=2380||2382<=s&&s<=2383||2434<=s&&s<=2435||2495<=s&&s<=2496||2503<=s&&s<=2504||2507<=s&&s<=2508||2563==s||2622<=s&&s<=2624||2691==s||2750<=s&&s<=2752||2761==s||2763<=s&&s<=2764||2818<=s&&s<=2819||2880==s||2887<=s&&s<=2888||2891<=s&&s<=2892||3007==s||3009<=s&&s<=3010||3014<=s&&s<=3016||3018<=s&&s<=3020||3073<=s&&s<=3075||3137<=s&&s<=3140||3202<=s&&s<=3203||3262==s||3264<=s&&s<=3265||3267<=s&&s<=3268||3271<=s&&s<=3272||3274<=s&&s<=3275||3330<=s&&s<=3331||3391<=s&&s<=3392||3398<=s&&s<=3400||3402<=s&&s<=3404||3458<=s&&s<=3459||3536<=s&&s<=3537||3544<=s&&s<=3550||3570<=s&&s<=3571||3635==s||3763==s||3902<=s&&s<=3903||3967==s||4145==s||4155<=s&&s<=4156||4182<=s&&s<=4183||4228==s||6070==s||6078<=s&&s<=6085||6087<=s&&s<=6088||6435<=s&&s<=6438||6441<=s&&s<=6443||6448<=s&&s<=6449||6451<=s&&s<=6456||6681<=s&&s<=6682||6741==s||6743==s||6765<=s&&s<=6770||6916==s||6965==s||6971==s||6973<=s&&s<=6977||6979<=s&&s<=6980||7042==s||7073==s||7078<=s&&s<=7079||7082==s||7143==s||7146<=s&&s<=7148||7150==s||7154<=s&&s<=7155||7204<=s&&s<=7211||7220<=s&&s<=7221||7393==s||7410<=s&&s<=7411||7415==s||43043<=s&&s<=43044||43047==s||43136<=s&&s<=43137||43188<=s&&s<=43203||43346<=s&&s<=43347||43395==s||43444<=s&&s<=43445||43450<=s&&s<=43451||43453<=s&&s<=43456||43567<=s&&s<=43568||43571<=s&&s<=43572||43597==s||43755==s||43758<=s&&s<=43759||43765==s||44003<=s&&s<=44004||44006<=s&&s<=44007||44009<=s&&s<=44010||44012==s||69632==s||69634==s||69762==s||69808<=s&&s<=69810||69815<=s&&s<=69816||69932==s||70018==s||70067<=s&&s<=70069||70079<=s&&s<=70080||70188<=s&&s<=70190||70194<=s&&s<=70195||70197==s||70368<=s&&s<=70370||70402<=s&&s<=70403||70463==s||70465<=s&&s<=70468||70471<=s&&s<=70472||70475<=s&&s<=70477||70498<=s&&s<=70499||70709<=s&&s<=70711||70720<=s&&s<=70721||70725==s||70833<=s&&s<=70834||70841==s||70843<=s&&s<=70844||70846==s||70849==s||71088<=s&&s<=71089||71096<=s&&s<=71099||71102==s||71216<=s&&s<=71218||71227<=s&&s<=71228||71230==s||71340==s||71342<=s&&s<=71343||71350==s||71456<=s&&s<=71457||71462==s||72199<=s&&s<=72200||72249==s||72279<=s&&s<=72280||72343==s||72751==s||72766==s||72873==s||72881==s||72884==s||94033<=s&&s<=94078||119142==s||119149==s?5:4352<=s&&s<=4447||43360<=s&&s<=43388?6:4448<=s&&s<=4519||55216<=s&&s<=55238?7:4520<=s&&s<=4607||55243<=s&&s<=55291?8:44032==s||44060==s||44088==s||44116==s||44144==s||44172==s||44200==s||44228==s||44256==s||44284==s||44312==s||44340==s||44368==s||44396==s||44424==s||44452==s||44480==s||44508==s||44536==s||44564==s||44592==s||44620==s||44648==s||44676==s||44704==s||44732==s||44760==s||44788==s||44816==s||44844==s||44872==s||44900==s||44928==s||44956==s||44984==s||45012==s||45040==s||45068==s||45096==s||45124==s||45152==s||45180==s||45208==s||45236==s||45264==s||45292==s||45320==s||45348==s||45376==s||45404==s||45432==s||45460==s||45488==s||45516==s||45544==s||45572==s||45600==s||45628==s||45656==s||45684==s||45712==s||45740==s||45768==s||45796==s||45824==s||45852==s||45880==s||45908==s||45936==s||45964==s||45992==s||46020==s||46048==s||46076==s||46104==s||46132==s||46160==s||46188==s||46216==s||46244==s||46272==s||46300==s||46328==s||46356==s||46384==s||46412==s||46440==s||46468==s||46496==s||46524==s||46552==s||46580==s||46608==s||46636==s||46664==s||46692==s||46720==s||46748==s||46776==s||46804==s||46832==s||46860==s||46888==s||46916==s||46944==s||46972==s||47e3==s||47028==s||47056==s||47084==s||47112==s||47140==s||47168==s||47196==s||47224==s||47252==s||47280==s||47308==s||47336==s||47364==s||47392==s||47420==s||47448==s||47476==s||47504==s||47532==s||47560==s||47588==s||47616==s||47644==s||47672==s||47700==s||47728==s||47756==s||47784==s||47812==s||47840==s||47868==s||47896==s||47924==s||47952==s||47980==s||48008==s||48036==s||48064==s||48092==s||48120==s||48148==s||48176==s||48204==s||48232==s||48260==s||48288==s||48316==s||48344==s||48372==s||48400==s||48428==s||48456==s||48484==s||48512==s||48540==s||48568==s||48596==s||48624==s||48652==s||48680==s||48708==s||48736==s||48764==s||48792==s||48820==s||48848==s||48876==s||48904==s||48932==s||48960==s||48988==s||49016==s||49044==s||49072==s||49100==s||49128==s||49156==s||49184==s||49212==s||49240==s||49268==s||49296==s||49324==s||49352==s||49380==s||49408==s||49436==s||49464==s||49492==s||49520==s||49548==s||49576==s||49604==s||49632==s||49660==s||49688==s||49716==s||49744==s||49772==s||49800==s||49828==s||49856==s||49884==s||49912==s||49940==s||49968==s||49996==s||50024==s||50052==s||50080==s||50108==s||50136==s||50164==s||50192==s||50220==s||50248==s||50276==s||50304==s||50332==s||50360==s||50388==s||50416==s||50444==s||50472==s||50500==s||50528==s||50556==s||50584==s||50612==s||50640==s||50668==s||50696==s||50724==s||50752==s||50780==s||50808==s||50836==s||50864==s||50892==s||50920==s||50948==s||50976==s||51004==s||51032==s||51060==s||51088==s||51116==s||51144==s||51172==s||51200==s||51228==s||51256==s||51284==s||51312==s||51340==s||51368==s||51396==s||51424==s||51452==s||51480==s||51508==s||51536==s||51564==s||51592==s||51620==s||51648==s||51676==s||51704==s||51732==s||51760==s||51788==s||51816==s||51844==s||51872==s||51900==s||51928==s||51956==s||51984==s||52012==s||52040==s||52068==s||52096==s||52124==s||52152==s||52180==s||52208==s||52236==s||52264==s||52292==s||52320==s||52348==s||52376==s||52404==s||52432==s||52460==s||52488==s||52516==s||52544==s||52572==s||52600==s||52628==s||52656==s||52684==s||52712==s||52740==s||52768==s||52796==s||52824==s||52852==s||52880==s||52908==s||52936==s||52964==s||52992==s||53020==s||53048==s||53076==s||53104==s||53132==s||53160==s||53188==s||53216==s||53244==s||53272==s||53300==s||53328==s||53356==s||53384==s||53412==s||53440==s||53468==s||53496==s||53524==s||53552==s||53580==s||53608==s||53636==s||53664==s||53692==s||53720==s||53748==s||53776==s||53804==s||53832==s||53860==s||53888==s||53916==s||53944==s||53972==s||54e3==s||54028==s||54056==s||54084==s||54112==s||54140==s||54168==s||54196==s||54224==s||54252==s||54280==s||54308==s||54336==s||54364==s||54392==s||54420==s||54448==s||54476==s||54504==s||54532==s||54560==s||54588==s||54616==s||54644==s||54672==s||54700==s||54728==s||54756==s||54784==s||54812==s||54840==s||54868==s||54896==s||54924==s||54952==s||54980==s||55008==s||55036==s||55064==s||55092==s||55120==s||55148==s||55176==s?9:44033<=s&&s<=44059||44061<=s&&s<=44087||44089<=s&&s<=44115||44117<=s&&s<=44143||44145<=s&&s<=44171||44173<=s&&s<=44199||44201<=s&&s<=44227||44229<=s&&s<=44255||44257<=s&&s<=44283||44285<=s&&s<=44311||44313<=s&&s<=44339||44341<=s&&s<=44367||44369<=s&&s<=44395||44397<=s&&s<=44423||44425<=s&&s<=44451||44453<=s&&s<=44479||44481<=s&&s<=44507||44509<=s&&s<=44535||44537<=s&&s<=44563||44565<=s&&s<=44591||44593<=s&&s<=44619||44621<=s&&s<=44647||44649<=s&&s<=44675||44677<=s&&s<=44703||44705<=s&&s<=44731||44733<=s&&s<=44759||44761<=s&&s<=44787||44789<=s&&s<=44815||44817<=s&&s<=44843||44845<=s&&s<=44871||44873<=s&&s<=44899||44901<=s&&s<=44927||44929<=s&&s<=44955||44957<=s&&s<=44983||44985<=s&&s<=45011||45013<=s&&s<=45039||45041<=s&&s<=45067||45069<=s&&s<=45095||45097<=s&&s<=45123||45125<=s&&s<=45151||45153<=s&&s<=45179||45181<=s&&s<=45207||45209<=s&&s<=45235||45237<=s&&s<=45263||45265<=s&&s<=45291||45293<=s&&s<=45319||45321<=s&&s<=45347||45349<=s&&s<=45375||45377<=s&&s<=45403||45405<=s&&s<=45431||45433<=s&&s<=45459||45461<=s&&s<=45487||45489<=s&&s<=45515||45517<=s&&s<=45543||45545<=s&&s<=45571||45573<=s&&s<=45599||45601<=s&&s<=45627||45629<=s&&s<=45655||45657<=s&&s<=45683||45685<=s&&s<=45711||45713<=s&&s<=45739||45741<=s&&s<=45767||45769<=s&&s<=45795||45797<=s&&s<=45823||45825<=s&&s<=45851||45853<=s&&s<=45879||45881<=s&&s<=45907||45909<=s&&s<=45935||45937<=s&&s<=45963||45965<=s&&s<=45991||45993<=s&&s<=46019||46021<=s&&s<=46047||46049<=s&&s<=46075||46077<=s&&s<=46103||46105<=s&&s<=46131||46133<=s&&s<=46159||46161<=s&&s<=46187||46189<=s&&s<=46215||46217<=s&&s<=46243||46245<=s&&s<=46271||46273<=s&&s<=46299||46301<=s&&s<=46327||46329<=s&&s<=46355||46357<=s&&s<=46383||46385<=s&&s<=46411||46413<=s&&s<=46439||46441<=s&&s<=46467||46469<=s&&s<=46495||46497<=s&&s<=46523||46525<=s&&s<=46551||46553<=s&&s<=46579||46581<=s&&s<=46607||46609<=s&&s<=46635||46637<=s&&s<=46663||46665<=s&&s<=46691||46693<=s&&s<=46719||46721<=s&&s<=46747||46749<=s&&s<=46775||46777<=s&&s<=46803||46805<=s&&s<=46831||46833<=s&&s<=46859||46861<=s&&s<=46887||46889<=s&&s<=46915||46917<=s&&s<=46943||46945<=s&&s<=46971||46973<=s&&s<=46999||47001<=s&&s<=47027||47029<=s&&s<=47055||47057<=s&&s<=47083||47085<=s&&s<=47111||47113<=s&&s<=47139||47141<=s&&s<=47167||47169<=s&&s<=47195||47197<=s&&s<=47223||47225<=s&&s<=47251||47253<=s&&s<=47279||47281<=s&&s<=47307||47309<=s&&s<=47335||47337<=s&&s<=47363||47365<=s&&s<=47391||47393<=s&&s<=47419||47421<=s&&s<=47447||47449<=s&&s<=47475||47477<=s&&s<=47503||47505<=s&&s<=47531||47533<=s&&s<=47559||47561<=s&&s<=47587||47589<=s&&s<=47615||47617<=s&&s<=47643||47645<=s&&s<=47671||47673<=s&&s<=47699||47701<=s&&s<=47727||47729<=s&&s<=47755||47757<=s&&s<=47783||47785<=s&&s<=47811||47813<=s&&s<=47839||47841<=s&&s<=47867||47869<=s&&s<=47895||47897<=s&&s<=47923||47925<=s&&s<=47951||47953<=s&&s<=47979||47981<=s&&s<=48007||48009<=s&&s<=48035||48037<=s&&s<=48063||48065<=s&&s<=48091||48093<=s&&s<=48119||48121<=s&&s<=48147||48149<=s&&s<=48175||48177<=s&&s<=48203||48205<=s&&s<=48231||48233<=s&&s<=48259||48261<=s&&s<=48287||48289<=s&&s<=48315||48317<=s&&s<=48343||48345<=s&&s<=48371||48373<=s&&s<=48399||48401<=s&&s<=48427||48429<=s&&s<=48455||48457<=s&&s<=48483||48485<=s&&s<=48511||48513<=s&&s<=48539||48541<=s&&s<=48567||48569<=s&&s<=48595||48597<=s&&s<=48623||48625<=s&&s<=48651||48653<=s&&s<=48679||48681<=s&&s<=48707||48709<=s&&s<=48735||48737<=s&&s<=48763||48765<=s&&s<=48791||48793<=s&&s<=48819||48821<=s&&s<=48847||48849<=s&&s<=48875||48877<=s&&s<=48903||48905<=s&&s<=48931||48933<=s&&s<=48959||48961<=s&&s<=48987||48989<=s&&s<=49015||49017<=s&&s<=49043||49045<=s&&s<=49071||49073<=s&&s<=49099||49101<=s&&s<=49127||49129<=s&&s<=49155||49157<=s&&s<=49183||49185<=s&&s<=49211||49213<=s&&s<=49239||49241<=s&&s<=49267||49269<=s&&s<=49295||49297<=s&&s<=49323||49325<=s&&s<=49351||49353<=s&&s<=49379||49381<=s&&s<=49407||49409<=s&&s<=49435||49437<=s&&s<=49463||49465<=s&&s<=49491||49493<=s&&s<=49519||49521<=s&&s<=49547||49549<=s&&s<=49575||49577<=s&&s<=49603||49605<=s&&s<=49631||49633<=s&&s<=49659||49661<=s&&s<=49687||49689<=s&&s<=49715||49717<=s&&s<=49743||49745<=s&&s<=49771||49773<=s&&s<=49799||49801<=s&&s<=49827||49829<=s&&s<=49855||49857<=s&&s<=49883||49885<=s&&s<=49911||49913<=s&&s<=49939||49941<=s&&s<=49967||49969<=s&&s<=49995||49997<=s&&s<=50023||50025<=s&&s<=50051||50053<=s&&s<=50079||50081<=s&&s<=50107||50109<=s&&s<=50135||50137<=s&&s<=50163||50165<=s&&s<=50191||50193<=s&&s<=50219||50221<=s&&s<=50247||50249<=s&&s<=50275||50277<=s&&s<=50303||50305<=s&&s<=50331||50333<=s&&s<=50359||50361<=s&&s<=50387||50389<=s&&s<=50415||50417<=s&&s<=50443||50445<=s&&s<=50471||50473<=s&&s<=50499||50501<=s&&s<=50527||50529<=s&&s<=50555||50557<=s&&s<=50583||50585<=s&&s<=50611||50613<=s&&s<=50639||50641<=s&&s<=50667||50669<=s&&s<=50695||50697<=s&&s<=50723||50725<=s&&s<=50751||50753<=s&&s<=50779||50781<=s&&s<=50807||50809<=s&&s<=50835||50837<=s&&s<=50863||50865<=s&&s<=50891||50893<=s&&s<=50919||50921<=s&&s<=50947||50949<=s&&s<=50975||50977<=s&&s<=51003||51005<=s&&s<=51031||51033<=s&&s<=51059||51061<=s&&s<=51087||51089<=s&&s<=51115||51117<=s&&s<=51143||51145<=s&&s<=51171||51173<=s&&s<=51199||51201<=s&&s<=51227||51229<=s&&s<=51255||51257<=s&&s<=51283||51285<=s&&s<=51311||51313<=s&&s<=51339||51341<=s&&s<=51367||51369<=s&&s<=51395||51397<=s&&s<=51423||51425<=s&&s<=51451||51453<=s&&s<=51479||51481<=s&&s<=51507||51509<=s&&s<=51535||51537<=s&&s<=51563||51565<=s&&s<=51591||51593<=s&&s<=51619||51621<=s&&s<=51647||51649<=s&&s<=51675||51677<=s&&s<=51703||51705<=s&&s<=51731||51733<=s&&s<=51759||51761<=s&&s<=51787||51789<=s&&s<=51815||51817<=s&&s<=51843||51845<=s&&s<=51871||51873<=s&&s<=51899||51901<=s&&s<=51927||51929<=s&&s<=51955||51957<=s&&s<=51983||51985<=s&&s<=52011||52013<=s&&s<=52039||52041<=s&&s<=52067||52069<=s&&s<=52095||52097<=s&&s<=52123||52125<=s&&s<=52151||52153<=s&&s<=52179||52181<=s&&s<=52207||52209<=s&&s<=52235||52237<=s&&s<=52263||52265<=s&&s<=52291||52293<=s&&s<=52319||52321<=s&&s<=52347||52349<=s&&s<=52375||52377<=s&&s<=52403||52405<=s&&s<=52431||52433<=s&&s<=52459||52461<=s&&s<=52487||52489<=s&&s<=52515||52517<=s&&s<=52543||52545<=s&&s<=52571||52573<=s&&s<=52599||52601<=s&&s<=52627||52629<=s&&s<=52655||52657<=s&&s<=52683||52685<=s&&s<=52711||52713<=s&&s<=52739||52741<=s&&s<=52767||52769<=s&&s<=52795||52797<=s&&s<=52823||52825<=s&&s<=52851||52853<=s&&s<=52879||52881<=s&&s<=52907||52909<=s&&s<=52935||52937<=s&&s<=52963||52965<=s&&s<=52991||52993<=s&&s<=53019||53021<=s&&s<=53047||53049<=s&&s<=53075||53077<=s&&s<=53103||53105<=s&&s<=53131||53133<=s&&s<=53159||53161<=s&&s<=53187||53189<=s&&s<=53215||53217<=s&&s<=53243||53245<=s&&s<=53271||53273<=s&&s<=53299||53301<=s&&s<=53327||53329<=s&&s<=53355||53357<=s&&s<=53383||53385<=s&&s<=53411||53413<=s&&s<=53439||53441<=s&&s<=53467||53469<=s&&s<=53495||53497<=s&&s<=53523||53525<=s&&s<=53551||53553<=s&&s<=53579||53581<=s&&s<=53607||53609<=s&&s<=53635||53637<=s&&s<=53663||53665<=s&&s<=53691||53693<=s&&s<=53719||53721<=s&&s<=53747||53749<=s&&s<=53775||53777<=s&&s<=53803||53805<=s&&s<=53831||53833<=s&&s<=53859||53861<=s&&s<=53887||53889<=s&&s<=53915||53917<=s&&s<=53943||53945<=s&&s<=53971||53973<=s&&s<=53999||54001<=s&&s<=54027||54029<=s&&s<=54055||54057<=s&&s<=54083||54085<=s&&s<=54111||54113<=s&&s<=54139||54141<=s&&s<=54167||54169<=s&&s<=54195||54197<=s&&s<=54223||54225<=s&&s<=54251||54253<=s&&s<=54279||54281<=s&&s<=54307||54309<=s&&s<=54335||54337<=s&&s<=54363||54365<=s&&s<=54391||54393<=s&&s<=54419||54421<=s&&s<=54447||54449<=s&&s<=54475||54477<=s&&s<=54503||54505<=s&&s<=54531||54533<=s&&s<=54559||54561<=s&&s<=54587||54589<=s&&s<=54615||54617<=s&&s<=54643||54645<=s&&s<=54671||54673<=s&&s<=54699||54701<=s&&s<=54727||54729<=s&&s<=54755||54757<=s&&s<=54783||54785<=s&&s<=54811||54813<=s&&s<=54839||54841<=s&&s<=54867||54869<=s&&s<=54895||54897<=s&&s<=54923||54925<=s&&s<=54951||54953<=s&&s<=54979||54981<=s&&s<=55007||55009<=s&&s<=55035||55037<=s&&s<=55063||55065<=s&&s<=55091||55093<=s&&s<=55119||55121<=s&&s<=55147||55149<=s&&s<=55175||55177<=s&&s<=55203?10:9757==s||9977==s||9994<=s&&s<=9997||127877==s||127938<=s&&s<=127940||127943==s||127946<=s&&s<=127948||128066<=s&&s<=128067||128070<=s&&s<=128080||128110==s||128112<=s&&s<=128120||128124==s||128129<=s&&s<=128131||128133<=s&&s<=128135||128170==s||128372<=s&&s<=128373||128378==s||128400==s||128405<=s&&s<=128406||128581<=s&&s<=128583||128587<=s&&s<=128591||128675==s||128692<=s&&s<=128694||128704==s||128716==s||129304<=s&&s<=129308||129310<=s&&s<=129311||129318==s||129328<=s&&s<=129337||129341<=s&&s<=129342||129489<=s&&s<=129501?n:127995<=s&&s<=127999?14:8205==s?15:9792==s||9794==s||9877<=s&&s<=9878||9992==s||10084==s||127752==s||127806==s||127859==s||127891==s||127908==s||127912==s||127979==s||127981==s||128139==s||128187<=s&&s<=128188||128295==s||128300==s||128488==s||128640==s||128658==s?i:128102<=s&&s<=128105?o:11}return this.nextBreak=function(e,t){if(void 0===t&&(t=0),t<0)return 0;if(t>=e.length-1)return e.length;for(var r,n,i=u(s(e,t)),o=[],c=t+1;c0)&&!(n=o.next()).done;)s.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=o.return)&&r.call(o)}finally{if(i)throw i.error}}return s},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,i=0,o=t.length;i=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.SegmentedMessage=void 0;var a=s(r(323)),u=s(r(856)),c=s(r(555)),f=s(r(254)),l=s(r(33)),h=["GSM-7","UCS-2","auto"],d=function(){function e(e,t,r){void 0===t&&(t="auto"),void 0===r&&(r=!1);var o=new a.default;if(!h.includes(t))throw new Error("Encoding ".concat(t," not supported. Valid values for encoding are ").concat(h.join(", ")));if(r&&(e=i([],n(e),!1).map((function(e){return void 0===l.default[e]?e:l.default[e]})).join("")),this.graphemes=o.splitGraphemes(e).reduce((function(e,t){var r="\r\n"===t?t.split(""):[t];return e.concat(r)}),[]),this.numberOfUnicodeScalars=i([],n(e),!1).length,this.encoding=t,"auto"===this.encoding)this.encodingName=this._hasAnyUCSCharacters(this.graphemes)?"UCS-2":"GSM-7";else{if("GSM-7"===t&&this._hasAnyUCSCharacters(this.graphemes))throw new Error("The string provided is incompatible with GSM-7 encoding");this.encodingName=this.encoding}this.encodedChars=this._encodeChars(this.graphemes),this.numberOfCharacters="UCS-2"===this.encodingName?this.graphemes.length:this._countCodeUnits(this.encodedChars),this.segments=this._buildSegments(this.encodedChars),this.lineBreakStyle=this._detectLineBreakStyle(e),this.warnings=this._checkForWarnings()}return e.prototype._hasAnyUCSCharacters=function(e){var t,r,n=!1;try{for(var i=o(e),s=i.next();!s.done;s=i.next()){var a=s.value;if(a.length>=2||1===a.length&&!f.default[a.charCodeAt(0)]){n=!0;break}}}catch(e){t={error:e}}finally{try{s&&!s.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return n},e.prototype._buildSegments=function(e){var t,r,n=[];n.push(new u.default);var i=n[0];try{for(var s=o(e),a=s.next();!a.done;a=s.next()){var c=a.value;if(i.freeSizeInBits(){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={"«":'"',"»":'"',"“":'"',"”":'"',ʺ:'"',ˮ:'"',"‟":'"',"❝":'"',"❞":'"',"〝":'"',"〞":'"',""":'"',"‘":"'","’":"'",ʻ:"'",ˈ:"'",ʼ:"'",ʽ:"'",ʹ:"'","‛":"'","'":"'","´":"'",ˊ:"'","`":"'",ˋ:"'","❛":"'","❜":"'","̓":"'","̔":"'","︐":"'","︑":"'","÷":"/","¼":"1/4","½":"1/2","¾":"3/4","⧸":"/","̷":"/","̸":"/","⁄":"/","∕":"/","/":"/","⧹":"\\","⧵":"\\","⃥":"\\","﹨":"\\","\":"\\","̲":"_","_":"_","⃒":"|","⃓":"|","∣":"|","|":"|","⎸":"|","⎹":"|","⏐":"|","⎜":"|","⎟":"|","⎼":"-","⎽":"-","―":"-","﹣":"-","-":"-","‐":"-","⁃":"-","﹫":"@","@":"@","﹩":"$","$":"$",ǃ:"!","︕":"!","﹗":"!","!":"!","﹟":"#","#":"#","﹪":"%","%":"%","﹠":"&","&":"&","‚":",","̦":",","﹐":",","﹑":",",",":",","、":",","❨":"(","❪":"(","﹙":"(","(":"(","⟮":"(","⦅":"(","❩":")","❫":")","﹚":")",")":")","⟯":")","⦆":")","⁎":"*","∗":"*","⊛":"*","✢":"*","✣":"*","✤":"*","✥":"*","✱":"*","✲":"*","✳":"*","✺":"*","✻":"*","✼":"*","✽":"*","❃":"*","❉":"*","❊":"*","❋":"*","⧆":"*","﹡":"*","*":"*","˖":"+","﹢":"+","+":"+","。":".","﹒":".",".":".","。":".","0":"0","1":"1","2":"2","3":"3","4":"4","5":"5","6":"6","7":"7","8":"8","9":"9",ː:":","˸":":","⦂":":","꞉":":","︓":":",":":":","⁏":";","︔":";","﹔":";",";":";","﹤":"<","<":"<","͇":"=","꞊":"=","﹦":"=","=":"=","﹥":">",">":">","︖":"?","﹖":"?","?":"?",A:"A",ᴀ:"A",B:"B",ʙ:"B",C:"C",ᴄ:"C",D:"D",ᴅ:"D",E:"E",ᴇ:"E",F:"F",ꜰ:"F",G:"G",ɢ:"G",H:"H",ʜ:"H",I:"I",ɪ:"I",J:"J",ᴊ:"J",K:"K",ᴋ:"K",L:"L",ʟ:"L",M:"M",ᴍ:"M",N:"N",ɴ:"N",O:"O",ᴏ:"O",P:"P",ᴘ:"P",Q:"Q",R:"R",ʀ:"R",S:"S",ꜱ:"S",T:"T",ᴛ:"T",U:"U",ᴜ:"U",V:"V",ᴠ:"V",W:"W",ᴡ:"W",X:"X",Y:"Y",ʏ:"Y",Z:"Z",ᴢ:"Z",ˆ:"^","̂":"^","^":"^","᷍":"^","❴":"{","﹛":"{","{":"{","❵":"}","﹜":"}","}":"}","[":"[","]":"]","˜":"~","˷":"~","̃":"~","̰":"~","̴":"~","∼":"~","~":"~"," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" "," ":" ","":" ","Ÿ":" ","€":" ","":" ","›":" ","":"","\t":" ","\0":"","":"","":"","":"","":"","":"","":"","":"","":"","⁠":"","‗":"'","—":"-","–":"-","‹":">","›":"<","‼":"!!","„":'"',"\u2028":" ","\u2029":" ","…":"..."," ":" ","​":"","、":",","\ufeff":"","•":"-"}},254:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={10:[10],12:[27,10],13:[13],32:[32],33:[33],34:[34],35:[35],36:[2],37:[37],38:[38],39:[39],40:[40],41:[41],42:[42],43:[43],44:[44],45:[45],46:[46],47:[47],48:[48],49:[49],50:[50],51:[51],52:[52],53:[53],54:[54],55:[55],56:[56],57:[57],58:[58],59:[59],60:[60],61:[61],62:[62],63:[63],64:[0],65:[65],66:[66],67:[67],68:[68],69:[69],70:[70],71:[71],72:[72],73:[73],74:[74],75:[75],76:[76],77:[77],78:[78],79:[79],80:[80],81:[81],82:[82],83:[83],84:[84],85:[85],86:[86],87:[87],88:[88],89:[89],90:[90],91:[27,60],92:[27,47],93:[27,62],94:[27,20],95:[17],97:[97],98:[98],99:[99],100:[100],101:[101],102:[102],103:[103],104:[104],105:[105],106:[106],107:[107],108:[108],109:[109],110:[110],111:[111],112:[112],113:[113],114:[114],115:[115],116:[116],117:[117],118:[118],119:[119],120:[120],121:[121],122:[122],123:[27,40],124:[27,64],125:[27,41],126:[27,61],161:[64],163:[1],164:[36],165:[3],167:[95],191:[96],196:[91],197:[14],198:[28],201:[31],209:[93],214:[92],216:[11],220:[94],223:[30],224:[127],228:[123],229:[15],230:[29],199:[9],232:[4],233:[5],236:[7],241:[125],242:[8],246:[124],248:[12],249:[6],252:[126],915:[19],916:[16],920:[25],923:[20],926:[26],928:[22],931:[24],934:[18],936:[23],937:[21],8364:[27,101]}},710:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(){this.isReservedChar=!0,this.isUserDataHeader=!0}return e.codeUnitSizeInBits=function(){return 8},e.prototype.sizeInBits=function(){return 8},e}();t.default=r}},t={};function r(n){var i=t[n];if(void 0!==i)return i.exports;var o=t[n]={exports:{}};return e[n].call(o.exports,o,o.exports,r),o.exports}var n={};(()=>{"use strict";var e=n;e.SegmentedMessage=void 0;var t=r(410);Object.defineProperty(e,"SegmentedMessage",{enumerable:!0,get:function(){return t.SegmentedMessage}})})(),SegmentedMessage=n.SegmentedMessage})(); --------------------------------------------------------------------------------