Comparing version 0.0.3 to 0.0.4
@@ -12,5 +12,5 @@ 'use strict'; | ||
this.stack = temp.stack; | ||
this.code = code; | ||
this.error = error; | ||
this.position = position; | ||
this.code = code; // One of parsingErrorCode values; | ||
this.error = error; // The main error message text; | ||
this.position = position; // Error position in the text: {line, column} | ||
this.message = "Error parsing SQL at {line:" + position.line + ",col:" + position.column + "}: " + error; | ||
@@ -17,0 +17,0 @@ } |
@@ -7,9 +7,10 @@ 'use strict'; | ||
//////////////////////////////////////////////// | ||
// Parses and minifies PostgreSQL query: | ||
// - removes all comments; | ||
// - replaces line breaks within strings with \n | ||
// - flattens result into a single line | ||
/////////////////////////////////////////// | ||
// Parses and minifies a PostgreSQL script. | ||
function minify(sql) { | ||
if (typeof sql !== 'string') { | ||
throw new TypeError("Input SQL must be a text string."); | ||
} | ||
if (!sql.length) { | ||
@@ -19,12 +20,23 @@ return ''; | ||
var idx = 0, // current index; | ||
s = '', // resulting code; | ||
len = sql.length, // sql length; | ||
emptyLine = true, // set while no symbols encountered on the current line; | ||
emptyLetters = '', // empty letters on a new line; | ||
EOL = getEOL(sql), // End-Of-Line. | ||
regLB = new RegExp(EOL, 'g'); | ||
var idx = 0, // current index | ||
result = '', // resulting sql | ||
len = sql.length, // sql length | ||
EOL = getEOL(sql), // End-Of-Line | ||
regLB = new RegExp(EOL, 'g'), | ||
space = false; | ||
do { | ||
if (sql[idx] === '-' && idx < len - 1 && sql[idx + 1] === '-') { | ||
var s = sql[idx], // current symbol; | ||
s1 = idx < len - 1 ? sql[idx + 1] : ''; // next symbol; | ||
if (isGap(s)) { | ||
while (++idx < len && isGap(sql[idx])); | ||
if (idx < len) { | ||
space = true; | ||
} | ||
idx--; | ||
continue; | ||
} | ||
if (s === '-' && s1 === '-') { | ||
var lb = sql.indexOf(EOL, idx + 2); | ||
@@ -34,11 +46,7 @@ if (lb < 0) { | ||
} | ||
if (emptyLine) { | ||
emptyLetters = ''; | ||
idx = lb + EOL.length - 1; // last symbol of the line break; | ||
} else { | ||
idx = lb - 1; // just before the line break; | ||
} | ||
idx = lb - 1; | ||
continue; | ||
} | ||
if (sql[idx] === '/' && idx < len - 1 && sql[idx + 1] === '*') { | ||
if (s === '/' && s1 === '*') { | ||
var end = sql.indexOf('*/', idx + 2); | ||
@@ -49,47 +57,17 @@ if (end < 0) { | ||
idx = end + 1; | ||
if (emptyLine) { | ||
emptyLetters = ''; | ||
} | ||
var lb = sql.indexOf(EOL, idx + 1); | ||
if (lb > idx) { | ||
var gapIdx = lb - 1; | ||
while ((sql[gapIdx] === ' ' || sql[gapIdx] === '\t') && --gapIdx > idx); | ||
if (emptyLine && gapIdx === idx) { | ||
idx = lb + EOL.length - 1; // last symbol of the line break; | ||
} | ||
} | ||
continue; | ||
} | ||
var symbol = sql[idx]; | ||
var isSpace = symbol === ' ' || symbol === '\t'; | ||
if (symbol === '\r' || symbol === '\n') { | ||
if (sql.indexOf(EOL, idx) === idx) { | ||
emptyLine = true; | ||
} | ||
} else { | ||
if (!isSpace) { | ||
emptyLine = false; | ||
s += emptyLetters; | ||
emptyLetters = ''; | ||
} | ||
} | ||
if (emptyLine && isSpace) { | ||
emptyLetters += symbol; | ||
} else { | ||
s += symbol; | ||
} | ||
if (symbol === '\'') { | ||
if (s === '\'') { | ||
var closeIdx = idx; | ||
do { | ||
closeIdx = sql.indexOf(symbol, closeIdx + 1); | ||
closeIdx = sql.indexOf('\'', closeIdx + 1); | ||
if (closeIdx > 0) { | ||
var shIdx = closeIdx; | ||
while (++shIdx < len && sql[shIdx] === '\''); | ||
if ((shIdx - closeIdx) % 2) { | ||
closeIdx = shIdx - 1; | ||
var step = closeIdx; | ||
while (++step < len && sql[step] === '\''); | ||
if ((step - closeIdx) % 2) { | ||
closeIdx = step - 1; | ||
break; | ||
} | ||
closeIdx = shIdx === len ? -1 : shIdx; | ||
closeIdx = step === len ? -1 : step; | ||
} | ||
@@ -100,16 +78,19 @@ } while (closeIdx > 0); | ||
} | ||
s += sql.substr(idx + 1, closeIdx - idx).replace(regLB, '\\n'); | ||
result += sql.substr(idx, closeIdx - idx + 1).replace(regLB, '\\n'); | ||
idx = closeIdx; | ||
continue; | ||
} | ||
if (space) { | ||
if (result.length) { | ||
result += ' '; | ||
} | ||
space = false; | ||
} | ||
result += s; | ||
} while (++idx < len); | ||
return s | ||
.split(EOL) | ||
.map(function (line) { | ||
return line.replace(/^(\s)+|(\s)+$/g, ''); | ||
}) | ||
.filter(function (line) { | ||
return line.length > 0; | ||
}).join(' '); | ||
return result; | ||
@@ -122,5 +103,4 @@ function throwError(code, error) { | ||
//////////////////////////////////////// | ||
// Automatically determines and returns | ||
// the type of End-of-Line in the text. | ||
////////////////////////////////////// | ||
// Returns the End-Of-Line from text. | ||
function getEOL(text) { | ||
@@ -147,3 +127,3 @@ var idx = 0, unix = 0, windows = 0; | ||
/////////////////////////////////////////////////////// | ||
// Returns {line, column} of the index within the text | ||
// Returns {line, column} of an index within the text. | ||
function getIndexPos(text, index, eol) { | ||
@@ -177,2 +157,8 @@ var line = 1, col = 1, pos = 0; | ||
//////////////////////////////////// | ||
// Identifies a gap / empty symbol. | ||
function isGap(s) { | ||
return s === ' ' || s === '\t' || s === '\r' || s === '\n'; | ||
} | ||
module.exports = { | ||
@@ -179,0 +165,0 @@ minify: minify, |
{ | ||
"name": "pg-minify", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "Minifies PostgreSQL scripts.", | ||
@@ -25,3 +25,4 @@ "main": "lib/index.js", | ||
"keywords": [ | ||
"minify SQL" | ||
"minify SQL", | ||
"uglify SQL" | ||
], | ||
@@ -28,0 +29,0 @@ "author": { |
pg-minify | ||
========= | ||
Minifies PostgreSQL scripts. | ||
[![Build Status](https://travis-ci.org/vitaly-t/pg-minify.svg?branch=master)](https://travis-ci.org/vitaly-t/pg-minify) | ||
@@ -13,3 +11,3 @@ [![Coverage Status](https://coveralls.io/repos/vitaly-t/pg-minify/badge.svg?branch=master)](https://coveralls.io/r/vitaly-t/pg-minify?branch=master) | ||
2. Concatenates multi-line strings into single-line with `\n` | ||
3. Removes all redundant gaps: line breaks, tabs and spaces | ||
3. Removes redundant line gaps: line breaks, tabs and spaces | ||
4. Flattens the resulting script into a single line | ||
@@ -41,3 +39,3 @@ | ||
var sql = 'SELECT 1; -- comments'; | ||
var sql = "SELECT 1; -- comments"; | ||
@@ -47,2 +45,16 @@ minify(sql); //=> SELECT 1; | ||
#### Error Handling | ||
[SQLParsingError] is thrown on failed SQL parsing. | ||
```js | ||
try { | ||
minify("SELECT '1"); | ||
} catch (error) { | ||
// error is minify.SQLParsingError instance | ||
// error.message: | ||
// Error parsing SQL at {line:1,col:7}: Unclosed text block. | ||
} | ||
``` | ||
## License | ||
@@ -52,1 +64,3 @@ | ||
Released under the MIT license. | ||
[SQLParsingError]:https://github.com/vitaly-t/pg-minify/blob/master/lib/error.js#L8 |
@@ -56,2 +56,12 @@ 'use strict'; | ||
describe("redundant gaps", function () { | ||
it("must be all replaced with a single space", function () { | ||
expect(minify("a b")).toBe("a b"); | ||
expect(minify(" a b ")).toBe("a b"); | ||
expect(minify("a\tb")).toBe("a b"); | ||
expect(minify("\ta\t\tb\t")).toBe("a b"); | ||
expect(minify("a - b")).toBe("a - b"); | ||
}); | ||
}); | ||
describe("with multiple lines", function () { | ||
@@ -67,5 +77,7 @@ it("must be ignored", function () { | ||
expect(minify("/*start" + LB + "end*/" + LB + "text")).toBe("text"); | ||
expect(minify(" /*hello*/ " + LB + "next")).toBe("next"); | ||
}); | ||
}); | ||
}); | ||
@@ -75,2 +87,14 @@ | ||
describe("passing non-text", function () { | ||
var errMsg = "Input SQL must be a text string."; | ||
it("must throw an error", function () { | ||
expect(function () { | ||
minify(); | ||
}).toThrow(new TypeError(errMsg)); | ||
expect(function () { | ||
minify(123); | ||
}).toThrow(new TypeError(errMsg)); | ||
}); | ||
}); | ||
describe("quotes in strings", function () { | ||
@@ -84,2 +108,6 @@ var errMsg = "Error parsing SQL at {line:1,col:1}: Unclosed text block."; | ||
expect(function () { | ||
minify("''' "); | ||
}).toThrow(errMsg); | ||
expect(function () { | ||
minify("'''"); | ||
@@ -86,0 +114,0 @@ }).toThrow(errMsg); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14076
327
63