mockupsNode

Node JS module for creating and manipulating Balsamiq BMML files

Available for Node 32bit on Windows, complete 32/64bit support for Windows, MAC, Linux coming soon

mockupsNode is a binary module for Node JS that can read, modify, and write Balsamiq BMML files. It has an easy to use API and objects for each control type exposing the same properties that can be modified within Balsamiq .

Using this module you can automate bulk processing of many BMML files and quickly do things that would be very time consuming to do within Balsamiq itself, such as:

  • Add a watermark to many files
  • Quickly change properties of many controls e.g. you want to change the color of all the buttons
  • Create mockups from other inputs, or generate mockups from templates
  • Export mockups to different formats e.g. a code generator

mockupsNode can be downloaded and used for free with minor restrictions on usage. Purchase a license to unlock full functionality.

Installation

You can either:

Download the appropriate platform package and unzip into your node_modules directory, or

Install via NPM: npm install mockupsnode.

mockupsnode is a binary only module. After the base package is downloaded from the npm repository the appropriate binaries for your node platform will be downloaded from our servers.

Usage

Set your license key to unlock full functionality

var mn = require('mockupsnode');
mn.setLicense('<insert license key here>');
console.log('Licensed to: ' + mn.licenseInfo);
//  Licensed to: Tim Shnaider
          

Open a BMML file and recurse through it, outputting to console the control hierarchy and some properties, save it to a different file

var mn = require('mockupsnode');
var mockup = mn.openMockup('/temp/file.bmml');
mockup.controls.forEach(function(control,i)
{
	var depthIndent = Array(getDepth(control)+1).join('-');
	console.log('%sControl #%d: %s (pos:%d,%d,size:%d,%d)', depthIndent,i, control.controlType, control.x,control.y, 
		control.width, control.height);
}, true /* recurse through groups*/)
mockup.saveMockup('/temp/fileout.bmml');

function getDepth(c)
{
	var depth = 0;
	c = c.parent.parent; // skip the parent collection
	while ( c instanceof mn.Control )
	{
		depth++;
		c = c.parent.parent;
	}
	return depth;
}

// Output
// Control #0: iPhone (pos:179,391,size:282,510)
// Control #1: Button (pos:1234,199,size:60,24)
// Control #2: __group__ (pos:258,154,size:799,346)
// -Control #0: MediaControls (pos:5,0,size:110,36)
// -Control #1: __group__ (pos:463,157,size:336,189)
// --Control #0: Alert (pos:0,0,size:200,113)
// --Control #1: ComboBox (pos:242,165,size:94,24)
// -Control #2: Alert (pos:225,29,size:200,113)
// Control #3: ProgressBar (pos:0,66,size:100,20)
// Control #4: Button (pos:100,200,size:75,24)
	  

Add and remove controls

var mn = require('mockupsnode');
var m = mn.newMockup();
var newC = new mn.ControlButton();
newC.x = 100;
newC.y = 200;
newC.color = "Red";
newC.width = 80;
newC.text = "Hello!";
newC.height = 75;
newC.state = mn.ButtonState.Disabled;
console.log('Control count: %d',m.controls.length);
console.log(newC);
m.controls.add(newC);
console.log('Control count: %d',m.controls.length);
console.log(m.controls[0]);
m.controls.remove(m.controls[0]);
console.log('Control count: %d',m.controls.length);

// Output
// Control count: 0
// { fontSize: 13,
//   links: { parent: [Circular], objectType: 'Links' },
//   hRef: '',
//   italic: false,
//   locked: false,
//   state: 3,
//   menuIcon: false,
//   color: '#ff0000',
//   map: '',
//   parent: null,
//   controlType: 'Button',
//   text: 'Hello!',
//   bold: false,
//   groupId: -1,
//   y: 200,
//   objectType: 'Control',
//   customId: '',
//   measuredHeight: 24,
//   iconSize: 1,
//   textAlign: 0,
//   icon: '',
//   underline: false,
//   height: 24,
//   x: 100,
//   width: 75,
//   z: 0,
//   id: -1,
//   customData: '',
//   measuredWidth: 60 }
// Control count: 1
// Control count: 0
	  
	  

Move controls around

m.controls.moveToTop(m.controls[2]);
m.controls.moveBefore(m.controls[0], m.controls[2]);
m.controls.moveAfter(m.controls[1], m.controls[0]);
m.controls.moveToBottom(m.controls[1]);
m.controls.moveForward(m.controls[1]);
m.controls.moveBackward(m.controls[1]);

// Move control to different collection, in this case a Group
m.controls.add(m.controls[2].controls[1]);

	  

mockupsNode is licensed software.

The module runs in Unlicensed mode until a license key has been set via mockupsnode.setLicense(). The only restriction when unlicensed is controls that have a Y location > 500px are excluded on save.

Purchase license (available from November 23)

View mockupsNode license

We have included scripts in the examples directory with the package

You can also find a growing library of scripts on the nimbleScript marketplace. Extract the code from the run() function to use in regular node js code

View scripts on the marketplace