Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

enketo-transformer

Package Overview
Dependencies
Maintainers
1
Versions
127
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

enketo-transformer - npm Package Compare versions

Comparing version 1.0.9 to 1.1.0

setup/bootstrap.sh

63

app.js

@@ -1,9 +0,11 @@

var express = require( 'express' ),
app = express(),
Q = require( 'q' ),
request = require( 'request' ),
transformer = require( './src/transformer' ),
debug = require( 'debug' )( 'app.js' ),
config = require( './config/config.json' );
'use strict';
var express = require( 'express' );
var app = express();
var Promise = require( 'q' ).Promise;
var request = require( 'request' );
var transformer = require( './src/transformer' );
var debug = require( 'debug' )( 'app.js' );
var config = require( './config/config.json' );
for ( var item in config ) {

@@ -49,32 +51,31 @@ app.set( item, config[ item ] );

function _request( options ) {
var error,
deferred = Q.defer();
var method;
var error;
// set headers
options.headers = options.headers || {};
options.headers[ 'X-OpenRosa-Version' ] = '1.0';
var method = options.method || 'get';
method = options.method || 'get';
request[ method ]( options, function( error, response, body ) {
if ( error ) {
debug( 'Error occurred when requesting ' + options.url, error );
deferred.reject( error );
} else if ( response.statusCode === 401 ) {
error = new Error( 'Forbidden. Authorization Required.' );
error.status = response.statusCode;
deferred.reject( error );
} else if ( response.statusCode < 200 || response.statusCode >= 300 ) {
error = new Error( 'Request to ' + options.url + ' failed.' );
error.status = response.statusCode;
deferred.reject( error );
} else {
debug( 'response of request to ' + options.url + ' has status code: ', response.statusCode );
deferred.resolve( {
xform: body
} );
}
return new Promise( function( resolve, reject ) {
request[ method ]( options, function( error, response, body ) {
if ( error ) {
debug( 'Error occurred when requesting ' + options.url, error );
reject( error );
} else if ( response.statusCode === 401 ) {
error = new Error( 'Forbidden. Authorization Required.' );
error.status = response.statusCode;
reject( error );
} else if ( response.statusCode < 200 || response.statusCode >= 300 ) {
error = new Error( 'Request to ' + options.url + ' failed.' );
error.status = response.statusCode;
reject( error );
} else {
debug( 'response of request to ' + options.url + ' has status code: ', response.statusCode );
resolve( {
xform: body
} );
}
} );
} );
return deferred.promise;
}
{
"name": "enketo-transformer",
"version": "1.0.9",
"version": "1.1.0",
"description": "Library that transforms ODK-compliant XForms in a format that enketo-core consumes",

@@ -27,11 +27,10 @@ "main": "src/transformer.js",

"author": "Martijn van de Rijdt",
"license": "Apache2",
"license": "Apache-2.0",
"dependencies": {
"debug": "2.1.x",
"enketo-xslt": "1.0.8",
"debug": "2.2.x",
"enketo-xslt": "1.1.0",
"express": "4.12.x",
"libxmljs": "0.14.x",
"node_xslt": "0.1.x",
"libxslt": "0.4.x",
"q": "2.0.x",
"request": "2.55.x"
"request": "2.58.x"
},

@@ -38,0 +37,0 @@ "devDependencies": {

@@ -8,4 +8,3 @@ Enketo Transformer [![Build Status](https://travis-ci.org/enketo/enketo-transformer.svg?branch=master)](https://travis-ci.org/enketo/enketo-transformer) [![Dependency Status](https://david-dm.org/enketo/enketo-transformer.svg)](https://david-dm.org/enketo/enketo-transformer)

1. Node v0.10.x is required. There is an [outstanding issue with Node v0.12.x](https://github.com/bsuh/node_xslt/issues/24).
2. Install libxslt and libxml2 with `(sudo) apt-get install libxml2-dev libxslt1-dev`
1. Node v0.10.x is required for now. There is an [outstanding issue with Node v0.12.x](https://github.com/albanm/node-libxslt/issues/15).

@@ -53,1 +52,5 @@ ## Install as module

* run tests with `npm test`
## Develop
A vagrant configuration file and provisioning script is included.

@@ -1,17 +0,20 @@

/* global setTimeout */
"use strict";
var version,
Q = require( 'q' ),
fs = require( 'fs' ),
crypto = require( 'crypto' ),
transformer = require( 'node_xslt' ),
libxmljs = require( "libxmljs" ),
sheets = require( 'enketo-xslt' ),
debug = require( 'debug' )( 'transformer' );
var Promise = require( 'q' ).Promise;
var fs = require( 'fs' );
var crypto = require( 'crypto' );
var libxslt = require( 'libxslt' );
var libxmljs = libxslt.libxmljs;
var sheets = require( 'enketo-xslt' );
var debug = require( 'debug' )( 'transformer' );
var xslFormDoc = libxmljs.parseXml( sheets.xslForm, {
nocdata: true
} );
var xslModelDoc = libxmljs.parseXml( sheets.xslModel, {
nocdata: true
} );
var version = _getVersion();
_setVersion();
/**
* Performs XSLT transformation on XForm asynchronously.
* Performs XSLT transformation on XForm and process the result.
*

@@ -22,54 +25,89 @@ * @param {{xform: string, theme: string}} survey Survey object with at least an xform property

function transform( survey ) {
var error, errorMsg, doc, formStylesheet, instanceStylesheet, xsltEndTime,
deferred = Q.defer(),
startTime = new Date().getTime();
var xsltEndTime;
var xformDoc;
var startTime = new Date().getTime();
// make this asynchronous, sort of
setTimeout( function() {
try {
doc = transformer.readXmlString( survey.xform );
return _parseXml( survey.xform )
.then( function( doc ) {
xformDoc = doc;
return _transform( xslFormDoc, xformDoc );
} )
.then( function( htmlDoc ) {
htmlDoc = _replaceTheme( htmlDoc, survey.theme );
htmlDoc = _replaceMediaSources( htmlDoc, survey.manifest );
// TODO: does this result in self-closing tags?
survey.form = htmlDoc.root().get( '*' ).toString( false );
formStylesheet = transformer.readXsltString( sheets.xslForm );
survey.form = _stripRoot( transformer.transform( formStylesheet, doc, [ 'wtf', 'why' ] ) );
return _transform( xslModelDoc, xformDoc );
} )
.then( function( xmlDoc ) {
xmlDoc = _replaceMediaSources( xmlDoc, survey.manifest );
instanceStylesheet = transformer.readXsltString( sheets.xslModel );
survey.model = _stripRoot( transformer.transform( instanceStylesheet, doc, [ 'wtf', 'why' ] ) );
survey.model = xmlDoc.root().get( '*' ).toString( false );
xsltEndTime = new Date().getTime();
debug( 'form and instance XSLT transformation took ' + ( xsltEndTime - startTime ) / 1000 + ' seconds' );
delete survey.xform;
return survey;
} );
}
survey.form = _replaceTheme( survey.form, survey.theme );
/**
* Performs a generic XSLT transformation
*
* @param {[type]} xslDoc libxmljs object of XSL stylesheet
* @param {[type]} xmlDoc libxmljs object of XML document
* @return {Promise} libxmljs result document object
*/
function _transform( xslDoc, xmlDoc ) {
return new Promise( function( resolve, reject ) {
libxslt.parse( xslDoc, function( error, stylesheet ) {
if ( error ) {
reject( error );
} else {
stylesheet.apply( xmlDoc, function( error, result ) {
if ( error ) {
reject( error );
} else {
resolve( result );
}
} );
}
} );
} );
}
survey.form = _replaceMediaSources( survey.form, survey.manifest );
survey.model = _replaceMediaSources( survey.model, survey.manifest );
debug( 'post-processing transformation result took ' + ( new Date().getTime() - xsltEndTime ) / 1000 + ' seconds' );
/**
* Parses and XML string into a libxmljs object
*
* @param {string} xmlStr XML string
* @return {Promise} libxmljs result document object
*/
function _parseXml( xmlStr ) {
var doc;
delete survey.xform;
deferred.resolve( survey );
return new Promise( function( resolve, reject ) {
try {
doc = libxmljs.parseXml( xmlStr );
resolve( doc );
} catch ( e ) {
error = ( e ) ? new Error( e ) : new Error( 'unknown transformation error' );
debug( 'error during xslt transformation', error );
deferred.reject( error );
reject( e );
}
}, 0 );
return deferred.promise;
} );
}
function _stripRoot( xml ) {
var xmlDoc = libxmljs.parseXml( xml );
return xmlDoc.root().get( '*' ).toString( false );
}
function _replaceTheme( xml, theme ) {
var doc, formClassAttr, formClassValue,
/**
* Replaces the form-defined theme
*
* @param {[type]} doc libxmljs object
* @param {string} theme theme
* @return {[type]} libxmljs object
*/
function _replaceTheme( doc, theme ) {
var formClassAttr, formClassValue,
HAS_THEME = /(theme-)[^"'\s]+/;
if ( !theme ) {
return xml;
return doc;
}
doc = libxmljs.parseXml( xml );
formClassAttr = doc.root().get( '/form' ).attr( 'class' );
formClassAttr = doc.root().get( '/root/form' ).attr( 'class' );
formClassValue = formClassAttr.value();

@@ -83,17 +121,20 @@

// TODO: probably result in selfclosing tags for empty elements where not allowed in HTML. Check this.
return doc.toString();
return doc;
}
function _replaceMediaSources( xmlStr, manifest ) {
var doc;
/**
* Replaces xformManifest urls with URLs according to an internal Enketo Express url format
*
* @param {[type]} xmlDoc libxmljs object
* @param {*} manifest json representation of XForm manifest
* @return {Promise} libxmljs object
*/
function _replaceMediaSources( xmlDoc, manifest ) {
if ( !manifest ) {
return xmlStr;
return xmlDoc;
}
doc = libxmljs.parseXml( xmlStr );
// iterate through each element with a src attribute
doc.find( '//*[@src]' ).forEach( function( mediaEl ) {
xmlDoc.find( '//*[@src]' ).forEach( function( mediaEl ) {
manifest.some( function( file ) {

@@ -110,3 +151,3 @@ if ( new RegExp( 'jr://(images|video|audio|file|file-csv)/' + file.filename ).test( mediaEl.attr( 'src' ).value() ) ) {

manifest.some( function( file ) {
var formLogoEl = doc.get( '//*[@class="form-logo"]' );
var formLogoEl = xmlDoc.get( '//*[@class="form-logo"]' );
if ( file.filename === 'form_logo.png' && formLogoEl ) {

@@ -121,4 +162,3 @@ formLogoEl

// TODO: probably result in selfclosing tags for empty elements where not allowed in HTML. Check this.
return doc.toString();
return xmlDoc;
}

@@ -143,7 +183,4 @@

*/
function _setVersion() {
// only perform this expensive check once after (re)starting application
if ( !version ) {
version = _md5( sheets.xslForm + sheets.xslModel );
}
function _getVersion() {
return _md5( sheets.xslForm + sheets.xslModel );
}

@@ -150,0 +187,0 @@

@@ -43,3 +43,3 @@ /* global describe, require, it*/

} );
return expect( result ).to.eventually.be.rejectedWith( Error, /parse/ );
return expect( result ).to.eventually.be.rejectedWith( Error );
} );

@@ -46,0 +46,0 @@ } );

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc