[Pkg-javascript-commits] [node-srs] 01/01: Imported Upstream version 0.4.8+dfsg

Jérémy Lal kapouer at moszumanska.debian.org
Sun Jun 21 19:32:41 UTC 2015


This is an automated email from the git hooks/post-receive script.

kapouer pushed a commit to branch upstream
in repository node-srs.

commit 5e1eb8d099109f530e1962b45b4d384ff27aa4c7
Author: Jérémy Lal <kapouer at melix.org>
Date:   Sun Jun 21 16:02:01 2015 +0200

    Imported Upstream version 0.4.8+dfsg
---
 .gitignore                                       |   4 +-
 .npmignore                                       |   8 +-
 .travis.yml                                      |  54 +++++
 CHANGELOG.md                                     |  90 ++++++++
 Makefile                                         |  45 ++--
 README.md                                        |  79 ++++---
 appveyor.yml                                     |  84 ++++++++
 binding.gyp                                      |  83 ++++++--
 common.gypi                                      |  72 +++++--
 gen_settings.py                                  |  17 ++
 lib/constants.js                                 |  86 ++++++++
 lib/srs.js                                       | 257 +++++++++--------------
 package.json                                     |  66 ++++--
 scripts/package_osx.sh                           |  36 ++++
 src/_srs.cc                                      | 217 -------------------
 src/srs.cc                                       | 175 +++++++++++++++
 test/data/transverse_merc_kasey.prj              |   1 +
 test/data/transverse_merc_kasey_custom_grids.prj |   1 +
 test/esri_variant.test.js                        |  14 ++
 test/geojson.test.js                             |  18 +-
 test/invalid.test.js                             |  28 +++
 test/qgis-qpj.test.js                            |  20 ++
 test/shapefile.27700.test.js                     |  22 +-
 test/shapefile.3857.test.js                      |   8 +-
 test/shapefile.4326.test.js                      |  80 +------
 test/split_proj.js                               |  13 ++
 test/util.js                                     |  15 ++
 test/version.test.js                             |   5 +-
 vcbuild-2014.bat                                 |   2 +
 vcbuild.bat                                      |  17 +-
 30 files changed, 1016 insertions(+), 601 deletions(-)

diff --git a/.gitignore b/.gitignore
index 023f3ef..c022933 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,8 +2,6 @@ build
 .DS_Store
 *.o
 *.a
-lib/settings.js
-lib/_srs.node
+lib/binding
 *pyc
-.sconsign.dblite
 node_modules
\ No newline at end of file
diff --git a/.npmignore b/.npmignore
index e93c91b..c022933 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1 +1,7 @@
-gyp
\ No newline at end of file
+build
+.DS_Store
+*.o
+*.a
+lib/binding
+*pyc
+node_modules
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..4a7cb5e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,54 @@
+language: cpp
+
+os:
+  - linux
+  - osx
+
+compiler:
+  - clang
+
+env:
+  matrix:
+   - NODE_VERSION="0.10.38" JOBS=8
+   - NODE_VERSION="0.12.2" JOBS=8
+   - NODE_VERSION="iojs-v2.0.0" JOBS=8
+  global:
+   - secure: J5pbPr7g29oKVLrGpKXUQQUV5TJpMf2/TkPZZXezZdO5ywR7M2PfFOUOqexKUylcLyLmEgDilSJhhTLHYz+wx42VPbCTB7Q3sSZdhM0RUXc5mO4BcRKoEUHkIy2Ibp6SbcfzupT/oELFLiZSiS2xojldVMoUAs8IzLGcYStO7Jc=
+   - secure: 1cPR5S+Gg4JiA3j8cvjKxSY3AshM0inXzHB/i/7P/ZjnxdvQQuZ48lK0e3TFvXQVTbA0rWYYrwuo62Fb9fc9bA8hDoOU2aruoF6hcEyuAbG7ERGRRJO9g6XaZKW1G0yK18T+1X6OBP7eXNZEPxl0OqBL8l3MKO3vuGxR3+5VQ0A=
+
+before_install:
+ - COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
+ - echo $COMMIT_MESSAGE
+ - export PATH=`pwd`/node_modules/.bin:$PATH
+ # here we set up the node version on the fly based on the matrix value.
+ # This is done manually so that it is easy to flip the 'language' to
+ # objective-c in another branch (to run the same travis.yml on OS X)
+ - rm -rf ~/.nvm && git clone --depth 1 https://github.com/creationix/nvm.git ~/.nvm
+ - source ~/.nvm/nvm.sh
+ - nvm install $NODE_VERSION
+ - nvm use $NODE_VERSION
+ - node --version
+ - npm --version
+ - platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/")
+
+install:
+ # test building from source
+ - npm install --build-from-source --clang=1
+ - node-pre-gyp package testpackage
+ - npm test
+
+before_script:
+ # test publishing and installing from remote if
+ # [publish binary] is present in commit message
+ - echo "before_script"
+ - PUBLISH_BINARY=false
+ - echo $COMMIT_MESSAGE
+ - if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then echo yes;PUBLISH_BINARY=true; fi;
+ - echo $PUBLISH_BINARY
+ - if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp unpublish publish info; rm -rf {build,lib/binding}; npm install --fallback-to-build=false; npm test; fi
+
+script:
+ # test building with against shared gdal
+ - rm -rf ./build
+ - rm -rf ./lib/binding
+ - if [[ "$platform" == 'linux' ]]; then sudo apt-get -qq update; sudo apt-get --force-yes -qq install libgdal-dev libgdal1-dev libgdal1h=1.10.0-1~precise1; npm install --build-from-source --shared_gdal --clang=1; npm test; fi;
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55d864d..cfecbd5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,95 @@
 # changelog
 
+0.4.8
+
+ - Upgraded to nan at 1.8.4
+ - Upgraded to node-pre-gyp at 0.6.7
+
+0.4.7
+
+ - Added support (and pre-build binaries) for io.js 1.2.x and node v0.12.x
+ - Upgraded to nan at 1.7.0
+ - Upgraded to node-pre-gyp at 0.6.4
+
+0.4.6
+
+ - Removed getenv workaround for Visual Studio 2013
+
+0.4.5
+
+ - Upgraded bundled node-pre-gyp
+
+0.4.4
+
+ - Upgraded to GDAL 1.11.1
+ - Stopped providing binaries for node v0.8.x
+ - Now providing binaries against Visual Studio 2014 (pass --toolset=v140) and use binaries from https://github.com/mapbox/node-cpp11
+
+0.4.3
+
+ - No changes: just re-published to try to avoid npm shasum error upon download
+
+0.4.2
+
+ - Now supporting node v0.11.x
+
+0.4.1
+
+ - Now shipping binaries for OS X, Windows, and Ubuntu Linux
+
+0.4.0
+
+ - Now builds on FreeBSD
+ - `srs.jsonCrs` added for detecting projection inside JSON object representing GeoJSON. Pass the result to `srs.parse`
+ - `srs.parse` no longer supports being passed a filepath to a GeoJSON.
+
+0.3.12
+
+ - Fixed generation of valid `srs_settings.js` on windows (#39)
+ - Fixed detection of some ESRI variant projections (#38)
+ - Added preliminary appveyor.yml for continuous builds on windows
+
+0.3.11
+
+ - Removed binary stripping on OS X which may cause link problems on mavericks
+ - Move to Mapbox organization
+
+0.3.10
+
+ - Improved support for topojson
+
+0.3.9
+
+ - `--runtime_link` option fixed to only apply when `--shared_gdal` is passed.
+
+0.3.8
+
+ - Build fixes for windows
+
+0.3.7
+
+ - Build fix for python3 (#33)
+
+0.3.6
+
+ - Build fixes to avoid possible undefined symbol errors are runtime on ubuntu linux
+ - Additional travis.ci testing of 32bit builds
+
+0.3.5
+
+ - Minor test fixes to work with variable external gdal versions
+
+0.3.4
+
+ - Changed name of build option to configure against shared gdal lib. Now pass `npm install --shared_gdal` (to be consistent with older node-srs).
+
+0.3.3
+
+ - Now building against internal `osr` again by default. Pass `npm install --gdal=shared` to build against systemwide GDAL (#30)
+ - Now forcing canonical wgs84/epsg:4326 represenation
+ - Now translating `+init` syntax to `+proj` for known projections (epsg:4326 and epsg:3857)
+ - Various fixes to detect more projections
+
 0.3.2
 
  - Re-enabled optional linking with `gdal-config --dep-libs` by passing `npm install --runtime_link=static`
diff --git a/Makefile b/Makefile
index 0a23d0c..c844493 100755
--- a/Makefile
+++ b/Makefile
@@ -1,28 +1,39 @@
-all: srs.node
+#http://www.gnu.org/prep/standards/html_node/Standard-Targets.html#Standard-Targets
 
-NPROCS:=1
-OS:=$(shell uname -s)
+all: build
 
-ifeq ($(OS),Linux)
-	NPROCS:=$(shell grep -c ^processor /proc/cpuinfo)
-endif
-ifeq ($(OS),Darwin)
-	NPROCS:=$(shell sysctl -n hw.ncpu)
-endif
+./node_modules:
+	npm install --build-from-source
+
+build: ./node_modules
+	./node_modules/.bin/node-pre-gyp build --loglevel=error
 
-srs.node:
-	`npm explore npm -g -- pwd`/bin/node-gyp-bin/node-gyp build
+debug:
+	./node_modules/.bin/node-pre-gyp rebuild --debug
+
+verbose:
+	./node_modules/.bin/node-pre-gyp rebuild --loglevel=verbose
 
 clean:
-	rm -rf build
-	rm -f lib/_srs.node
+	@rm -rf ./build
+	rm -rf lib/binding/
+	rm -rf ./node_modules/
+
+grind:
+	valgrind --leak-check=full node node_modules/.bin/_mocha
 
+rebuild:
+	@make clean
+	@make
+
+ifndef only
 test:
 	@PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec
+else
+test:
+	@PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec test/${only}.test.js
+endif
 
 check: test
 
-lint:
-	@jshint lib/*js test/*js --config=jshint.json
-
-.PHONY: test
+.PHONY: test clean build
diff --git a/README.md b/README.md
index 9c73be7..26a4a72 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,26 @@
-
 # Node-Srs
-      
-  Bindings to libosr for handling spatial references in [node](http://nodejs.org).
+
+Linux: [![Build Status](https://secure.travis-ci.org/mapbox/node-srs.svg)](http://travis-ci.org/mapbox/node-srs)
+
+Windows: [![Build status](https://ci.appveyor.com/api/projects/status/ff1n3h7h506i4vx0)](https://ci.appveyor.com/project/Mapbox/node-srs)
+
+This module tries to detect projections, also known as "spatial reference systems". It works similiarly to [gdalsrsinfo](http://www.gdal.org/gdalsrsinfo.html).
+
+`node-srs` supports parsing a variety of textual representations of projections, like the formats known as `OGC WKT`, `ESRI WKT`, `OGC CRS URN`, or `proj4`. It supports [shapefiles](http://en.wikipedia.org/wiki/Shapefile) and [GeoJSON](http://geojson.org/). Shapefiles optionally come with a separate .prj and inside the `.prj` the text is usually in the `ESRI WKT` format. GeoJSON optionally contains a `crs` property that declares projection as `OGC CRS URN`.
+
+Detecting projections is important for applications like TileMill, which - through Mapnik - needs the `proj4` representation of a projection to create coordinate transformations for re-projecting vector or raster data on the fly.
+
+`node-srs` includes a variety of hacks to determine if your projection looks like `web mercator` (epsg:3857) or `wgs84` (epsg:4326) and if so returns the canonical representations of these projections (according to @springmeyer). This ensures applications like TileMill can avoid unneeded projection. It is common for data out in the wild in web mercator projection to store slightly different projection strings based on the software that created the files. `node-srs` ensures a consistent f [...]
+
+`node-srs` does not support looking for, or detecting, projection information in formats like GeoTIFF, PostGIS, or SQLite. Rather for those formats you would need to extract the projection information yourself and then pass it to `node-srs`.
+
+## API
+
+### `srs.parse(string)`
+
+Parse a string of projection specification data and return an object describing
+the detected projection. If the SRS cannot be parsed, throws a `TypeError`
+describing the issue.
 
 ## Example
 
@@ -38,43 +57,33 @@ Detect a WKT string as WGS84:
 
 ## Depends
 
-  node >= 0.2.4 (development headers)
-  
-  No other required dependencies
-  
-  Optionally can depend/dynamically link to libgdal by doing:
+ - Node >= 0.6.13 (development headers)
+ - No other required dependencies (though can optionally depend on external `libgdal`)
 
-      ./configure --shared-gdal
-      make
+## Installation
 
-  or:
+Install from binary:
 
-      export NODE_SRS_SHARED_GDAL=1
-      npm install srs
+    npm install
 
+Install from source:
 
-## Installation
-  
-  Install node-srs:
-  
-  From source:
-  
-    $ git clone git://github.com/springmeyer/node-srs.git
-    $ cd node-srs
-    $ ./configure
-    $ make
-    $ sudo make install
-    $ make test
-
-  Make sure the node modules is on your path:
-  
-    export NODE_PATH=/usr/local/lib/node/
-
-  Or you can install via npm:
-  
-    $ npm install srs
-  
+    npm install --build-from-source
+
+From source:
+
+    git clone git://github.com/mapbox/node-srs.git
+    cd node-srs
+    npm install
+
+Against external libgdal (avoids compiling internal copy of libosr)
+
+    npm install --build-from-source --shared_gdal
+
+## Test
+
+    npm test
 
 ## License
 
-  BSD, see LICENSE.txt
\ No newline at end of file
+  BSD, see LICENSE.txt
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..a8a7a70
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,84 @@
+environment:
+  node_pre_gyp_accessKeyId:
+    secure: 7DrSVc5eIGtmMcki5H+iRft+Tk3MJTwDBQEUuJHWaQ4=
+  node_pre_gyp_secretAccessKey:
+    secure: 1amwJJw9fu0j6dXnc5KsAQbSYf7Cjw/dapT6OZWABa6nc52grkKeLQ+DGaOfQz8i
+  matrix:
+    - nodejs_version: 0.10.36
+      platform: x86
+      msvs_toolset: 12
+    - nodejs_version: 0.10.36
+      platform: x64
+      msvs_toolset: 12
+    - nodejs_version: 0.12.0
+      platform: x86
+      msvs_toolset: 12
+    - nodejs_version: 0.12.0
+      platform: x64
+      msvs_toolset: 12
+    # custom 64 bit visual studio 2014 builds
+    - nodejs_version: 0.10.36
+      platform: x64
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.10.36
+      platform: x86
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.11.14
+      platform: x86
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.11.14
+      platform: x64
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.12.0
+      platform: x86
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+    - nodejs_version: 0.12.0
+      platform: x64
+      msvs_toolset: 14
+      TOOLSET_ARGS: --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --toolset=v140
+
+os: Visual Studio 2014 CTP4
+
+install:
+  # add local node to path (since we install it for msvs_toolset == 14)
+  - SET PATH=%CD%;%PATH%;
+  # add local node-pre-gyp dir to path
+  - SET PATH=node_modules\.bin;%PATH%
+  # use 64 bit python if platform is 64 bit
+  - if "%PLATFORM%" == "x64" set PATH=C:\Python27-x64;%PATH%
+  - SET ARCHPATH=
+  - if %platform% == x64 (SET ARCHPATH=x64/)
+  # install node version per visual studio toolset
+  - if "%msvs_toolset%" == "12" powershell Install-Product node $env:nodejs_version $env:Platform
+  - if "%msvs_toolset%" == "14" powershell Write-Output "fetching https://mapbox.s3.amazonaws.com/node-cpp11/v$env:nodejs_version/${env:ARCHPATH}node.exe"
+  - if "%msvs_toolset%" == "14" powershell Start-FileDownload "https://mapbox.s3.amazonaws.com/node-cpp11/v$env:nodejs_version/${env:ARCHPATH}node.exe"
+  - node -v
+  - node -e "console.log(process.argv,process.execPath)"
+  - SET PATH=C:\Program Files (x86)\MSBuild\%msvs_toolset%.0\bin;%PATH%
+  - SET PATH=C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\bin;%PATH%
+  - if %platform% == x64 CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" amd64
+  - if %platform% == x86 CALL "C:\Program Files (x86)\Microsoft Visual Studio %msvs_toolset%.0\VC\vcvarsall.bat" amd64_x86
+  - npm install --build-from-source --msvs_version=2013 %TOOLSET_ARGS% --loglevel=http
+  - node_modules\.bin\node-pre-gyp reveal module --silent > module.txt
+  - SET /p MODULE=<module.txt
+  - del module.txt
+  - node -e "console.log(process.execPath)" > node_path.txt
+  - SET /p NODE_EXE_PATH=<node_path.txt
+  - del node_path.txt
+  # should display MSVCP140.dll if build with visual studio 2014 and /MD
+  - dumpbin /DEPENDENTS "%NODE_EXE_PATH%"
+  - dumpbin /DEPENDENTS "%MODULE%"
+  - npm test
+  - node-pre-gyp package %TOOLSET_ARGS%
+  # make commit message env var shorter
+  - SET CM=%APPVEYOR_REPO_COMMIT_MESSAGE%
+  - if not "%CM%" == "%CM:[publish binary]=%" node-pre-gyp --msvs_version=2013 unpublish publish %TOOLSET_ARGS%
+
+build: OFF
+test: OFF
+deploy: OFF
diff --git a/binding.gyp b/binding.gyp
index 088c2a2..471d616 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -1,39 +1,84 @@
 {
   'includes': [ 'common.gypi' ],
   'variables': {
-      'runtime_link%':'shared',
+    'runtime_link%':'shared',
+    'shared_gdal%':'false',
   },
   'targets': [
     {
-      'target_name': '_srs',
-      'libraries' : ['<!@(gdal-config --libs)'],
+      'target_name': 'action_before_build',
+      'hard_dependency': 1,
+      'type': 'none',
+      'actions': [
+        {
+          'action_name': 'generate_setting',
+          'inputs': [
+            'gen_settings.py'
+          ],
+          'outputs': [
+            '<(SHARED_INTERMEDIATE_DIR)/srs_settings.js'
+          ],
+          'action': ['python', 'gen_settings.py', '<@(shared_gdal)', '<(SHARED_INTERMEDIATE_DIR)/srs_settings.js']
+        }
+      ],
+      'copies': [
+        {
+          'files': [ '<(SHARED_INTERMEDIATE_DIR)/srs_settings.js' ],
+          'destination': '<(module_path)'
+        }
+      ]
+    },
+    {
+      'target_name': 'srs',
+      'dependencies': [ 'action_before_build' ],
       'conditions': [
-        ['runtime_link == "static"', {
-            'libraries': ['<!@(gdal-config --dep-libs)']
-        }]
+        ['shared_gdal == "false"',
+          {
+            'dependencies': [
+              'deps/osr.gyp:osr'
+            ]
+          },
+          {
+            'conditions': [
+              ['runtime_link == "static"',
+                {
+                  'libraries': ['<!@(gdal-config --dep-libs)']
+                }
+              ],
+            ],
+            'libraries' : ['<!@(gdal-config --libs)'],
+            'cflags_cc' : ['<!@(gdal-config --cflags)'],
+            'xcode_settings': {
+              'OTHER_CPLUSPLUSFLAGS':[
+                '<!@(gdal-config --cflags)'
+              ]
+            }
+          }
+        ]
       ],
-      'cflags_cc' : ['<!@(gdal-config --cflags)'],
-      'cflags_cc!': ['-fno-rtti', '-fno-exceptions'],
+      'cflags_cc!': ['-fno-exceptions'],
       'xcode_settings': {
-        'OTHER_CPLUSPLUSFLAGS':[
-           '<!@(gdal-config --cflags)'
-        ],
-        'GCC_ENABLE_CPP_RTTI': 'YES',
-        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
+        'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
+        'OTHER_LDFLAGS':[
+          '-Wl,-bind_at_load'
+        ]
       },
       'sources': [
-        'src/_srs.cc'
+        'src/srs.cc'
       ],
+      "include_dirs" : [
+        "<!(node -e \"require('nan')\")"
+      ]
     },
     {
       'target_name': 'action_after_build',
       'type': 'none',
-      'dependencies': [ '_srs' ],
+      'dependencies': [ '<(module_name)' ],
       'copies': [
-          {
-            'files': [ '<(PRODUCT_DIR)/_srs.node' ],
-            'destination': './lib/'
-          }
+        {
+          'files': [ '<(PRODUCT_DIR)/<(module_name).node' ],
+          'destination': '<(module_path)'
+        }
       ]
     }
   ]
diff --git a/common.gypi b/common.gypi
index bf7b460..03eba02 100644
--- a/common.gypi
+++ b/common.gypi
@@ -1,29 +1,55 @@
 {
+  'variables': {
+      "toolset%":'',
+  },
   'target_defaults': {
-      'default_configuration': 'Release',
-      'configurations': {
-          'Debug': {
-              'cflags_cc!': ['-O3', '-Os', '-DNDEBUG'],
-              'xcode_settings': {
-                'OTHER_CPLUSPLUSFLAGS!':['-O3', '-Os', '-DNDEBUG'],
-                'GCC_OPTIMIZATION_LEVEL': '0',
-                'GCC_GENERATE_DEBUGGING_SYMBOLS': 'YES'
-              }
-          },
-          'Release': {
-              'xcode_settings': {
-                'GCC_OPTIMIZATION_LEVEL': 's',
-                'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO',
-                'DEAD_CODE_STRIPPING':'YES',
-                'GCC_INLINES_ARE_PRIVATE_EXTERN':'YES',
-                'OTHER_LDFLAGS': [
-                    '-s' # warns 'option -s is obsolete and being ignored' but actually works
-                ]
-              },
-              'ldflags': [
-                    '-Wl,-s'
-              ]
+    'default_configuration': 'Release',
+    'msbuild_toolset':'<(toolset)',
+    'configurations': {
+      'Debug': {
+        'defines!': [
+          'NDEBUG'
+        ],
+        'cflags_cc!': [
+          '-O3',
+          '-Os',
+          '-DNDEBUG'
+        ],
+        'xcode_settings': {
+          'OTHER_CPLUSPLUSFLAGS!': [
+            '-O3',
+            '-Os',
+            '-DDEBUG'
+          ],
+          'GCC_OPTIMIZATION_LEVEL': '0',
+          'GCC_GENERATE_DEBUGGING_SYMBOLS': 'YES'
+        },
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'ExceptionHandling': 1, # /EHsc
           }
+        }
+      },
+      'Release': {
+        'defines': [
+          'NDEBUG'
+        ],
+        'xcode_settings': {
+          'OTHER_CPLUSPLUSFLAGS!': [
+            '-Os',
+            '-O2'
+          ],
+          'GCC_OPTIMIZATION_LEVEL': '3',
+          'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO',
+          'DEAD_CODE_STRIPPING': 'YES',
+          'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES'
+        },
+        'msvs_settings': {
+          'VCCLCompilerTool': {
+            'ExceptionHandling': 1, # /EHsc
+          }
+        }
       }
+    }
   }
 }
\ No newline at end of file
diff --git a/gen_settings.py b/gen_settings.py
new file mode 100755
index 0000000..a451955
--- /dev/null
+++ b/gen_settings.py
@@ -0,0 +1,17 @@
+import os
+import sys
+
+settings = os.path.abspath(sys.argv[2])
+
+# this goes into a srs_settings.js file beside the C++ srs.node
+settings_template = """
+module.exports.shared_gdal = %s;
+"""
+
+if __name__ == '__main__':
+    arg = sys.argv[1].strip("'").strip('"')
+    # windows gives ../false
+    if 'false' in arg:
+        open(settings,'w').write(settings_template % 'false')
+    else:
+        open(settings,'w').write(settings_template % 'true')
diff --git a/lib/constants.js b/lib/constants.js
new file mode 100644
index 0000000..e9c369d
--- /dev/null
+++ b/lib/constants.js
@@ -0,0 +1,86 @@
+/*
+ This is a custom srs definition for
+ spherical mercator that we make
+ canonical because no single variant
+ of the projection stored by various
+ applications is optimal.
+
+ This is basically a modification of gdal's
+ understanding of epsg 3857
+
+ Changes:
+
+ * add +over and +wktext to proj4 string
+ * remove any double spaces in proj4 string
+ * epsg is 3857, the new official epsg for 900913
+ * name is pulled from gdal/data/cubwerx_extra.wkt for 900913
+   instead of using 'WGS 84 / Pseudo-Mercator' or 'Popular...'
+
+ TODO:
+ * +x_0=0.0 vs +x_0=0 (same with +y_0)
+ * handle two scaling aliases +k and +k_0
+ * meaning of +k=1. vs +k=1.0 ?
+
+*/
+var merc_pretty_wkt = 'PROJCS["WGS 84 / Pseudo-Mercator",\n    GEOGCS["WGS 84",\n        DATUM["WGS_1984",\n            SPHEROID["WGS 84",6378137,298.257223563,\n                AUTHORITY["EPSG","7030"]],\n            AUTHORITY["EPSG","6326"]],\n        PRIMEM["Greenwich",0,\n            AUTHORITY["EPSG","8901"]],\n        UNIT["degree",0.0174532925199433,\n            AUTHORITY["EPSG","9122"]],\n        AUTHORITY["EPSG","4326"]],\n    UNIT["metre",1,\n        AUTHORITY["EPSG","9001"]],\ [...]
+
+var lon_lat_pretty_wkt = 'GEOGCS["WGS 84",\n    DATUM["WGS_1984",\n        SPHEROID["WGS 84",6378137,298.257223563,\n            AUTHORITY["EPSG","7030"]],\n        TOWGS84[0,0,0,0,0,0,0],\n        AUTHORITY["EPSG","6326"]],\n    PRIMEM["Greenwich",0,\n        AUTHORITY["EPSG","8901"]],\n    UNIT["degree",0.0174532925199433,\n        AUTHORITY["EPSG","9108"]],\n    AUTHORITY["EPSG","4326"]]';
+
+module.exports.merc_names = [
+    'Google_Maps_Global_Mercator',
+    'Google Maps Global Mercator',
+    'WGS 84 / Pseudo-Mercator', // 3857
+    'WGS_84_Pseudo_Mercator', // 3857 with new gdal/ogr name as per https://github.com/mapbox/node-srs/issues/27
+    'Popular Visualisation CRS / Mercator', // 3785
+    'WGS_1984_Web_Mercator', // ESRI
+    'WGS_1984_Web_Mercator_Auxiliary_Sphere', // ESRI
+    'Popular_Visualisation_CRS_Mercator_deprecated', // wtf
+    'Mercator_1SP',
+    'Mercator_2SP'
+];
+
+module.exports.merc_srids = [
+    900913, // http://crschmidt.net/blog/archives/243/google-projection-900913/
+    3857, // epsg official, second try
+    3785, // epsg deprecated, failed first try
+    102100, // esri official, second try
+    102113, // esri deprecated, failed first try
+    41001 //osgeo
+];
+
+// commonly confused as spherical mercator, but not, right?
+// here only for reference currently, nothing done programmatically
+module.exports.other_merc_srids = [
+    3395, // "WGS 84 / World Mercator" or normal, no googlized mercator: lacked +a=6378137 +b=6378137
+    3587, // common typo but actually NAD83(NSRS2007) / Michigan Central
+    // for these see also notes in shapefile.3857.test.js
+    9804, // older, esri style-named traditional merc: http://www.remotesensing.org/geotiff/proj_list/mercator_1sp.html
+    9805, // older, esri style-named traditional merc: http://www.remotesensing.org/geotiff/proj_list/mercator_2sp.html
+];
+
+module.exports.known_esri_variant_special_cases = [
+    ['DATUM["D_OSGB_1936"','DATUM["OSGB_1936"']
+];
+
+module.exports.canonical = {
+    spherical_mercator: {
+        proj4: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over',
+        srid: 3857, // or 900913
+        auth: 'EPSG',
+        pretty_wkt: merc_pretty_wkt,
+        esri: false,
+        name: 'Google Maps Global Mercator', // so many variants here
+        valid: true,
+        is_geographic: false
+    },
+    wgs84: {
+        proj4: '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs',
+        srid: 4326,
+        auth: 'EPSG',
+        pretty_wkt: lon_lat_pretty_wkt,
+        esri: false,
+        name: 'WGS 84',
+        valid: true,
+        is_geographic: true
+    }
+};
diff --git a/lib/srs.js b/lib/srs.js
index 3e1f293..b1e882a 100644
--- a/lib/srs.js
+++ b/lib/srs.js
@@ -1,125 +1,29 @@
-var path = require('path');
-var fs = require('fs');
-var srs = require('./_srs');
+var binary = require('node-pre-gyp');
 var exists = require('fs').existsSync || require('path').existsSync;
-if (exists('./settings.js')) {
-   var _settings = require('./settings');
-}
-
-exports.version = require('../package').version;
-
-/*
- This is a custom srs definition for
- spherical mercator that we make
- canonical because no single variant
- of the projection stored by various
- applications is optimal.
-
- This is basically a modification of gdal's
- understanding of epsg 3857
-
- Changes:
-
- * add +over and +wktext to proj4 string
- * remove any double spaces in proj4 string
- * epsg is 3857, the new official epsg for 900913
- * name is pulled from gdal/data/cubwerx_extra.wkt for 900913
-   instead of using 'WGS 84 / Pseudo-Mercator' or 'Popular...'
-
- TODO:
- * +x_0=0.0 vs +x_0=0 (same with +y_0)
- * handle two scaling aliases +k and +k_0
- * meaning of +k=1. vs +k=1.0 ?
-
-*/
-
-var merc_pretty_wkt = 'PROJCS["WGS 84 / Pseudo-Mercator",\n    GEOGCS["WGS 84",\n        DATUM["WGS_1984",\n            SPHEROID["WGS 84",6378137,298.257223563,\n                AUTHORITY["EPSG","7030"]],\n            AUTHORITY["EPSG","6326"]],\n        PRIMEM["Greenwich",0,\n            AUTHORITY["EPSG","8901"]],\n        UNIT["degree",0.0174532925199433,\n            AUTHORITY["EPSG","9122"]],\n        AUTHORITY["EPSG","4326"]],\n    UNIT["metre",1,\n        AUTHORITY["EPSG","9001"]],\ [...]
-
-var lon_lat_pretty_wkt = 'GEOGCS["WGS 84",\n    DATUM["WGS_1984",\n        SPHEROID["WGS 84",6378137,298.257223563,\n            AUTHORITY["EPSG","7030"]],\n        TOWGS84[0,0,0,0,0,0,0],\n        AUTHORITY["EPSG","6326"]],\n    PRIMEM["Greenwich",0,\n        AUTHORITY["EPSG","8901"]],\n    UNIT["degree",0.0174532925199433,\n        AUTHORITY["EPSG","9108"]],\n    AUTHORITY["EPSG","4326"]]';
-
-var canonical = {
-  spherical_mercator: {
-      proj4: '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over',
-      srid: 3857, // or 900913
-      auth: 'EPSG',
-      pretty_wkt: merc_pretty_wkt,
-      esri: false,
-      name: 'Google Maps Global Mercator', // so many variants here
-      valid: true,
-      is_geographic: false
-  },
-  wgs_84: {
-      proj4: '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs',
-      srid: 4326,
-      auth: 'EPSG',
-      pretty_wkt: lon_lat_pretty_wkt,
-      esri: false,
-      name: 'WGS 84',
-      valid: true,
-      is_geographic: true
-  }
-};
-
-function oc(a) {
-    var o = {};
-    for (var i = 0; i < a.length; i++) {
-        o[a[i]] = '';
-    }
-    return o;
-}
-
-var merc_names = [
-  'Google_Maps_Global_Mercator',
-  'Google Maps Global Mercator',
-  'WGS 84 / Pseudo-Mercator', // 3857
-  'WGS_84_Pseudo_Mercator', // 3857 with new gdal/ogr name as per https://github.com/springmeyer/node-srs/issues/27
-  'Popular Visualisation CRS / Mercator', // 3785
-  'WGS_1984_Web_Mercator', // ESRI
-  'WGS_1984_Web_Mercator_Auxiliary_Sphere', // ESRI
-  'Popular_Visualisation_CRS_Mercator_deprecated', // wtf
-  'Mercator_1SP',
-  'Mercator_2SP'
-  ];
-
-var merc_srids = [
-  900913, // http://crschmidt.net/blog/archives/243/google-projection-900913/
-  3857, // epsg official, second try
-  3785, // epsg deprecated, failed first try
-  102100, // esri official, second try
-  102113, // esri deprecated, failed first try
-  41001 //osgeo
-  ];
-
-// commonly confused as spherical mercator, but not, right?
-// here only for reference currently, nothing done programmatically
-var other_merc_srids = [
-  3395, // "WGS 84 / World Mercator" or normal, no googlized mercator: lacked +a=6378137 +b=6378137
-  3587, // common typo but actually NAD83(NSRS2007) / Michigan Central
-  // for these see also notes in shapefile.3857.test.js
-  9804, // older, esri style-named traditional merc: http://www.remotesensing.org/geotiff/proj_list/mercator_1sp.html
-  9805, // older, esri style-named traditional merc: http://www.remotesensing.org/geotiff/proj_list/mercator_2sp.html
-]
-
-var known_esri_variant_special_cases = [
-  ['DATUM["D_OSGB_1936"','DATUM["OSGB_1936"']
-];
+var path = require('path');
+var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
+var settings_path = path.join(path.dirname(binding_path),'srs_settings.js');
+var settings = require(settings_path);
 
 /*
-if we have statically linked libosr then we need
-to set the GDAL_DATA directory so that the bundled
-.csv and .wkt files are found.
+ * if we have statically linked libosr then we need
+ * to set the GDAL_DATA directory so that the bundled
+ * .csv and .wkt files are found.
 */
-if (_settings && _settings.static_osr) {
+var srs_settings = require(settings_path);
+if (!srs_settings.shared_gdal) {
     process.env.GDAL_DATA = path.join(__dirname, 'srs_data');
 }
 
-var force_merc = function(result) {
-    var new_merc = canonical.spherical_mercator;
-    new_merc.input = result.input;
-    return new_merc;
-};
+var binding = require(binding_path);
+var srs = module.exports = exports = binding;
+exports.module_path = path.dirname(binding_path);
+var constants = require('./constants');
+var canonical = constants.canonical;
+exports.version = require('../package').version;
 
-var split_proj = function(literal) {
+
+function split_proj(literal) {
     var parts = literal.split(' ');
     // remove blank parts due to double spaces (common in proj epsg table)
     var len = parts.length;
@@ -138,13 +42,13 @@ var split_proj = function(literal) {
             var pair = p.split('=');
             if (pair[1] && pair[1] === '0') {
                 // https://github.com/mapbox/tilemill/issues/1866
-                pair[1] = '0.0'
+                pair[1] = '0.0';
             }
             pairs[pair[0]] = pair[1];
         }
     }
     return pairs;
-};
+}
 
 var canonical_parts = split_proj(canonical.spherical_mercator.proj4);
 var canonical_stringify = JSON.stringify(canonical_parts);
@@ -154,40 +58,6 @@ var parse = function(arg) {
         arg = arg.toString();
     }
 
-    if (exists(arg)) {
-        var extension = path.extname(arg).toLowerCase();
-        var is_json = false;
-        if (extension == '.json' || extension == '.geojson') {
-            is_json = true;
-        }
-        var file_data = fs.readFileSync(arg);
-        if (!is_json) {
-           if (file_data[0] == '{') {
-               is_json = true;
-           } else {
-                 var fstring = file_data.toString();
-                 if (
-                     ((fstring.search('"type"') > -1) && (fstring.search('"coordinates"') > -1))
-                     || (fstring.search('"FeatureCollection"') > -1)
-                     || ((fstring.search('"geometryType"') > -1) && (fstring.search('"esriGeometry"') > -1))
-                    )
-                 {
-                   is_json = true;
-                 }
-           }
-        }
-        if (is_json) {
-            var file = JSON.parse(file_data);
-            if (file.crs && file.crs.properties && file.crs.properties.urn) {
-                arg = file.crs.properties.urn;
-            } else if (file.crs && file.crs.properties && file.crs.properties.name) {
-                arg = file.crs.properties.name;
-            } else {
-                arg = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs';
-            }
-        }
-    }
-    
     // early check for known +init=epsg: syntax, which we will
     // translate to +proj literal to avoid requiring proj4 to do that in mapnik
     var arg_lower = arg.toLowerCase();
@@ -195,43 +65,73 @@ var parse = function(arg) {
         var parts = arg_lower.split(':');
         if (parts[1]) {
             var code = +parts[1];
-            if (merc_srids.indexOf(code) > -1) {
+            if (constants.merc_srids.indexOf(code) > -1) {
                 return force_merc({input:arg});
             }
+            if (code === 4326) {
+                return force_wgs84({input:arg});
+            }
         }
     }
 
-    for (var hack in known_esri_variant_special_cases) {
-        var obj = known_esri_variant_special_cases[hack];
+    for (var hack in constants.known_esri_variant_special_cases) {
+        var obj = constants.known_esri_variant_special_cases[hack];
         if (arg.indexOf(obj[0]) > -1) {
             arg = arg.replace(obj[0],obj[1]);
         }
     }
-    var result;
 
+    var result;
+    var esri_try = false;
     try {
         result = srs._parse(arg);
-    } catch (e) {
+    } catch (err) {
         if (arg.indexOf('ESRI::') !== 0) {
-            result = srs._parse('ESRI::' + arg);
+            try {
+                esri_try = true;
+                result = srs._parse('ESRI::' + arg);
+            } catch (esri_err) {
+                throw err; // throw original error
+            }
         } else {
-            throw e;
+            throw err;
+        }
+    }
+
+    // if the first parse succeeded without throwing
+    // but still failed to detect the proj4 string then
+    // we need to try harder and assume an ESRI variant
+    if (result.proj4 === undefined &&
+        esri_try === false &&
+        arg.indexOf('ESRI::') !== 0) {
+        try {
+            var esri_result = srs._parse('ESRI::' + arg);
+            // success detecting proj4 as ESRI variant?
+            if (esri_result.proj4) {
+                result = esri_result;
+            }
+        } catch (err) {
+            // pass
         }
     }
 
+    // force wgs84 variants to canonical
+    if (result.srid === 4326) {
+        return force_wgs84(result);
+    }
     // detect mercator variants and
     // replace with canonical.spherical_mercator
-    if (result.name in oc(merc_names)) {
+    if (result.name in oc(constants.merc_names)) {
         // this should be a fast track for many .prj files
         return force_merc(result);
-    } else if (result.srid in oc(merc_srids)) {
+    } else if (result.srid in oc(constants.merc_srids)) {
         return force_merc(result);
     } else if (result.proj4 !== undefined && result.proj4.indexOf('+proj=merc') != -1) {
         // catch case of gdal's translation to proj4 being used as input
         if (result.proj4 === '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs') {
            return force_merc(result);
         } else if (result.proj4 === '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +units=m +no_defs') {
-           return force_merc(result);        
+           return force_merc(result);
         }
         // break into parts
         // TODO - sort and remove less critical pairs
@@ -242,7 +142,7 @@ var parse = function(arg) {
     }
 
     // detect OSGB variant and fix the srid
-    // https://github.com/springmeyer/node-srs/issues/25
+    // https://github.com/mapbox/node-srs/issues/25
     if (!result.srid && result.name == 'OSGB 1936 / British National Grid') {
         result.srid = 27700;
         result.auth = 27700;
@@ -251,11 +151,44 @@ var parse = function(arg) {
     return result;
 };
 
+function jsonCrs(gj) {
+    if (gj.crs && gj.crs.properties) {
+        if (gj.crs.properties.urn) {
+            return gj.crs.properties.urn;
+        } else if (gj.crs.properties.name) {
+            return gj.crs.properties.name;
+        }
+    } else {
+        return canonical.wgs84.proj4;
+    }
+}
+
+function oc(a) {
+    var o = {};
+    for (var i = 0; i < a.length; i++) {
+        o[a[i]] = '';
+    }
+    return o;
+}
+
+function force_merc(result) {
+    var new_srs = canonical.spherical_mercator;
+    new_srs.input = result.input;
+    return new_srs;
+}
+
+function force_wgs84(result) {
+    var new_srs = canonical.wgs84;
+    new_srs.input = result.input;
+    return new_srs;
+}
+
 // push all C++ symbols into js module
 for (var k in srs) { exports[k] = srs[k]; }
 
 // make available objects from js
-exports.settings = _settings;
+exports.settings = srs_settings;
 exports.canonical = canonical;
 exports.split_proj = split_proj;
 exports.parse = parse;
+exports.jsonCrs = jsonCrs;
diff --git a/package.json b/package.json
index 3838e47..2769329 100644
--- a/package.json
+++ b/package.json
@@ -1,25 +1,49 @@
 {
-  "name"          : "srs",
-  "version"       : "0.3.2",
-  "main"          : "./lib/index.js",
-  "description"   : "Spatial reference library for node",
-  "keywords"      : ["map", "projection", "spatialreference", "srid", "proj4", "mercator"],
-  "url"           : "http://github.com/springmeyer/node-srs",
-   "repository" : {
-           "type" : "git",
-           "url"  : "git://github.com/springmeyer/node-srs.git" 
+  "name": "srs",
+  "version": "0.4.8",
+  "main": "./lib/index.js",
+  "description": "Spatial reference library for node",
+  "keywords": [
+    "map",
+    "projection",
+    "spatialreference",
+    "srid",
+    "proj4",
+    "mercator",
+    "gdal",
+    "ogr",
+    "osr"
+  ],
+  "binary": {
+    "module_name" : "srs",
+    "module_path" : "./lib/binding/{node_abi}-{platform}-{arch}",
+    "host"        : "https://mapbox-node-binary.s3.amazonaws.com",
+    "remote_path" : "./{name}/v{version}/{toolset}/",
+    "package_name": "{node_abi}-{platform}-{arch}.tar.gz"
   },
-  "author"        : "Dane Springmeyer <dane at dbsgeo.com>",
-  "contributors"  : [],
-  "licenses"      : ["BSD"],
-  "dependencies"  : {},
-   "directories"  : {
-       "src"      : "src"
-   },
-  "engines": {
-    "node": ">= 0.6.13"
+  "url": "http://github.com/mapbox/node-srs",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/mapbox/node-srs.git"
   },
-  "scripts"       : {
-      "test"    : "make test"
-   }
+  "dependencies": {
+    "nan": "~1.8.4",
+    "node-pre-gyp": "~0.6.7"
+  },
+  "bundledDependencies": [
+    "node-pre-gyp"
+  ],
+  "author": "Dane Springmeyer <dane at mapbox.com>",
+  "licenses": [
+    "BSD"
+  ],
+  "scripts": {
+    "prepublish": "npm ls",
+    "install": "node-pre-gyp install --fallback-to-build",
+    "test": "mocha -R spec"
+  },
+  "devDependencies": {
+    "mocha": "1.x",
+    "aws-sdk": "~2.0.25"
+  }
 }
diff --git a/scripts/package_osx.sh b/scripts/package_osx.sh
new file mode 100755
index 0000000..d2b7942
--- /dev/null
+++ b/scripts/package_osx.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+set -e
+
+CURRENT_DIR="$( cd "$( dirname $BASH_SOURCE )" && pwd )"
+cd $CURRENT_DIR/../
+source ~/.nvm/nvm.sh
+nvm install 0.10
+nvm use 0.10
+npm install node-pre-gyp
+npm install aws-sdk
+./node_modules/.bin/node-pre-gyp info
+npm cache clean
+rm -rf sdk
+
+function doit () {
+    NVER=$1
+    nvm install $1
+    nvm use $1
+    npm install --build-from-source
+    npm test
+    node ./node_modules/.bin/node-pre-gyp package testpackage
+    node ./node_modules/.bin/node-pre-gyp testpackage
+    npm ls
+    node ./node_modules/.bin/node-pre-gyp publish
+    node ./node_modules/.bin/node-pre-gyp info
+    rm -rf {build,lib/binding}
+    npm install --fallback-to-build=false
+    npm test
+}
+
+doit 0.10.33
+doit 0.11.14
+
+# to avoid then publishing with node v0.11.x
+# https://github.com/npm/npm/issues/5515#issuecomment-46688278
+nvm use 0.10
diff --git a/src/_srs.cc b/src/_srs.cc
deleted file mode 100644
index 876cd99..0000000
--- a/src/_srs.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// v8
-#include <v8.h>
-
-// node
-#include <node.h>
-#include <node_version.h>
-
-// stl
-#include <sstream>
-#include <iostream>
-#include <stdio.h>
-#include <stdlib.h>
-
-// osr
-#include "ogr_spatialref.h"
-//#include "ogr_core.h"
-//#include "cpl_conv.h"
-#include "cpl_string.h"
-//#include "ogr_p.h"
-//#include "cpl_multiproc.h"
-//#include "ogr_srs_api.h"
-
-using namespace node;
-using namespace v8;
-
-#define TOSTR(obj) (*String::Utf8Value((obj)->ToString()))
-
-
-/*
-OGRERR_DICT = { 1 : (OGRException, "Not enough data."),
-                2 : (OGRException, "Not enough memory."),
-                3 : (OGRException, "Unsupported geometry type."),
-                4 : (OGRException, "Unsupported operation."),
-                5 : (OGRException, "Corrupt data."),
-                6 : (OGRException, "OGR failure."),
-                7 : (SRSException, "Unsupported SRS."),
-                8 : (OGRException, "Invalid handle."),
-                }
-*/
-
-static Handle<Value> parse(const Arguments& args)
-{
-    HandleScope scope;
-
-    if (args.Length() != 1 || !args[0]->IsString())
-      return ThrowException(Exception::TypeError(
-        String::New("first argument must be srs string in any form readable by OGR, like WKT (.prj file) or a proj4 string")));
-
-    OGRSpatialReference oSRS;
-
-    Local<Object> result = Object::New();
-
-    result->Set(String::NewSymbol("input"), args[0]->ToString());
-    // intialize as undefined
-    result->Set(String::NewSymbol("proj4"), Undefined());
-    result->Set(String::NewSymbol("srid"), Undefined());
-    result->Set(String::NewSymbol("auth"), Undefined());
-    result->Set(String::NewSymbol("pretty_wkt"), Undefined());
-    result->Set(String::NewSymbol("esri"), Undefined());
-    result->Set(String::NewSymbol("name"), Undefined());
-
-    std::string wkt_string = TOSTR(args[0]->ToString());
-
-    const char *wkt_char = wkt_string.data();
-
-    bool error = false;
-
-    Handle<Value> err;
-    
-    if( oSRS.SetFromUserInput(wkt_char) != OGRERR_NONE )
-    {
-        error = true;
-        std::ostringstream s;
-        s << "OGR Error type #" << CPLE_AppDefined
-          << " problem occured importing from srs wkt: " << wkt_string << ".\n";;
-        err = ThrowException(Exception::TypeError(String::New(s.str().c_str())));
-
-        // try again to import from ESRI
-        oSRS.Clear();
-        char **wkt_lines = NULL;
-        wkt_lines = CSLTokenizeString2( wkt_char, " \t\n", 
-                                CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
-        if( oSRS.importFromESRI(wkt_lines) != OGRERR_NONE )
-        {
-            error = true;
-            oSRS.Clear();
-            //std::ostringstream s;
-            //s << "b: OGR Error type #" << CPLE_AppDefined 
-            //  << " problem occured importing assuming esri wkt " << wkt_string << ".\n";
-            //err = ThrowException(Exception::TypeError(String::New(s.str().c_str())));
-        }
-        else
-        {
-            error = false;
-            std::clog << "imported assuming esri format...\n";
-            result->Set(String::NewSymbol("esri"), Boolean::New(true));
-        }
-    }
-    else
-    {
-        error = false;
-        if (wkt_string.substr(0,6) == "ESRI::")
-        {
-            result->Set(String::NewSymbol("esri"), Boolean::New(true));
-        }
-        else
-        {
-            result->Set(String::NewSymbol("esri"), Boolean::New(false));
-        }
-    }
-    
-    if (error)
-        return err;
-    
-    char  *srs_output = NULL;
-    if( oSRS.Validate() == OGRERR_NONE)
-        result->Set(String::NewSymbol("valid"), Boolean::New(true));
-    else if (oSRS.Validate() == OGRERR_UNSUPPORTED_SRS)
-        result->Set(String::NewSymbol("valid"), Boolean::New(false));    
-    else
-        result->Set(String::NewSymbol("valid"), Boolean::New(false));
-    
-    // TODO - trim output of proj4 result
-    if (oSRS.exportToProj4( &srs_output ) != OGRERR_NONE )
-    {
-        std::ostringstream s;
-        s << "OGR Error type #" << CPLE_AppDefined 
-          << " problem occured when converting to proj4 format " << wkt_string << ".\n";
-        // for now let proj4 errors be non-fatal so that some info can be known...
-        //std::clog << s.str();
-        //return ThrowException(Exception::TypeError(String::New(s.str().c_str())));
-        
-    }
-    else
-    {
-        // proj4 strings from osr have an uneeded trailing slash, so we trim it...
-        result->Set(String::NewSymbol("proj4"), String::New(CPLString(srs_output).Trim()));
-    }
-
-    CPLFree( srs_output );
-
-    if (oSRS.AutoIdentifyEPSG() != OGRERR_NONE )
-    {
-        /*std::ostringstream s;
-        s << "OGR Error type #" << CPLE_AppDefined 
-          << " problem occured when attempting to auto identify epsg code " << wkt_string << ".\n";
-        std::clog << s.str();
-        */
-        //return ThrowException(Exception::TypeError(String::New(s.str().c_str())));
-    }
-
-    if (oSRS.IsGeographic())
-    {
-        result->Set(String::NewSymbol("is_geographic"), Boolean::New(true));
-        const char *code = oSRS.GetAuthorityCode("GEOGCS");
-        if (code)
-            result->Set(String::NewSymbol("srid"), Integer::New(atoi(code)));
-        const char *auth = oSRS.GetAuthorityName("GEOGCS");
-        if (auth)
-            result->Set(String::NewSymbol("auth"), String::New(auth));
-        const char *name = oSRS.GetAttrValue("GEOGCS");
-        if (name)
-            result->Set(String::NewSymbol("name"), String::New(name));
-    }
-    else
-    {
-        result->Set(String::NewSymbol("is_geographic"), Boolean::New(false));
-        const char *code = oSRS.GetAuthorityCode("PROJCS");
-        if (code)
-            result->Set(String::NewSymbol("srid"), Integer::New(atoi(code)));
-        const char *auth = oSRS.GetAuthorityName("PROJCS");
-        if (auth)
-            result->Set(String::NewSymbol("auth"), String::New(auth));
-        const char *name = oSRS.GetAttrValue("PROJCS");
-        if (name)
-            result->Set(String::NewSymbol("name"), String::New(name));
-    }
-
-    char  *srs_output2 = NULL;
-    if (oSRS.exportToPrettyWkt( &srs_output2 , 0) != OGRERR_NONE )
-    {
-        // this does not yet actually return errors
-        std::ostringstream s;
-        s << "OGR Error type #" << CPLE_AppDefined 
-          << " problem occured when converting to pretty wkt format " << wkt_string << ".\n";
-        //std::clog << s.str();
-        //return ThrowException(Exception::TypeError(String::New(s.str().c_str())));
-    }
-    else
-    {
-        result->Set(String::NewSymbol("pretty_wkt"), String::New(srs_output2));
-    }
-
-    CPLFree( srs_output2 );
-    //OGRSpatialReference::DestroySpatialReference( &oSRS );
-    return scope.Close(result);
-}
-
-
-extern "C" {
-
-  static void init (Handle<Object> target)
-  {
-
-    NODE_SET_METHOD(target, "_parse", parse);
-    
-    // versions of deps
-    Local<Object> versions = Object::New();
-    versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
-    versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
-    // ogr/osr ?
-    target->Set(String::NewSymbol("versions"), versions);
-
-  }
-
-  NODE_MODULE(_srs, init);
-}
diff --git a/src/srs.cc b/src/srs.cc
new file mode 100644
index 0000000..f8957c1
--- /dev/null
+++ b/src/srs.cc
@@ -0,0 +1,175 @@
+// v8
+#include <v8.h>
+
+// node
+#include <node.h>
+#include <nan.h>
+#include <node_version.h>
+
+// stl
+#include <sstream>
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+
+// osr
+#include "ogr_spatialref.h"
+#include "cpl_error.h" // CPLE_AppDefined
+#include "cpl_conv.h" // CPLFree
+#include "cpl_string.h" // CPLString
+
+using namespace node;
+using namespace v8;
+
+#define TOSTR(obj) (*String::Utf8Value((obj)->ToString()))
+
+/*
+OGRERR_DICT = { 1 : (OGRException, "Not enough data."),
+                2 : (OGRException, "Not enough memory."),
+                3 : (OGRException, "Unsupported geometry type."),
+                4 : (OGRException, "Unsupported operation."),
+                5 : (OGRException, "Corrupt data."),
+                6 : (OGRException, "OGR failure."),
+                7 : (SRSException, "Unsupported SRS."),
+                8 : (OGRException, "Invalid handle."),
+                }
+*/
+
+NAN_METHOD(parse) {
+    NanScope();
+    if (args.Length() != 1 || !args[0]->IsString())
+      return NanThrowTypeError("first argument must be srs string in any form readable by OGR, like WKT (.prj file) or a proj4 string");
+
+    Local<Object> result = NanNew<Object>();
+    result->Set(NanNew<String>("input"), args[0]->ToString());
+    result->Set(NanNew<String>("proj4"), NanUndefined());
+    result->Set(NanNew<String>("srid"), NanUndefined());
+    result->Set(NanNew<String>("auth"), NanUndefined());
+    result->Set(NanNew<String>("pretty_wkt"), NanUndefined());
+    result->Set(NanNew<String>("esri"), NanUndefined());
+    result->Set(NanNew<String>("name"), NanUndefined());
+
+    std::string wkt_string = TOSTR(args[0]->ToString());
+    const char *wkt_char = wkt_string.data();
+    bool error = false;
+    std::string err_msg;
+    OGRSpatialReference oSRS;
+    if( oSRS.SetFromUserInput(wkt_char) != OGRERR_NONE )
+    {
+        error = true;
+        std::ostringstream s;
+        s << "OGR Error type #" << CPLE_AppDefined
+          << " problem occured importing from srs wkt: " << wkt_string << ".\n";;
+        err_msg = s.str();
+
+        // try again to import from ESRI
+        oSRS.Clear();
+        char **wkt_lines = NULL;
+        wkt_lines = CSLTokenizeString2( wkt_char, " \t\n",
+                                CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
+        if( oSRS.importFromESRI(wkt_lines) != OGRERR_NONE )
+        {
+            error = true;
+            oSRS.Clear();
+        }
+        else
+        {
+            error = false;
+            result->Set(NanNew<String>("esri"), NanNew<Boolean>(true));
+        }
+    }
+    else
+    {
+        error = false;
+        if (wkt_string.substr(0,6) == "ESRI::")
+        {
+            result->Set(NanNew<String>("esri"), NanNew<Boolean>(true));
+        }
+        else
+        {
+            result->Set(NanNew<String>("esri"), NanNew<Boolean>(false));
+        }
+    }
+
+    if (error) {
+        return NanThrowError(err_msg.c_str());
+    } else {
+        char  *srs_output = NULL;
+        if (oSRS.Validate() == OGRERR_NONE) {
+            result->Set(NanNew<String>("valid"), NanNew<Boolean>(true));
+        } else if (oSRS.Validate() == OGRERR_UNSUPPORTED_SRS) {
+            result->Set(NanNew<String>("valid"), NanNew<Boolean>(false));
+        } else {
+            result->Set(NanNew<String>("valid"), NanNew<Boolean>(false));
+        }
+
+        if (oSRS.exportToProj4( &srs_output ) == OGRERR_NONE ) {
+            // proj4 strings from osr have an uneeded trailing slash, so we trim it...
+            result->Set(NanNew<String>("proj4"), NanNew<String>(CPLString(srs_output).Trim().c_str()));
+        }
+
+        CPLFree( srs_output );
+
+        if (oSRS.AutoIdentifyEPSG() != OGRERR_NONE )
+        {
+            // do nothing
+        }
+
+        if (oSRS.IsGeographic())
+        {
+            result->Set(NanNew<String>("is_geographic"), NanNew<Boolean>(true));
+            const char *code = oSRS.GetAuthorityCode("GEOGCS");
+            if (code) {
+                result->Set(NanNew<String>("srid"), NanNew<Integer>(atoi(code)));
+            }
+            const char *auth = oSRS.GetAuthorityName("GEOGCS");
+            if (auth) {
+                result->Set(NanNew<String>("auth"), NanNew<String>(auth));
+            }
+            const char *name = oSRS.GetAttrValue("GEOGCS");
+            if (name) {
+                result->Set(NanNew<String>("name"), NanNew<String>(name));
+            }
+        }
+        else
+        {
+            result->Set(NanNew<String>("is_geographic"), NanNew<Boolean>(false));
+            const char *code = oSRS.GetAuthorityCode("PROJCS");
+            if (code) {
+                result->Set(NanNew<String>("srid"), NanNew<Integer>(atoi(code)));
+            }
+            const char *auth = oSRS.GetAuthorityName("PROJCS");
+            if (auth) {
+                result->Set(NanNew<String>("auth"), NanNew<String>(auth));
+            }
+            const char *name = oSRS.GetAttrValue("PROJCS");
+            if (name) {
+                result->Set(NanNew<String>("name"), NanNew<String>(name));
+            }
+        }
+
+        char  *srs_output2 = NULL;
+        if (oSRS.exportToPrettyWkt( &srs_output2 , 0) == OGRERR_NONE ) {
+            result->Set(NanNew<String>("pretty_wkt"), NanNew<String>(srs_output2));
+        }
+        CPLFree(srs_output2);
+        NanReturnValue(result);
+    }
+}
+
+
+extern "C" {
+
+  static void init (Handle<Object> target)
+  {
+
+    NODE_SET_METHOD(target, "_parse", parse);
+    // versions of deps
+    Local<Object> versions = NanNew<Object>();
+    versions->Set(NanNew<String>("node"), NanNew<String>(NODE_VERSION+1));
+    versions->Set(NanNew<String>("v8"), NanNew<String>(V8::GetVersion()));
+    target->Set(NanNew<String>("versions"), versions);
+  }
+
+  NODE_MODULE(srs, init);
+}
diff --git a/test/data/transverse_merc_kasey.prj b/test/data/transverse_merc_kasey.prj
new file mode 100644
index 0000000..1f13406
--- /dev/null
+++ b/test/data/transverse_merc_kasey.prj
@@ -0,0 +1 @@
+PROJCS["Transverse_Mercator",GEOGCS["GCS_Clarke 1866",DATUM["D_unknown",SPHEROID["clrk66",6378206.4,294.9786982]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",35.83333333333334],PARAMETER["central_meridian",-90.5],PARAMETER["scale_factor",0.9999333333333333],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Foot_US",0.30480060960121924]]
\ No newline at end of file
diff --git a/test/data/transverse_merc_kasey_custom_grids.prj b/test/data/transverse_merc_kasey_custom_grids.prj
new file mode 100644
index 0000000..a48ec59
--- /dev/null
+++ b/test/data/transverse_merc_kasey_custom_grids.prj
@@ -0,0 +1 @@
+PROJCS["unnamed",GEOGCS["Clarke 1866",DATUM["unknown",SPHEROID["clrk66",6378206.4,294.9786982139006],EXTENSION["PROJ4_GRIDS","@conus, at alaska, at ntv2_0.gsb, at ntv1_can.dat"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",35.83333333333334],PARAMETER["central_meridian",-90.5],PARAMETER["scale_factor",0.9999333333333333],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Foot_US",0.3048006096012192]]
diff --git a/test/esri_variant.test.js b/test/esri_variant.test.js
new file mode 100644
index 0000000..1ce6894
--- /dev/null
+++ b/test/esri_variant.test.js
@@ -0,0 +1,14 @@
+var srs = require('../');
+var fs = require('fs');
+var assert = require('assert');
+
+// http://spatialreference.org/ref/esri/102685/
+// http://spatialreference.org/ref/sr-org/7058/
+describe('maryland ESRI variant', function() {
+    it('detects proj if parsed as ESRI::', function(done) {
+        var ref = srs.parse(fs.readFileSync('./test/data/maryland.prj'));
+        assert.ok(ref.proj4);
+        assert.equal(ref.name,'NAD_1983_StatePlane_Maryland_FIPS_1900');
+        done();
+    });
+});
diff --git a/test/geojson.test.js b/test/geojson.test.js
index e5846f7..c4986f2 100644
--- a/test/geojson.test.js
+++ b/test/geojson.test.js
@@ -1,24 +1,26 @@
-var srs = require('srs');
+var srs = require('../');
 var assert = require('assert');
+var fs = require('fs');
+var util = require('./util');
 
 describe('GeoJSON', function() {
     it('should detect mercator', function() {
-        var merc = srs.parse('./test/data/world_extent_merc.geojson');
+        var merc = srs.parse(srs.jsonCrs(JSON.parse(fs.readFileSync('./test/data/world_extent_merc.geojson'))));
         assert.equal(merc.proj4, srs.canonical.spherical_mercator.proj4);
     });
 
     it('should detect wgs84', function() {
-        var wgs84 = srs.parse('./test/data/world_extent_wgs84.geojson');
-        assert.equal(wgs84.proj4, '+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
+        var parsed = srs.parse(srs.jsonCrs(JSON.parse(fs.readFileSync('./test/data/world_extent_wgs84.geojson'))));
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 2', function() {
-        var wgs84_2 = srs.parse('./test/data/test.json');
-        assert.equal(wgs84_2.proj4, '+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
+        var parsed = srs.parse(srs.jsonCrs(JSON.parse(fs.readFileSync('./test/data/test.json'))));
+        util.assert_wgs84(parsed);
     });
 
     it('should detect with no ext', function() {
-        var wgs84 = srs.parse('./test/data/mystery-api');
-        assert.equal(wgs84.proj4, '+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
+        var parsed = srs.parse(srs.jsonCrs(JSON.parse(fs.readFileSync('./test/data/mystery-api'))));
+        util.assert_wgs84(parsed);
     });
 });
diff --git a/test/invalid.test.js b/test/invalid.test.js
new file mode 100644
index 0000000..f19efab
--- /dev/null
+++ b/test/invalid.test.js
@@ -0,0 +1,28 @@
+var srs = require('../');
+var fs = require('fs');
+var assert = require('assert');
+
+// http://spatialreference.org/ref/esri/102685/
+// http://spatialreference.org/ref/sr-org/7058/
+describe('throws on invalid input', function() {
+    it('detects proj if parsed as ESRI::', function() {
+        assert.throws(function() {
+            var ref = srs.parse('PROCS[]');
+        });
+    });
+    it('init=epsg:3857', function() {
+        assert.throws(function() {
+            srs.parse('init=epsg:3857');
+        });
+    });
+    it('+init=epsg', function() {
+        assert.throws(function() {
+            srs.parse('+init=epsg');
+        });
+    });
+    it('+init=epsg:500', function() {
+        assert.throws(function() {
+            assert.ok(srs.parse('+init=epsg:500'));
+        });
+    });
+});
diff --git a/test/qgis-qpj.test.js b/test/qgis-qpj.test.js
new file mode 100644
index 0000000..dfe607b
--- /dev/null
+++ b/test/qgis-qpj.test.js
@@ -0,0 +1,20 @@
+var srs = require('../');
+var fs = require('fs');
+var assert = require('assert');
+
+describe('qgis qpj format', function() {
+    it('detects custom grids inside qgis transverse mercator projection', function(done) {
+        var qgis = srs.parse(fs.readFileSync('./test/data/transverse_merc_kasey_custom_grids.prj'));
+        var normal = srs.parse(fs.readFileSync('./test/data/transverse_merc_kasey.prj'));
+        assert.ok(normal.proj4);
+        assert.ok(qgis.proj4);
+        assert.ok(qgis.proj4.indexOf('nadgrids=@conus') > 0);
+        assert.ok(qgis.proj4.indexOf('proj=tmerc') > 0);
+        assert.ok(qgis.proj4.indexOf('ellps=clrk66') > 0);
+        assert.ok(normal.proj4.indexOf('nadgrids=@conus') == -1);
+        assert.ok(normal.name,'Transverse_Mercator');
+        assert.ok(normal.proj4.indexOf('proj=tmerc') > 0);
+        assert.ok(normal.proj4.indexOf('ellps=clrk66') > 0);
+        done();
+    });
+});
diff --git a/test/shapefile.27700.test.js b/test/shapefile.27700.test.js
index 726bff3..b78ce88 100644
--- a/test/shapefile.27700.test.js
+++ b/test/shapefile.27700.test.js
@@ -1,4 +1,4 @@
-var srs = require('srs');
+var srs = require('../');
 var fs = require('fs');
 var assert = require('assert');
 
@@ -11,17 +11,20 @@ describe('OSGB 1936', function() {
         assert.equal(esri_result.esri,true);
     });
 
-    // https://github.com/springmeyer/node-srs/issues/25
+    // https://github.com/mapbox/node-srs/issues/25
     it('should detect OGC format for OSGB 1936 / British National Grid', function() {
         var ogc_srs = fs.readFileSync('./test/data/27700_ogc_wkt.prj').toString();
         var ogc = srs.parse(ogc_srs);
         assert.equal(ogc.srid,27700);
         assert.equal(ogc.name,'OSGB 1936 / British National Grid');
         assert.equal(ogc.esri,false);
-        assert.equal(ogc.proj4,'+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +datum=OSGB36 +units=m +no_defs');
+        assert.equal(ogc.proj4.indexOf('datum=OSGB36') > -1,true);
+        assert.equal(ogc.proj4.indexOf('proj=tmerc') > -1,true);
+        // not stable across gdal versions
+        //assert.equal(ogc.proj4,'+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +datum=OSGB36 +units=m +no_defs');
     });
 
-    // https://github.com/springmeyer/node-srs/issues/25
+    // https://github.com/mapbox/node-srs/issues/25
     it('should detect correct proj4 for ESRI format for OSGB 1936 / British National Grid', function() {
         var esri_srs = fs.readFileSync('./test/data/27700_esri_wkt.prj').toString();
         // parse by forcing ESRI:: prepend
@@ -31,11 +34,16 @@ describe('OSGB 1936', function() {
         // +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +datum=OSGB36 +units=m +no_defs
         // not:
         // +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +units=m +no_defs
-        var expected = '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +datum=OSGB36 +units=m +no_defs';
-        assert.equal(esri_result.proj4,expected);
+        assert.equal(esri_result.proj4.indexOf('datum=OSGB36') > -1,true);
+        assert.equal(esri_result.proj4.indexOf('proj=tmerc') > -1,true);
+        // not stable across gdal versions
+        //var expected = '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +datum=OSGB36 +units=m +no_defs';
+        //assert.equal(esri_result.proj4,expected);
         // and test parsing without forcing ESRI:: prepend
         var esri_result2 = srs.parse(esri_srs);
-        assert.equal(esri_result2.proj4,expected);
+        //assert.equal(esri_result2.proj4,expected);
+        assert.equal(esri_result2.proj4.indexOf('datum=OSGB36') > -1,true);
+        assert.equal(esri_result2.proj4.indexOf('proj=tmerc') > -1,true);
     });
 
     it('should detect correct srid for ESRI format for OSGB 1936 / British National Grid', function() {
diff --git a/test/shapefile.3857.test.js b/test/shapefile.3857.test.js
index b500e38..1d8ee08 100644
--- a/test/shapefile.3857.test.js
+++ b/test/shapefile.3857.test.js
@@ -1,4 +1,4 @@
-var srs = require('srs');
+var srs = require('../');
 var fs = require('fs');
 var assert = require('assert');
 
@@ -15,7 +15,7 @@ describe('Mercator', function() {
         var srid3349 = '+proj=merc +lon_0=-150 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs';
         var parsed = srs.parse(srid3349);
         assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=merc +lon_0=-150 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
+        assert.equal(parsed.proj4.indexOf('+nadgrids=@null'), -1);
         assert.equal(parsed.srid, not_3857.srid);
         assert.equal(parsed.auth, not_3857.auth);
         assert.equal(parsed.esri, not_3857.esri);
@@ -24,7 +24,7 @@ describe('Mercator', function() {
         var epsg3395 = fs.readFileSync('./test/data/3395-non-spherical-merc.prj').toString();
         parsed = srs.parse(epsg3395);
         assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
+        assert.equal(parsed.proj4.indexOf('+nadgrids=@null'), -1);
         assert.equal(parsed.srid, not_3857.srid);
         assert.equal(parsed.auth, not_3857.auth);
         assert.equal(parsed.esri, not_3857.esri);
@@ -41,7 +41,7 @@ describe('Mercator', function() {
 
     */
 
-    // https://github.com/springmeyer/node-srs/issues/27
+    // https://github.com/mapbox/node-srs/issues/27
     it('should detect qgis/ogr wkt', function() {
         var val = fs.readFileSync('./test/data/3857-ogr-1.10.0-wkt.prj').toString();
         var parsed = srs.parse(val);
diff --git a/test/shapefile.4326.test.js b/test/shapefile.4326.test.js
index c2ee38c..802a0f8 100644
--- a/test/shapefile.4326.test.js
+++ b/test/shapefile.4326.test.js
@@ -1,121 +1,63 @@
-var srs = require('srs');
+var srs = require('../');
 var fs = require('fs');
 var assert = require('assert');
-
-var expected = { srid: 4326, auth: 'EPSG', esri: false, is_geographic: true, valid: true };
+var util = require('./util');
 
 describe('WGS84', function() {
     it('should detect wgs84 proj4 init detection', function() {
-
         var parsed = srs.parse('+init=epsg:4326');
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 proj4 literal from gdal trunk detection', function() {
-
         // +datum=WGS84
         var parsed = srs.parse('+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 proj4 literal +datum will trigger addition to towgs detection', function() {
-
         // +datum will trigger addition to towgs
         var parsed = srs.parse('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs');
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 wkt detection', function() {
 
         var val = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]';
         var parsed = srs.parse(val);
-        assert.equal(parsed.proj4, '+proj=longlat +datum=WGS84 +no_defs');
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 epsg detection', function() {
 
         var parsed = srs.parse('EPSG:4326');
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +datum=WGS84 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 common name detection', function() {
 
         var parsed = srs.parse('WGS84');
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 proj4 literal no datum detection', function() {
 
         var parsed = srs.parse('+proj=longlat +ellps=WGS84 +no_defs');
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +ellps=WGS84 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 wkt from prj file', function() {
 
         var data = fs.readFileSync('./test/data/4326.esri.prj');
         var parsed = srs.parse(data);
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +ellps=WGS84 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
     it('should detect wgs84 wkt from another prj file', function() {
 
         var data = fs.readFileSync('./test/data/4326.prj');
         var parsed = srs.parse(data);
-        assert.ok(parsed.proj4);
-        assert.equal(parsed.proj4, '+proj=longlat +ellps=WGS84 +no_defs');
-        assert.equal(parsed.srid, expected.srid);
-        assert.equal(parsed.auth, expected.auth);
-        assert.equal(parsed.esri, expected.esri);
-        assert.equal(parsed.is_geographic, expected.is_geographic);
-        assert.equal(parsed.valid, expected.valid);
+        util.assert_wgs84(parsed);
     });
 
 });
\ No newline at end of file
diff --git a/test/split_proj.js b/test/split_proj.js
new file mode 100644
index 0000000..8984949
--- /dev/null
+++ b/test/split_proj.js
@@ -0,0 +1,13 @@
+var srs = require('../');
+var assert = require('assert');
+var util = require('./util');
+
+describe('#split_proj', function() {
+    it('splits on spaces', function() {
+        assert.deepEqual(srs.split_proj('a=b'), {a:'b'});
+        assert.deepEqual(srs.split_proj('a=b c=d'), {a:'b',c:'d'});
+        assert.deepEqual(srs.split_proj('a=b c=0'), {a:'b',c:'0.0'});
+        assert.deepEqual(srs.split_proj('a=b c=2.0'), {a:'b',c:'2.0'});
+        assert.deepEqual(srs.split_proj('a=b +bar c=2.0'), {a:'b',c:'2.0'});
+    });
+});
diff --git a/test/util.js b/test/util.js
new file mode 100644
index 0000000..f34b6be
--- /dev/null
+++ b/test/util.js
@@ -0,0 +1,15 @@
+var assert = require('assert');
+var srs = require('../');
+
+function assert_wgs84(parsed) {
+    assert.ok(parsed.proj4);
+    assert.equal(parsed.name, srs.canonical.wgs84.name);
+    assert.equal(parsed.srid, srs.canonical.wgs84.srid);
+    assert.equal(parsed.auth, srs.canonical.wgs84.auth);
+    assert.equal(parsed.esri, srs.canonical.wgs84.esri);
+    assert.equal(parsed.is_geographic, srs.canonical.wgs84.is_geographic);
+    assert.equal(parsed.valid, srs.canonical.wgs84.valid);
+    assert.equal(parsed.proj4, srs.canonical.wgs84.proj4);
+}
+
+exports.assert_wgs84 = assert_wgs84;
diff --git a/test/version.test.js b/test/version.test.js
index 5b921cf..5b014ea 100644
--- a/test/version.test.js
+++ b/test/version.test.js
@@ -1,13 +1,12 @@
-var srs = require('srs');
+var srs = require('../');
 var fs = require('fs');
 var assert = require('assert');
 
-
 describe('Version check', function() {
     it('test version updated for release', function() {
         if (parseInt(process.version.split('.')[1]) > 4) {
             var info = require('../package.json');
             assert.equal(info.version, srs.version);
-        }    
+        }
     });
 });
diff --git a/vcbuild-2014.bat b/vcbuild-2014.bat
new file mode 100644
index 0000000..2cdd8f2
--- /dev/null
+++ b/vcbuild-2014.bat
@@ -0,0 +1,2 @@
+call node_modules\.bin\node-pre-gyp.cmd --msvs_version=2013 --toolset=v140 --dist-url=https://s3.amazonaws.com/mapbox/node-cpp11 --target=0.10.33 build
+call ..\v0.10.33-nodecpp11\Release\node.exe node_modules\mocha\bin\mocha
\ No newline at end of file
diff --git a/vcbuild.bat b/vcbuild.bat
index 4c789b9..58115f8 100644
--- a/vcbuild.bat
+++ b/vcbuild.bat
@@ -1,14 +1,7 @@
-set PROJ_LIB=C:\dev2\proj\nad
-set GDAL_DATA=C:\dev2\gdal\data
-del build.sln
-rd /q /s Default
+set PROJ_LIB=C:\mapnik-v2.3.0\share\proj
+set GDAL_DATA=C:\mapnik-v2.3.0\share\gdal
+rd /q /s build
 del lib\\_srs.node
-rd /q /s lib\\srs_data
-python gyp/gyp build.gyp --depth=. -f msvs -G msvs_version=2010
-msbuild build.sln
-copy Default\\_srs.node lib\\_srs.node
-rem test!
-echo module.exports.static_osr = false; > lib\settings.js
+npm install --nodedir=%HOMEPATH%/.node-gyp/0.10.21-mod
 set NODE_PATH=lib
-node node_modules\mocha\bin\mocha
-rem node -e "console.log(require('mapnik'))"
+npm test

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/node-srs.git



More information about the Pkg-javascript-commits mailing list