flow-remove-types
Advanced tools
Comparing version 1.0.5 to 1.1.0
146
index.js
var babylon = require('babylon'); | ||
var vlq = require('vlq'); | ||
@@ -9,20 +10,54 @@ /** | ||
* | ||
* - checkPragma: (default: true) looks for an @flow pragma before parsing. | ||
* - all: (default: false) | ||
* If true, bypasses looking for an @flow pragma comment before parsing. | ||
* | ||
* - pretty: (default: false) | ||
* If true, removes types completely rather than replacing with spaces. | ||
* This may require using source maps. | ||
* | ||
* Returns an object with two methods: | ||
* | ||
* - .toString() | ||
* Returns the transformed source code. | ||
* | ||
* - .generateMap() | ||
* Returns a v3 source map. | ||
*/ | ||
module.exports = function flowRemoveTypes(source, options) { | ||
// Options | ||
var all = Boolean(options && options.all); | ||
if (options && options.checkPragma) { | ||
throw new Error( | ||
'flow-remove-types: the "checkPragma" option has been replaced by "all".' | ||
); | ||
} | ||
// If there's no @flow or @noflow flag, then expect no annotation. | ||
var pragmaStart = source.indexOf('@flow'); | ||
var pragmaEnd = pragmaStart + 5; | ||
var pragmaStart = source.indexOf('@' + 'flow'); | ||
var pragmaSize = 5; | ||
if (pragmaStart === -1) { | ||
pragmaStart = source.indexOf('@noflow'); | ||
pragmaEnd = pragmaStart + 7; | ||
if (pragmaStart === -1 && !(options && options.checkPragma === false)) { | ||
return source; | ||
pragmaStart = source.indexOf('@' + 'noflow'); | ||
pragmaSize = 7; | ||
if (pragmaStart === -1 && !all) { | ||
return resultPrinter(options, source); | ||
} | ||
} | ||
var removedNodes = pragmaStart === -1 ? | ||
[] : | ||
[ { start: pragmaStart, end: pragmaEnd } ]; | ||
var removedNodes = []; | ||
// Remove the flow pragma. | ||
if (pragmaStart !== -1) { | ||
var prePragmaLines = source.slice(0, pragmaStart).split('\n'); | ||
var pragmaLine = prePragmaLines.length; | ||
var pragmaCol = prePragmaLines[pragmaLine - 1].length; | ||
removedNodes.push({ | ||
start: pragmaStart, | ||
end: pragmaStart + pragmaSize, | ||
loc: { | ||
start: { line: pragmaLine, column: pragmaCol }, | ||
end: { line: pragmaLine, column: pragmaCol + pragmaSize } | ||
}, | ||
}) | ||
} | ||
// Babylon is one of the sources of truth for Flow syntax. This parse | ||
@@ -40,27 +75,48 @@ // configuration is intended to be as permissive as possible. | ||
if (removedNodes.length === 0) { | ||
return source; | ||
} | ||
return resultPrinter(options, source, removedNodes); | ||
} | ||
var result = ''; | ||
var lastPos = 0; | ||
function resultPrinter(options, source, removedNodes) { | ||
// Options | ||
var pretty = Boolean(options && options.pretty); | ||
// Step through the removed nodes, building up the resulting string. | ||
for (var i = 0; i < removedNodes.length; i++) { | ||
var node = removedNodes[i]; | ||
result += source.slice(lastPos, node.start); | ||
var toReplace = source.slice(node.start, node.end); | ||
lastPos = node.end; | ||
if (!node.loc || node.loc.start.line === node.loc.end.line) { | ||
result += space(toReplace.length); | ||
} else { | ||
var toReplaceLines = toReplace.split(LINE_RX); | ||
result += space(toReplaceLines[0].length); | ||
for (var j = 1; j < toReplaceLines.length; j += 2) { | ||
result += toReplaceLines[j] + space(toReplaceLines[j + 1].length); | ||
return { | ||
toString: function () { | ||
if (!removedNodes || removedNodes.length === 0) { | ||
return source; | ||
} | ||
var result = ''; | ||
var lastPos = 0; | ||
// Step through the removed nodes, building up the resulting string. | ||
for (var i = 0; i < removedNodes.length; i++) { | ||
var node = removedNodes[i]; | ||
result += source.slice(lastPos, node.start); | ||
lastPos = node.end; | ||
if (!pretty) { | ||
var toReplace = source.slice(node.start, node.end); | ||
if (!node.loc || node.loc.start.line === node.loc.end.line) { | ||
result += space(toReplace.length); | ||
} else { | ||
var toReplaceLines = toReplace.split(LINE_RX); | ||
result += space(toReplaceLines[0].length); | ||
for (var j = 1; j < toReplaceLines.length; j += 2) { | ||
result += toReplaceLines[j] + space(toReplaceLines[j + 1].length); | ||
} | ||
} | ||
} | ||
} | ||
return result += source.slice(lastPos); | ||
}, | ||
generateMap: function () { | ||
return { | ||
version: 3, | ||
sources: [ 'source.js' ], | ||
names: [], | ||
mappings: pretty ? generateSourceMappings(removedNodes) : '' | ||
}; | ||
} | ||
} | ||
return result += source.slice(lastPos); | ||
} | ||
@@ -226,1 +282,31 @@ | ||
} | ||
// Generate a source map when *removing* nodes rather than replacing them | ||
// with spaces. | ||
function generateSourceMappings(removedNodes) { | ||
var mappings = ''; | ||
var end = { line: 1, column: 0 }; | ||
for (var i = 0; i < removedNodes.length; i++) { | ||
var start = removedNodes[i].loc.start; | ||
var lineDiff = start.line - end.line; | ||
var columnDiff = start.column - end.column; | ||
if (lineDiff) { | ||
for (var l = 0; l !== lineDiff; l++) { | ||
mappings += ';'; | ||
} | ||
mappings += vlq.encode([ start.column, 0, lineDiff, columnDiff ]); | ||
} else if (columnDiff) { | ||
if (i) { | ||
mappings += ','; | ||
} | ||
mappings += vlq.encode([ columnDiff, 0, lineDiff, columnDiff ]); | ||
} | ||
end = removedNodes[i].loc.end; | ||
mappings += ','; | ||
mappings += vlq.encode([ 0, 0, end.line - start.line, end.column - start.column ]); | ||
} | ||
return mappings; | ||
} |
{ | ||
"name": "flow-remove-types", | ||
"version": "1.0.5", | ||
"version": "1.1.0", | ||
"description": "Removes Flow type annotations from JavaScript files with speed and simplicity.", | ||
@@ -12,2 +12,10 @@ "author": "Lee Byron <lee@leebyron.com> (http://leebyron.com/)", | ||
}, | ||
"files": [ | ||
"index.js", | ||
"register.js", | ||
"flow-remove-types", | ||
"flow-node", | ||
"LICENSE", | ||
"PATENTS" | ||
], | ||
"homepage": "https://github.com/leebyron/flow-remove-types", | ||
@@ -22,4 +30,4 @@ "bugs": { | ||
"scripts": { | ||
"test": "DIFF=$(./flow-remove-types test/source.js | diff test/expected.js -); if [ -n \"$DIFF\" ]; then echo \"$DIFF\"; exit 1; fi; RES=$(node -e 'require(\"./register\");require(\"./test/test-node-module.js\")'); if [ \"$RES\" != 42 ]; then echo 'Node register hook failed'; exit 1; fi; FLOW_NODE=$(./flow-node ./test/test-node-module.js); if [ \"$FLOW_NODE\" != 42 ]; then echo 'flow-node failed'; exit 1; fi;", | ||
"test-update": "./flow-remove-types test/source.js > test/expected.js" | ||
"test": "./test.sh", | ||
"test-update": "./test-update.sh" | ||
}, | ||
@@ -35,4 +43,5 @@ "keywords": [ | ||
"dependencies": { | ||
"babylon": "^6.8.4" | ||
"babylon": "^6.8.4", | ||
"vlq": "^0.2.1" | ||
} | ||
} |
@@ -49,3 +49,3 @@ flow-remove-types | ||
var output = flowRemoveTypes(input); | ||
fs.writeFileSync('output.js', output); | ||
fs.writeFileSync('output.js', output.toString()); | ||
``` | ||
@@ -56,7 +56,15 @@ | ||
**Rollup**: [`rollup-plugin-flow`](https://github.com/leebyron/rollup-plugin-flow) | ||
**Rollup:** [`rollup-plugin-flow`](https://github.com/leebyron/rollup-plugin-flow) | ||
**Browserify:** [`unflowify`](https://github.com/leebyron/unflowify) | ||
**Webpack:** [`remove-flow-types-loader`](https://github.com/conorhastings/remove-flow-types-loader) | ||
## Use with existing development tools | ||
* ESLint: [eslint-plugin-flowtype](https://github.com/gajus/eslint-plugin-flowtype) | ||
* Mocha: `mocha -r flow-remove-types/register` | ||
## Use `flow-node` | ||
@@ -79,3 +87,3 @@ | ||
Using the require hook allows you to automatically compile files on the fly when | ||
requiring in node: | ||
requiring in node, useful during development: | ||
@@ -87,3 +95,13 @@ ```js | ||
As always, don't forget to use `flow-remove-types` to compile files before | ||
distributing your code on npm, as using the require hook affects the whole | ||
runtime and not just your module. | ||
You can also provide options to the require hook: | ||
```js | ||
// Transforms all files, not just those with a "@flow" comment. | ||
require('flow-remove-types/register')({ all: true }) | ||
``` | ||
## Dead-Simple Transforms | ||
@@ -145,3 +163,24 @@ | ||
### Pretty Transform | ||
Rather not have the whitespace? Pass the `--pretty` flag to remove the whitespace. | ||
``` | ||
flow-remove-types --pretty source.js | ||
``` | ||
Or using the JS API: | ||
```js | ||
var flowRemoveTypes = require('flow-remove-types'); | ||
var fs = require('fs'); | ||
var input = fs.readFileSync('input.js', 'utf8'); | ||
var output = flowRemoveTypes(input, { pretty: true }); | ||
fs.writeFileSync('output.js', output.toString()); | ||
var sourceMap = output.generateMap(); | ||
fs.writeFileSync('output.js.map', JSON.stringify(sourceMap)); | ||
``` | ||
## Performance | ||
@@ -148,0 +187,0 @@ |
@@ -1,13 +0,26 @@ | ||
var Module = require('module'); | ||
var removeTypes = require('./index'); | ||
var flowRemoveTypes = require('./index'); | ||
// Rather than use require.extensions, swizzle Module#_compile. Not only does | ||
// this typically leverage the existing behavior of require.extensions['.js'], | ||
// but allows for use alongside other "require extension hook" if necessary. | ||
var super_compile = Module.prototype._compile; | ||
Module.prototype._compile = function _compile(source, filename) { | ||
var transformedSource = filename.indexOf('node_modules/') === -1 | ||
? removeTypes(source) | ||
: source; | ||
super_compile.call(this, transformedSource, filename); | ||
}; | ||
var options; | ||
module.exports = function setOptions(newOptions) { | ||
options = newOptions; | ||
} | ||
// Swizzle Module#_compile on each applicable module instance. | ||
// NOTE: if using alongside Babel or another require-hook which simply | ||
// over-writes the require.extensions and does not continue execution, then | ||
// this require hook must come after it. Encourage those module authors to call | ||
// the prior loader in their require hooks. | ||
var jsLoader = require.extensions['.js']; | ||
var exts = [ '.js', '.jsx', '.flow', '.es6' ]; | ||
exts.forEach(function (ext) { | ||
var superLoader = require.extensions[ext] || jsLoader; | ||
require.extensions[ext] = function (module, filename) { | ||
if (filename.indexOf('/node_modules/') === -1) { | ||
var super_compile = module._compile; | ||
module._compile = function _compile(code, filename) { | ||
super_compile.call(this, flowRemoveTypes(code, options).toString(), filename); | ||
}; | ||
} | ||
superLoader(module, filename); | ||
}; | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
29547
230
0
2
8
300
+ Addedvlq@^0.2.1
+ Addedvlq@0.2.3(transitive)