
Security News
Follow-up and Clarification on Recent Malicious Ruby Gems Campaign
A clarification on our recent research investigating 60 malicious Ruby gems.
Proforma is a Ruby-based document rendering framework with a focus on being:
The basic premise is you input a dataset and a template and Proforma will:
When a component is in the process of being data-bound it will be evaluated against the current data being read. The evaluator serves two purposes:
The basic evaluator that comes with this library is Proforma::HashEvaluator. It is limited to:
$
then it is noted as being a data-bound value. The value proceeding the $
will be resolved and returned. If it does not begin with this special string then the value following the $ will be resolved and returned.Other libraries that can be plugged in, such as:
See the libraries respective README files for more information.
To install through Rubygems:
gem install install proforma
You can also add this to your Gemfile:
bundle add proforma
The examples in this library will be based on the default plugins that are contained within package and thus will be as bare bones as they can be. See other plugin library documentation to see how the input and output can be greatly enhanced.
The following is a list of components that can be used for modeling:
Most aspects of the components will be data-bound.
Let's say we have a list of users:
data = [
{ id: 1, first: 'Matt', last: 'Smith' },
{ id: 2, first: 'Katie', last: 'Rizzo' },
{ id: 3, first: 'Nathan', last: 'Nathanson' }
]
template = {
title: 'User List',
children: [
{
type: 'DataTable',
columns: [
{ header: 'ID Number', body: '$id' },
{ header: 'First Name', body: '$first' },
{ header: 'Last Name', body: '$last' }
]
}
]
}
documents = Proforma.render(data, template)
The documents
variable will now be an array with only one document object:
documents = [
{
contents: "ID Number, First Name, Last Name\n1, Matt, Smith\n...", # condensed
extension: ".txt",
title: "User List"
)
]
The contents
attribute will be the rendered text-based table.
Let's now say instead of rendering a table we want to render one unique document per record:
data = [
{ id: 1, first: 'Matt', last: 'Smith' },
{ id: 2, first: 'Katie', last: 'Rizzo' },
{ id: 3, first: 'Nathan', last: 'Nathanson' }
]
template = {
title: 'User Details',
split: true, # notice the split directive here.
children: [
{
type: 'Pane',
columns: [
{
lines: [
{ label: 'ID Number', value: '$id' },
{ label: 'First Name', value: '$first' }
]
},
{
lines: [
{ label: 'Last Name', value: '$last' }
]
}
]
}
]
}
documents = Proforma.render(data, template)
The documents
variable will now be an array with three document objects:
documents = [
{
contents: "ID Number: 1\nFirst Name: Matt\nLast Name: Smith\n",
extension: ".txt",
title: "User Details"
},
{
contents: "ID Number: 2\nFirst Name: Katie\nLast Name: Rizzo\n",
extension: ".txt",
title: "User Details"
},
{
contents: "ID Number: 3\nFirst Name: Nathan\nLast Name: Nathanson\n",
extension: ".txt",
title: "User Details"
}
]
Each document will have a contents
attribute that contains its respective rendered text-based pane.
Let's build on our previous user list example and add more data. With this additional data, we will add sub-data tables using grouping:
data = [
{
id: 1,
first: 'Matt',
last: 'Smith',
phone_numbers: [
{ type: 'Mobile', number: '444-333-2222' },
{ type: 'Home', number: '444-333-2222' }
]
},
{
id: 2,
first: 'Katie',
last: 'Rizzo',
phone_numbers: [
{ type: 'Fax', number: '888-777-6666' }
]
},
{
id: 3,
first: 'Nathan',
last: 'Nathanson',
phone_numbers: []
}
]
template = {
title: 'User Report',
children: [
{
type: 'Banner',
title: 'System A',
details: "555 N. Michigan Ave.\nChicago, IL 55555\n555-555-5555 ext. 5132"
},
{ type: 'Header', value: 'User List' },
{ type: 'Separator' },
{ type: 'Spacer' },
{
type: 'DataTable',
columns: [
{ header: 'ID Number', body: '$id' },
{ header: 'First Name', body: '$first' },
{ header: 'Last Name', body: '$last' }
]
},
{ type: 'Spacer' },
{
type: 'Grouping',
children: [
{ type: 'Header', value: 'User Details' },
{ type: 'Separator' },
{ type: 'Spacer' },
{
type: 'Pane',
columns: [
{
lines: [
{ label: 'ID Number', value: '$id' },
{ label: 'First Name', value: '$first' }
]
},
{
lines: [
{ label: 'Last Name', value: '$last' }
]
}
]
},
{
type: 'DataTable',
property: 'phone_numbers',
columns: [
{ header: 'Type', body: '$type' },
{ header: 'Number', body: '$number' }
]
},
{ type: 'Spacer' }
]
}
]
}
documents = Proforma.render(data, template)
The documents
variable will now be an array with only one document object:
documents = [
{
contents: '========================================\nSystem A\n=======Nathan...', # ...
extension: '.txt',
title: 'User Report'
}
]
The contents
attribute will now contain:
The full contents can be seen in this fixture file.
Basic steps to take to get this repository compiling:
To execute the test suite run:
bundle exec rspec spec --format documentation
Alternatively, you can have Guard watch for changes:
bundle exec guard
Also, do not forget to run Rubocop:
bundle exec rubocop
Note: ensure you have proper authorization before trying to publish new versions.
After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
lib/proforma/version.rb
using semantic versioningbundle
CHANGELOG.md
with release notesbundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
This project is MIT Licensed.
FAQs
Unknown package
We found that proforma demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A clarification on our recent research investigating 60 malicious Ruby gems.
Security News
ESLint now supports parallel linting with a new --concurrency flag, delivering major speed gains and closing a 10-year-old feature request.
Research
/Security News
A malicious Go module posing as an SSH brute forcer exfiltrates stolen credentials to a Telegram bot controlled by a Russian-speaking threat actor.