Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
This Node.js module is designed to be a simple API for programatically rendering Bootstrap 4 HTML user interfaces. Outputs clean, formatted code using the EZ HTML module, making it easy to troubleshoot errors.
Highly functional, but still under development. Currently have all HTML 5 elements plus Bootstrap 4 accordians, alerts, badges, anchors, buttons, button checkboxes, button groups, button links, button radios, button toolbars, cards, carousels, columns, collapsable divs, dropdowns, forms, headings, inputs and input sets, jumbotrons, list groups, modals, progress bars, selects, tables, and textareas. For standard HTML 5 elements, see EZ HTML whose objects are passed through in the Strapped, unless they are superseded by Bootstrap 4 components.
In addition, there is a Page object which is a very convenient way to writing short hand web page pages. That is what is being used to draw the example below. Support for some remaining elements will be added soon.
npm install strapped
There is an intuitive, yet slightly ambiguous operating principle behind this library. It is generally expected that the Page object will be used to generate all content. Elements are therefore added by using the defined helper methods, e.g. Page.div(), Page.alert(), Page.button(), etc. As for how these elements get nested, you'll have to learn but the curve should be very low. Most elements default to the last 'Col' (Bootstrap column) created; however, there are several exceptions:
You can also customize the container that a given element will be nested in by passing as the argument the name of the element tag you want to nest in, i.e. p.row('form') will nest a row element in the most recent form element.
If no default is found, and no argument was passed for customized nesting, it will be attached to the root node.
Elements can also be added explicitly by instanciating the objects and appending (or prepending) them as children to other container elements, such as:
const html = new strapped.HTML();
html.append(new strapped.Head());
html.append(new strapped.Body());
html.last('head').append(new strapped.Title().text('My Example Site'));
The library is pretty straightforward and simple, yet powerful. Feel free to dive in the code, or guess at the operating principles and examine the HTML output to verify if things worked as you expect.
const express = require('express');
const strapped = require('strapped');
/** Create express app */
const app = express();
/** Create express path for root of web server '/' */
app.get('/', (req, res, next) => {
/** Create new page */
const p = new strapped.Page();
/** Start content */
p.html();
p.head();
/** Append required Bootstrap 4 meta tags */
p.meta().charset('utf-8');
p.meta().name('viewport').content('width=device-width, initial-scale=1, shrink-to-fit=no');
/** Append example title */
p.title().text('Example Site');
/** Append required Bootstrap 4 JavaScript */
p.script().src('https://code.jquery.com/jquery-3.5.1.slim.js');
p.script().src('https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js');
p.script().src('https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js');
/** Append required Bootstrap 4 CSS */
p.link().rel('stylesheet').href('https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css');
/** Append body */
p.body();
const colors = ['primary', 'secondary', 'success', 'danger', 'warning', 'info'];
/** Example headings */
p.row();
p.col();
p.h1().color('primary').text('Bootstrap Heading');
p.row();
p.col();
p.h2().color('secondary').text('Bootstrap Heading');
p.row();
p.col();
p.h3().color('success').text('Bootstrap Heading');
p.row();
p.col();
p.h4().color('danger').text('Bootstrap Heading');
p.row();
p.col();
p.h5().color('warning').text('Bootstrap Heading');
p.row();
p.col();
p.h6().color('info').text('Bootstrap Heading');
p.lineBreak();
/** Example alerts */
p.row();
p.col().size(8);
p.alert().color('primary').dismissable(true).strong('Hey there!').text('Check this stuff out...');
p.row();
p.col().size(7);
p.alert().color('secondary').dismissable(true).strong('Hey there!').text('Check this stuff out...');
p.row();
p.col().size(6);
p.alert().color('success').dismissable(true).strong('Hey there!').text('Check this stuff out...');
p.row();
p.col().size(5);
p.alert().color('danger').strong('Hey there!').text('Check this stuff out...');
p.row();
p.col().size(4);
p.alert().color('warning').strong('Hey there!').text('Check this stuff out...');
p.row();
p.col().size(3);
p.alert().color('info').strong('Hey there!').text('Check this stuff out...');
p.lineBreak();
/** Example buttons */
p.row();
p.col().size(8).center(true);
p.button().id('test-button').color('primary').text('Button');
p.badge('button').color('light').text('1');
p.button().color('secondary').text('Button');
p.badge('button').color('light').text('2');
p.button().color('success').text('Button');
p.badge('button').color('light').text('3');
p.button().color('danger').text('Button');
p.badge('button').color('light').text('4');
p.button().color('warning').text('Button');
p.badge('button').color('light').text('5');
p.button().color('info').text('Button');
p.badge('button').color('light').text('6');
p.lineBreak();
/** Example button toolbar with button groups including button radios and checkboxes */
p.row();
p.col().size(6).center(true);
p.buttonToolbar().addClass('justify-content-between');
p.buttonGroup('buttonToolbar').toggle(true);
p.buttonRadio('buttonGroup').color('primary').name('test').id('test1').text('Test 1').active(true);
p.buttonRadio('buttonGroup').color('secondary').name('test').id('test2').text('Test 2');
p.buttonRadio('buttonGroup').color('success').name('test').id('test3').text('Test 3');
p.buttonGroup('buttonToolbar').toggle(true);
p.buttonCheckbox('buttonGroup').color('danger').name('test4').id('test4').text('Test 4').active(true);
p.buttonCheckbox('buttonGroup').color('warning').name('test5').id('test5').text('Test 5');
p.buttonCheckbox('buttonGroup').color('info').name('test6').id('test6').text('Test 6');
p.lineBreak();
/** Example cards */
p.row();
p.col().size(8);
p.cardDeck();
for ( let i = 0; i < 6; i += 2 ) {
p.card('cardDeck');
p.cardImage().src('/images/example.svg');
p.cardBody();
p.h5('cardBody').addClass('card-title').text('Card Example');
p.paragraph('cardBody').addClass('card-text').text(`Some quick example text to build on the card title and make up the bulk of the card's content`);
p.buttonLink('cardBody').color(colors[i]).href('#').text('Go somewhere');
p.cardFooter().text('Last updated 3 mins ago');
}
p.lineBreak();
/** Example collapsable accordian */
p.row();
p.col().size(4);
p.accordian().id('accordian');
for ( let i = 0; i < 3; i++ ) {
p.card('accordian');
p.cardHeader();
p.h5('cardHeader').addClass('mb-0');
if ( i == 0 )
p.anchor('h5').collapses(`#accordian-${i}`).text(`Accordian ${i + 1}`);
else
p.anchor('h5').addClass('collapsed').collapses(`#accordian-${i}`).text(`Accordian ${i + 1}`);
if ( i == 0 )
p.collapse('card').addClass('show').id(`accordian-${i}`).attr('data-parent', `#accordian`);
else
p.collapse('card').id(`accordian-${i}`).attr('data-parent', `#accordian`);
p.cardBody('collapse');
p.paragraph('cardBody').addClass('card-text').text('Some quick example text to provide sample content for this accordian collapsable card body.');
}
p.lineBreak();
/** Example carousel */
p.row();
p.col(8).size(8);
p.carousel().id('carousel').controls(true).indicators(true);
p.carouselItem().src('/images/example2.svg').alt('First Slide').caption('First Slide').description('This is the first slide description');
p.carouselItem().src('/images/example2.svg').alt('Second Slide').caption('Second Slide').description('This is the second slide description');
p.carouselItem().src('/images/example2.svg').alt('Third Slide').caption('Third Slide').description('This is the third slide description');
p.lineBreak();
/** Examples row with split cols */
p.row();
p.col().size(5);
p.row('col');
p.col().size(6);
p.card();
p.cardHeader().text('Test Card');
p.cardBody();
p.paragraph('cardBody').addClass('card-text').text('Some quick example text to provide sample content for this column split card body.');
p.col().size(6);
p.card();
p.cardHeader().text('Test Card');
p.cardBody();
p.paragraph('cardBody').addClass('card-text').text('Some quick example text to provide sample content for this column split card body.');
p.col('parent').size(5);
p.card();
p.cardHeader().text('Test Card');
p.cardBody();
p.paragraph('cardBody').addClass('card-text').text('Some quick example text to provide sample content for this column split card body.');
p.lineBreak();
/** Example dropdowns */
p.row();
p.col().size(8).center(true);
colors.forEach((color) => {
p.button().color(color).text('Dropdown').togglesDropdown(true);
p.dropdownMenu();
p.h6('dropdownMenu').addClass('dropdown-header').text('Section 1');
p.anchor('dropdownMenu').addClass(`dropdown-item`).href('#').text('Action');
p.anchor('dropdownMenu').addClass(`dropdown-item`).href('#').text('Another Action');
p.div('dropdownMenu').addClass('dropdown-divider');
p.h6('dropdownMenu').addClass('dropdown-header').text('Section 2');
p.anchor('dropdownMenu').addClass(`dropdown-item`).href('#').text('More Actions');
p.anchor('dropdownMenu').addClass(`dropdown-item`).href('#').text('Last Action');
});
p.lineBreak();
/** Example standard form */
p.row();
p.col();
p.h2().color('primary').text('Example Standard Form');
p.row();
p.col().size(4).left(true);
p.form().action('/quoting/test').method('GET');
p.input().id('text').name('text').label('Example Text').type('text').placeholder('Example Placeholder');
p.input().id('password').name('password').label('Example Password').type('password');
p.row('form');
p.input('row').cols(6).id('color').name('color').label('Example Color').type('color').addClass('p-0');
p.input('row').cols(6).id('date').name('date').label('Example Date').type('date');
p.row('form');
p.input('row').cols(9).id('range').name('range').label('Example Range').type('range').max(100);
p.col().size(3).center(true);
p.lineBreak('col');
p.div().id('range-out').addClass('pt-2').text('50');
p.inputSet();
p.input('inputSet').id('checkbox').name('checkbox').label('Example Checkbox').type('checkbox').checked(true);
p.textarea().id('textarea').name('textarea').label('Example TextArea').placeholder('I can hold a lot of text...').rows(3);
p.input().id('money').name('money').pattern('[0-9]+').value(0).type('text').before('$').after('.00').label('Example Input Group');
p.row('form');
p.col().size(3).center(true);
p.button().color('danger').type('reset').text('Reset');
p.col().size(3).center(true);
p.button().color('success').type('submit').text('Submit');
p.lineBreak();
/** Example horizontal form */
p.row();
p.col();
p.h2().color('primary').text('Example Horizontal Form').addClass('pb-2');
p.row();
p.col().size(4).left(true);
p.form().action('/quoting/test').method('GET');
p.input().id('first-name').name('first-name').label('First Name:').type('text').labelCols(4).inputCols(6).horizontal(true);
p.input().id('last-name').name('last-name').label('Last Name:').type('text').labelCols(4).inputCols(6).horizontal(true);
p.input().id('email').name('email').label('Email:').type('email').labelCols(4).inputCols(8).horizontal(true);
p.input().id('tel').name('tel').label('Telephone:').type('tel').before('+1').labelCols(4).inputCols(6).horizontal(true);
p.row('form');
p.col().size(4).text('Sex:').addClass('col-form-label pt-0');
p.col().size(8);
p.inputSet('col');
p.input('inputSet').id('male').name('sex').type('radio').label('Male');
p.input('inputSet').id('female').name('sex').type('radio').label('Female');
p.select().id('department').name('department').label('Department:').labelCols(4).inputCols(6).horizontal(true);
p.option().value('engineering').text('Engineering');
p.option().value('quality').text('Quality').selected(true);
p.option().value('materials').text('Materials');
p.option().value('manufacturing').text('Manufacturing');
p.row('form');
p.col().size(3).center(true);
p.button().color('danger').type('reset').text('Reset');
p.col().size(3).center(true);
p.button().color('success').type('submit').text('Submit');
p.lineBreak();
/** Example inline form */
p.row();
p.col();
p.h2().color('primary').text('Example Inline Form').addClass('pb-2');
p.row();
p.col();
p.form().action('/quoting/test').method('GET').inline(true);
p.input().id('username').name('username').type('text').placeholder('Username');
p.input().id('password').name('password').type('password').placeholder('Password').addClass('mx-3');
p.button('form').color('primary').type('submit').text('Login');
p.lineBreak();
/** Example jumbotron */
p.row();
p.col().size(8);
p.jumbotron();
p.h1('jumbotron').display(4).text('Example Jumbotron');
p.paragraph('jumbotron').addClass('lead').text('This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.');
p.horizontalRule('jumbotron');
p.paragraph('jumbotron').text('It uses utility classes for typography and spacing to space content out within the larger container.');
p.button('jumbotron').color('info').size('lg').text('Learn more');
p.lineBreak();
/** Example progress bars */
p.row();
p.col().size(8);
p.progressBar().color('primary').percent(10);
p.lineBreak('col');
p.progressBar().color('success').percent(25);
p.lineBreak('col');
p.progressBar().color('info').striped(true).percent(50);
p.lineBreak('col');
p.progressBar().color('warning').striped(true).percent(75);
p.lineBreak('col');
p.progressBar().color('danger').striped(true).percent(100).animated(true);
p.lineBreak();
/** Example modal */
p.row();
p.col();
p.button().color('danger').attr('data-toggle', 'modal').attr('data-target', '#modal').text('Launch Modal');
p.modal().id('modal').middle(true);
p.modalHeader();
p.h5('modalHeader').addClass(`modal-title`).text('Hello Modal');
p.button('modalHeader').addClass('close').attr('data-dismiss', 'modal').text('×');
p.modalBody().text('This is an example modal box that might be used to confirm changes, or provide a sub-form for a main form.');
p.modalFooter();
p.button('modalFooter').color('secondary').attr('data-dismiss', 'modal').text('Close');
p.button('modalFooter').color('primary').text('Save Changes');
p.lineBreak();
/** Example JavaScript handlers (these are automatically wrapped in a $( document ).ready() block) */
p.script().append(() => {
$( '#test-button' ).click(() => {
alert('Test!');
});
$( '#range' ).on('input', () => {
$( '#range-out' ).html($( '#range' ).val());
});
});
res.send(p.render());
});
/** Start express listening */
app.listen(3000, () => {
console.log(`Express is listening on port 3000!`);
});
FAQs
Node.js Bootstrap Implementation Using EZ HTML
We found that strapped demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers 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.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.