pax_global_header00006660000000000000000000000064130262653040014513gustar00rootroot0000000000000052 comment=bde3deba75c01fa95d18cd4786593df2318cdeb6 lines-and-columns-1.1.6/000077500000000000000000000000001302626530400150505ustar00rootroot00000000000000lines-and-columns-1.1.6/.babelrc000066400000000000000000000004561302626530400164500ustar00rootroot00000000000000{ "plugins": [ "syntax-class-properties", "transform-es2015-block-scoping", "transform-flow-strip-types", "transform-strict-mode", "transform-class-properties", "transform-es2015-classes", "transform-es2015-destructuring", "transform-es2015-shorthand-properties" ] }lines-and-columns-1.1.6/.gitignore000066400000000000000000000000051302626530400170330ustar00rootroot00000000000000dist lines-and-columns-1.1.6/.travis.yml000066400000000000000000000006701302626530400171640ustar00rootroot00000000000000sudo: false language: node_js cache: directories: - node_modules notifications: email: false node_js: - '6' - '4' - '0.12' before_install: - npm i -g npm@^2.0.0 before_script: - npm prune after_success: - 'curl -Lo travis_after_all.py https://git.io/travis_after_all' - python travis_after_all.py - export $(cat .to_export_back) &> /dev/null - npm run semantic-release branches: except: - /^v\d+\.\d+\.\d+$/ lines-and-columns-1.1.6/LICENSE000066400000000000000000000020701302626530400160540ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 Brian Donovan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lines-and-columns-1.1.6/README.md000066400000000000000000000010501302626530400163230ustar00rootroot00000000000000# lines-and-columns Maps lines and columns to character offsets and back. This is useful for parsers and other text processors that deal in character ranges but process text with meaningful lines and columns. ## Install ``` $ npm install [--save] lines-and-columns ``` ## Usage ```js import LinesAndColumns from 'lines-and-columns'; const lines = new LinesAndColumns( `table { border: 0 }`); lines.locationForIndex(9); // { line: 1, column: 1 } lines.indexForLocation({ line: 1, column: 2 }); // 10 ``` ## License MIT lines-and-columns-1.1.6/package.json000066400000000000000000000024231302626530400173370ustar00rootroot00000000000000{ "name": "lines-and-columns", "description": "Maps lines and columns to character offsets and back.", "main": "dist/index.js", "module": "dist/index.mjs", "types": "dist/index.d.ts", "scripts": { "lint": "tslint --config tslint.json --project tsconfig.json --type-check", "lint-fix": "tslint --config tslint.json --project tsconfig.json --type-check --fix", "prebuild": "rm -rf dist", "build": "./script/build", "pretest": "npm run build", "test": "mocha", "prepublish": "npm run lint && npm run build", "semantic-release": "semantic-release pre && npm publish && semantic-release post" }, "files": [ "dist" ], "repository": { "type": "git", "url": "https://github.com/eventualbuddha/lines-and-columns.git" }, "keywords": [ "lines", "columns", "parser" ], "author": "Brian Donovan ", "license": "MIT", "bugs": { "url": "https://github.com/eventualbuddha/lines-and-columns/issues" }, "homepage": "https://github.com/eventualbuddha/lines-and-columns#readme", "devDependencies": { "@types/mocha": "^2.2.34", "@types/node": "^6.0.52", "mocha": "^3.2.0", "semantic-release": "^6.3.2", "ts-node": "^1.7.2", "tslint": "^4.1.1", "typescript": "^2.1.4" } } lines-and-columns-1.1.6/script/000077500000000000000000000000001302626530400163545ustar00rootroot00000000000000lines-and-columns-1.1.6/script/build000077500000000000000000000010461302626530400174020ustar00rootroot00000000000000#!/usr/bin/env bash set -e DIST="${DIST:-dist}" TSC="${TSC:-node_modules/.bin/tsc}" rm -rf "${DIST}" echo 'Building ES module version.' "${TSC}" \ --project . \ --outDir "${DIST}" \ --module ES2015 \ --moduleResolution node for js in $(find "${DIST}" -name '*.js'); do mv "${js}" "$(dirname "${js}")/$(basename "${js}" .js).mjs" done echo 'Building CommonJS version.' "${TSC}" \ --project . \ --outDir "${DIST}" \ --module commonjs \ --moduleResolution node # Restructure. rm -rf dist/test mv dist/src/* dist/ rmdir dist/src lines-and-columns-1.1.6/src/000077500000000000000000000000001302626530400156375ustar00rootroot00000000000000lines-and-columns-1.1.6/src/index.ts000066400000000000000000000031041302626530400173140ustar00rootroot00000000000000export type SourceLocation = { line: number, column: number }; const LF = '\n'; const CR = '\r'; export default class LinesAndColumns { private string: string; private offsets: Array; constructor(string: string) { this.string = string; let offsets = [0]; for (let offset = 0; offset < string.length;) { switch (string[offset]) { case LF: offset += LF.length; offsets.push(offset); break; case CR: offset += CR.length; if (string[offset] === LF) { offset += LF.length; } offsets.push(offset); break; default: offset++; break; } } this.offsets = offsets; } locationForIndex(index: number): SourceLocation | null { if (index < 0 || index > this.string.length) { return null; } let line = 0; let offsets = this.offsets; while (offsets[line + 1] <= index) { line++; } let column = index - offsets[line]; return { line, column }; } indexForLocation(location: SourceLocation): number | null { let { line, column } = location; if (line < 0 || line >= this.offsets.length) { return null; } if (column < 0 || column > this.lengthOfLine(line)) { return null; } return this.offsets[line] + column; } private lengthOfLine(line: number): number { let offset = this.offsets[line]; let nextOffset = line === this.offsets.length - 1 ? this.string.length : this.offsets[line + 1]; return nextOffset - offset; } } lines-and-columns-1.1.6/test/000077500000000000000000000000001302626530400160275ustar00rootroot00000000000000lines-and-columns-1.1.6/test/mocha.opts000066400000000000000000000000541302626530400200240ustar00rootroot00000000000000--compilers ts:ts-node/register --recursive lines-and-columns-1.1.6/test/test.ts000066400000000000000000000073711302626530400173660ustar00rootroot00000000000000import { deepEqual as deq, strictEqual as eq } from 'assert'; import LinesAndColumns from '../src'; describe('LinesAndColumns', function() { it('maps index 0 to line 0, column 0', function() { const map = new LinesAndColumns('a'); deq(map.locationForIndex(0), { line: 0, column: 0 }); }); it('maps indexes in a single-line string to line 0 and column at index', function() { const map = new LinesAndColumns('abcd'); deq(map.locationForIndex(2), { line: 0, column: 2 }); }); it('maps indexes in a multi-line string to the appropriate line and column', function() { const map = new LinesAndColumns('ab\ncd'); deq(map.locationForIndex(2), { line: 0, column: 2 }); deq(map.locationForIndex(3), { line: 1, column: 0 }); }); it('maps indexes before the beginning to null', function() { const map = new LinesAndColumns(''); eq(map.locationForIndex(-1), null); }); it('maps indexes at the end', function() { const map = new LinesAndColumns(''); deq(map.locationForIndex(0), { line: 0, column: 0 }); }); it('maps indexes after the end to null', function() { const map = new LinesAndColumns(''); eq(map.locationForIndex(1), null); }); it('maps line 0, column 0 to index 0', function() { const map = new LinesAndColumns('a'); eq(map.indexForLocation({ line: 0, column: 0 }), 0); }); it('maps line 0, column N to index N', function() { const map = new LinesAndColumns('abcd'); eq(map.indexForLocation({ line: 0, column: 2 }), 2); }); it('maps line/column to the appropriate index', function() { const map = new LinesAndColumns('ab\ncd'); eq(map.indexForLocation({ line: 0, column: 2 }), 2); eq(map.indexForLocation({ line: 1, column: 0 }), 3); eq(map.indexForLocation({ line: 1, column: 2 }), 5); }); it('maps non-existent line to null', function() { const map = new LinesAndColumns('a\nb'); eq(map.indexForLocation({ line: -1, column: 0 }), null); eq(map.indexForLocation({ line: 2, column: 0 }), null); }); it('maps non-existent columns to null', function() { const map = new LinesAndColumns('a\nb'); eq(map.indexForLocation({ line: 0, column: 3 }), null); eq(map.indexForLocation({ line: 0, column: -1 }), null); }); it('handles carriage returns as newline characters', function() { const map = new LinesAndColumns('a\rb'); deq(map.locationForIndex(2), { line: 1, column: 0 }); deq(map.indexForLocation({ line: 1, column: 0 }), 2); }); it('handles joined carriage return line feeds as newlines', function() { const map = new LinesAndColumns('a\r\nb'); deq(map.locationForIndex(0), { line: 0, column: 0 }); deq(map.locationForIndex(1), { line: 0, column: 1 }); deq(map.locationForIndex(2), { line: 0, column: 2 }); deq(map.locationForIndex(3), { line: 1, column: 0 }); deq(map.indexForLocation({ line: 0, column: 0 }), 0); deq(map.indexForLocation({ line: 0, column: 1 }), 1); deq(map.indexForLocation({ line: 0, column: 2 }), 2); deq(map.indexForLocation({ line: 1, column: 0 }), 3); }); it('handles separate carriage returns and line feeds as independent newlines', function() { const map = new LinesAndColumns('a\rb\nc'); deq(map.locationForIndex(0), { line: 0, column: 0 }); deq(map.locationForIndex(1), { line: 0, column: 1 }); deq(map.locationForIndex(2), { line: 1, column: 0 }); deq(map.locationForIndex(3), { line: 1, column: 1 }); deq(map.locationForIndex(4), { line: 2, column: 0 }); deq(map.indexForLocation({ line: 0, column: 0 }), 0); deq(map.indexForLocation({ line: 0, column: 1 }), 1); deq(map.indexForLocation({ line: 1, column: 0 }), 2); deq(map.indexForLocation({ line: 1, column: 1 }), 3); deq(map.indexForLocation({ line: 2, column: 0 }), 4); }); }); lines-and-columns-1.1.6/tsconfig.json000066400000000000000000000006161302626530400175620ustar00rootroot00000000000000{ "compilerOptions": { "strictNullChecks": true, "module": "commonjs", "typeRoots": ["node_modules/@types"], "declaration": true, "lib": ["es2015"], "experimentalDecorators": true, "noUnusedParameters": true, "noUnusedLocals": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true }, "exclude": [ "node_modules", "dist/**/*" ] }lines-and-columns-1.1.6/tslint.json000066400000000000000000000017521302626530400172650ustar00rootroot00000000000000{ "rules": { "array-type": [true, "generic"], "no-unused-expression": true, "curly": true, "class-name": true, "semicolon": [true, "always"], "triple-equals": true, "new-parens": true, "ordered-imports": [true, {"import-sources-order": "case-insensitive", "named-imports-order": "lowercase-first"}], "no-any": true, "no-namespace": true, "no-internal-module": true, "no-var-requires": true, "no-var-keyword": true, "prefer-for-of": true, "typedef": [true, "parameter", "property-declaration"], "typedef-whitespace": [ true, { "call-signature": "nospace", "index-signature": "nospace", "parameter": "nospace", "property-declaration": "nospace", "variable-declaration": "nospace" }, { "call-signature": "space", "index-signature": "space", "parameter": "space", "property-declaration": "space", "variable-declaration": "space" } ] } }