code-error-fragment
Advanced tools
| [*] | ||
| charset = utf-8 | ||
| indent_style = tab | ||
| indent_size = 4 | ||
| [package.json] | ||
| indent_style = space | ||
| indent_size = 2 |
Sorry, the diff of this file is not supported yet
| export default (string, targetLength, padString) => { | ||
| if (String.prototype.padStart) { | ||
| return string.padStart(targetLength, padString); | ||
| } | ||
| targetLength = targetLength >> 0; // Floor if number or convert non-number to 0; | ||
| padString = String(padString || ' '); | ||
| if (string.length > targetLength) { | ||
| return String(string); | ||
| } else { | ||
| targetLength = targetLength - string.length; | ||
| if (targetLength > padString.length) { | ||
| padString += padString.repeat(targetLength / padString.length); // Append to original to ensure we are longer than needed | ||
| } | ||
| return padString.slice(0, targetLength) + String(string); | ||
| } | ||
| } |
+37
| import padStart from './helpers/pad-start.js'; | ||
| function printLine(line, position, maxNumLength, settings) { | ||
| const num = String(position); | ||
| const formattedNum = padStart(num, maxNumLength, ' '); | ||
| return formattedNum + ' | ' + line.replace(/\t/g, ' '.repeat(settings.tabSize)); | ||
| } | ||
| function printLines(lines, start, end, maxNumLength, settings) { | ||
| return lines | ||
| .slice(start, end) | ||
| .map((line, i) => printLine(line, start + i + 1, maxNumLength, settings)) | ||
| .join('\n'); | ||
| } | ||
| const defaultSettings = { | ||
| extraLines: 2, | ||
| tabSize: 4 | ||
| }; | ||
| export default (input, linePos, columnPos, settings) => { | ||
| settings = { ...defaultSettings, ...settings }; | ||
| const lines = input.split(/\r\n?|\n|\f/); | ||
| const startLinePos = Math.max(1, linePos - settings.extraLines) - 1; | ||
| const endLinePos = Math.min(linePos + settings.extraLines, lines.length); | ||
| const maxNumLength = String(endLinePos).length; | ||
| const prevLines = printLines(lines, startLinePos, linePos, maxNumLength, settings); | ||
| const targetLineBeforeCursor = printLine(lines[linePos - 1].substring(0, columnPos - 1), linePos, maxNumLength, settings); | ||
| const cursorLine = ' '.repeat(targetLineBeforeCursor.length) + '^'; | ||
| const nextLines = printLines(lines, linePos, endLinePos, maxNumLength, settings); | ||
| return [prevLines, cursorLine, nextLines] | ||
| .filter(Boolean) | ||
| .join('\n'); | ||
| } |
| import babel from 'rollup-plugin-babel'; | ||
| import { list as babelHelpersList } from 'babel-helpers'; | ||
| export default { | ||
| input: 'index.js', | ||
| name: 'codeErrorFragment', | ||
| output: { | ||
| file: 'build.js', | ||
| format: 'umd' | ||
| }, | ||
| plugins: [ | ||
| babel({ | ||
| exclude: 'node_modules/**', | ||
| presets: [ | ||
| ['es2015', { | ||
| modules: false | ||
| }], | ||
| 'stage-3' | ||
| ], | ||
| plugins: [ | ||
| 'external-helpers' | ||
| ], | ||
| // fixing temporary rollup's regression, remove when https://github.com/rollup/rollup/issues/1595 gets solved | ||
| externalHelpersWhitelist: babelHelpersList.filter(helperName => helperName !== 'asyncGenerator'), | ||
| }) | ||
| ], | ||
| watch: { | ||
| include: '*.js', | ||
| exclude: 'node_modules/**' | ||
| } | ||
| } |
| var TYPE = { | ||
| PLAIN_PARAM: 'PLAIN_PARAM', | ||
| ANY_PARAM: 'ANY_PARAM', | ||
| WORD: 'WORD', | ||
| GROUP: 'GROUP', | ||
| GROUP_OPTION: 'GROUP_OPTION' | ||
| }; | ||
| function parsePath(route){ | ||
| var value = String(route || ''); | ||
| var params = []; | ||
| function findWord(offset){ | ||
| return value.substr(offset).match(/^\w+/); | ||
| } | ||
| function getOption(i) { | ||
| return parse(i + 1, ')', '|'); | ||
| } | ||
| function getGroup(i) { | ||
| var res; | ||
| var result = ''; | ||
| var options = []; | ||
| while (res = getOption(i)) { | ||
| options.push({ | ||
| type: TYPE.GROUP_OPTION, | ||
| children: res.ast | ||
| }); | ||
| i = res.offset; | ||
| result += res.result; | ||
| if (res.stoppedAt == ')') | ||
| { | ||
| return { | ||
| type: TYPE.GROUP, | ||
| options: options, | ||
| result: result, | ||
| offset: i | ||
| }; | ||
| } | ||
| else | ||
| { | ||
| result += '|'; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function parse(offset, stopChar, anotherStopChar){ | ||
| var result = ''; | ||
| var res; | ||
| var curWord = ''; | ||
| var ast = []; | ||
| function putCurrentWord() { | ||
| if (curWord) | ||
| { | ||
| ast.push({ | ||
| type: TYPE.WORD, | ||
| name: curWord | ||
| }); | ||
| curWord = ''; | ||
| } | ||
| } | ||
| for (var i = offset; i < value.length; i++) | ||
| { | ||
| var c = value.charAt(i); | ||
| switch (c) | ||
| { | ||
| case stopChar: | ||
| case anotherStopChar: | ||
| putCurrentWord(); | ||
| return { | ||
| result: result, | ||
| offset: i, | ||
| stoppedAt: c, | ||
| ast: ast | ||
| }; | ||
| case '\\': | ||
| var nextChar = value.charAt(++i); | ||
| result += '\\' + nextChar; | ||
| curWord += nextChar; | ||
| break; | ||
| case '|': // allow | inside braces | ||
| result += stopChar != ')' ? '\\|' : '|'; | ||
| curWord += '|'; | ||
| break; | ||
| case '(': // optional: (something) -> (?:something)? | ||
| if (res = getGroup(i)) | ||
| { | ||
| i = res.offset; | ||
| result += '(?:' + res.result + ')?'; | ||
| putCurrentWord(); | ||
| ast.push({ | ||
| type: TYPE.GROUP, | ||
| options: res.options | ||
| }); | ||
| } | ||
| else | ||
| { | ||
| result += '\\('; | ||
| curWord += '('; | ||
| } | ||
| break; | ||
| case ':': // named: :name -> ([^/]+) | ||
| putCurrentWord(); | ||
| if (res = findWord(i + 1)) | ||
| { | ||
| i += res[0].length; | ||
| result += '([^\/]+)'; | ||
| params.push(res[0]); | ||
| ast.push({ | ||
| type: TYPE.PLAIN_PARAM, | ||
| name: res[0] | ||
| }); | ||
| } | ||
| else | ||
| { | ||
| result += ':'; | ||
| } | ||
| break; | ||
| case '*': // splat: *name -> (.*?) | ||
| putCurrentWord(); | ||
| if (res = findWord(i + 1)) | ||
| { | ||
| i += res[0].length; | ||
| result += '(.*?)'; | ||
| params.push(res[0]); | ||
| ast.push({ | ||
| type: TYPE.ANY_PARAM, | ||
| name: res[0] | ||
| }); | ||
| } | ||
| else | ||
| { | ||
| result += '\\*'; | ||
| } | ||
| break; | ||
| default: | ||
| result += basis.string.forRegExp(c); | ||
| curWord += c; | ||
| } | ||
| } | ||
| putCurrentWord(); | ||
| return stopChar ? null : { | ||
| regexpStr: result, | ||
| ast: ast | ||
| }; | ||
| } | ||
| var parsingResult = parse(0); | ||
| var regexp = new RegExp('^' + parsingResult.regexpStr + '$', 'i'); | ||
| return { | ||
| path: route, | ||
| regexp: regexp, | ||
| params: params, | ||
| ast: parsingResult.ast | ||
| }; | ||
| } | ||
| function stringifyGroup(group, values, areModified) { | ||
| var defaultResult = null; | ||
| for (var i = 0; i < group.options.length; i++) { | ||
| var option = group.options[i]; | ||
| var stringifiedOption = stringifyNodes(option.children, values, areModified, true); | ||
| if (stringifiedOption.modifiedParamsWritten) | ||
| return stringifiedOption; | ||
| else if (!defaultResult) | ||
| defaultResult = stringifiedOption; | ||
| } | ||
| return defaultResult; | ||
| } | ||
| function stringifyNodes(nodes, values, areModified) { | ||
| // Part of string complying to default params, | ||
| // which should be written if they precede a modified one | ||
| var trailingDefaults = ''; | ||
| var result = ''; | ||
| var modifiedParamsWritten = null; | ||
| function markAsWritten(paramName) { | ||
| if (!modifiedParamsWritten) | ||
| modifiedParamsWritten = {}; | ||
| modifiedParamsWritten[paramName] = true; | ||
| } | ||
| function append(value) { | ||
| result += trailingDefaults + value; | ||
| trailingDefaults = ''; | ||
| } | ||
| nodes.forEach(function(node){ | ||
| switch (node.type) { | ||
| case TYPE.WORD: | ||
| append(node.name); | ||
| break; | ||
| case TYPE.PLAIN_PARAM: | ||
| case TYPE.ANY_PARAM: | ||
| append(encodeURIComponent(values[node.name])); | ||
| if (areModified[node.name]) | ||
| markAsWritten(node.name); | ||
| break; | ||
| case TYPE.GROUP: | ||
| var groupStringifyResult = stringifyGroup(node, values, areModified); | ||
| if (groupStringifyResult.modifiedParamsWritten) | ||
| { | ||
| append(groupStringifyResult.result); | ||
| basis.object.iterate(groupStringifyResult.modifiedParamsWritten, markAsWritten); | ||
| } | ||
| else | ||
| { | ||
| trailingDefaults += groupStringifyResult.result; | ||
| } | ||
| break; | ||
| } | ||
| }); | ||
| return { | ||
| result: result, | ||
| modifiedParamsWritten: modifiedParamsWritten | ||
| }; | ||
| } | ||
| function stringify(nodes, values, areModified) { | ||
| var stringifyPathResult = stringifyNodes.apply(this, arguments); | ||
| var modifiedParamsWritten = stringifyPathResult.modifiedParamsWritten; | ||
| var result = stringifyPathResult.result; | ||
| var query = []; | ||
| basis.object.iterate(values, function(key, value){ | ||
| if (modifiedParamsWritten && modifiedParamsWritten[key]) | ||
| return; | ||
| if (!areModified[key]) | ||
| return; | ||
| query.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); | ||
| }); | ||
| if (query.length) | ||
| result += '?' + query.join('&'); | ||
| return result; | ||
| } | ||
| module.exports = { | ||
| parsePath: parsePath, | ||
| stringify: stringify, | ||
| TYPE: TYPE | ||
| }; |
| 246 | var query = []; | ||
| 247 | | ||
| 248 | basis.object.iterate(values, function(key, value){ | ||
| ^ | ||
| 249 | if (modifiedParamsWritten && modifiedParamsWritten[key]) | ||
| 250 | return; |
| module.exports = { | ||
| line: 248, | ||
| column: 21 | ||
| }; |
| let fs = require('fs'); | ||
| let path = require('path'); | ||
| let assert = require('assert'); | ||
| let codeErrorFragment = require('../build'); | ||
| function readFile(file) { | ||
| let src = fs.readFileSync(file, 'utf8'); | ||
| // normalize line endings | ||
| src = src.replace(/\r\n/, '\n'); | ||
| // remove trailing newline | ||
| src = src.replace(/\n$/, ''); | ||
| return src; | ||
| } | ||
| const folderPath = path.join(__dirname, 'fixtures'); | ||
| describe('Test', () => { | ||
| fs.readdirSync(folderPath).forEach(fileName => { | ||
| const fixtureIndexOf = fileName.indexOf('.input'); | ||
| if (fixtureIndexOf === -1) { | ||
| return; | ||
| } | ||
| const fixtureName = fileName.substring(0, fixtureIndexOf); | ||
| it(fixtureName, () => { | ||
| const input = readFile(path.join(folderPath, fileName)); | ||
| const params = require(path.join(folderPath, fixtureName + '.params.js')); | ||
| const output = readFile(path.join(folderPath, fixtureName + '.output.txt')); | ||
| const expectedOutput = codeErrorFragment(input, params.line, params.column); | ||
| assert.deepEqual(expectedOutput, output, 'is valid'); | ||
| }); | ||
| }); | ||
| }); |
+18
-24
@@ -7,21 +7,3 @@ (function (global, factory) { | ||
| var babelHelpers = {}; | ||
| babelHelpers._extends = Object.assign || function (target) { | ||
| for (var i = 1; i < arguments.length; i++) { | ||
| var source = arguments[i]; | ||
| for (var key in source) { | ||
| if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
| target[key] = source[key]; | ||
| } | ||
| } | ||
| } | ||
| return target; | ||
| }; | ||
| 'use strict'; | ||
| var padStart = function (string, targetLength, padString) { | ||
| var padStart = (function (string, targetLength, padString) { | ||
| if (String.prototype.padStart) { | ||
@@ -43,6 +25,18 @@ return string.padStart(targetLength, padString); | ||
| } | ||
| }); | ||
| var _extends = Object.assign || function (target) { | ||
| for (var i = 1; i < arguments.length; i++) { | ||
| var source = arguments[i]; | ||
| for (var key in source) { | ||
| if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
| target[key] = source[key]; | ||
| } | ||
| } | ||
| } | ||
| return target; | ||
| }; | ||
| 'use strict'; | ||
| function printLine(line, position, maxNumLength, settings) { | ||
@@ -66,4 +60,4 @@ var num = String(position); | ||
| var index = function (input, linePos, columnPos, settings) { | ||
| settings = babelHelpers._extends({}, defaultSettings, settings); | ||
| var index = (function (input, linePos, columnPos, settings) { | ||
| settings = _extends({}, defaultSettings, settings); | ||
@@ -80,3 +74,3 @@ var lines = input.split(/\r\n?|\n|\f/); | ||
| return [prevLines, cursorLine, nextLines].filter(Boolean).join('\n'); | ||
| }; | ||
| }); | ||
@@ -83,0 +77,0 @@ return index; |
+10
-10
| { | ||
| "name": "code-error-fragment", | ||
| "version": "0.0.1", | ||
| "version": "0.0.2", | ||
| "author": "Vlad Trushin", | ||
| "homepage": "https://github.com/vtrushin/code-error-fragment", | ||
| "description": "Shows code error fragment of input file", | ||
| "repository": "vtrushin/pretty-code-errors", | ||
| "repository": "vtrushin/code-error-fragment", | ||
| "maintainers": [ | ||
@@ -16,21 +16,21 @@ { | ||
| "main": "build.js", | ||
| "jsnext:main": "index", | ||
| "devDependencies": { | ||
| "babel-core": "^6.26.0", | ||
| "babel-helpers": "^6.24.1", | ||
| "babel-plugin-external-helpers": "^6.22.0", | ||
| "babel-preset-es2015": "^6.24.1", | ||
| "babel-preset-stage-3": "^6.24.1", | ||
| "coveralls": "^3.0.0", | ||
| "mocha": "^4.0.1", | ||
| "rollup": "^0.50.0", | ||
| "rollup-plugin-babel": "^1.0.0" | ||
| "rollup-plugin-babel": "^3.0.2" | ||
| }, | ||
| "scripts": { | ||
| "test": "mocha", | ||
| "build": "rollup --config rollup.config.js", | ||
| "watch": "rollup --config rollup.config.js --watch", | ||
| "build": "rollup -c", | ||
| "watch": "rollup -c -w", | ||
| "prepublish": "npm run build" | ||
| }, | ||
| "files": [ | ||
| "build.js", | ||
| "LICENSE", | ||
| "readme.md" | ||
| ], | ||
| "license": "MIT" | ||
| } |
+1
-1
@@ -1,2 +0,2 @@ | ||
| # Pretty code errors | ||
| # Code error fragment | ||
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
13815
203.69%13
225%394
525.4%9
80%4
300%1
Infinity%