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

himalaya

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

himalaya - npm Package Compare versions

Comparing version 0.2.2 to 0.2.3

.babelrc

97

bin/himalaya.js
#!/usr/bin/env node
(function () {
function help () {
/*
Usage: himalaya [file] [dest]
function help() {
/*
Usage: himalaya [file] [dest]
(no args): pipe in HTML, pipe out JSON

@@ -16,55 +16,56 @@ file: HTML file location

*/
}
}
var fs = require('fs');
var path = require('path');
var himalaya = require('..');
var fs = require('fs')
var path = require('path')
var himalaya = require('..')
var args = process.argv.slice(2);
var root = process.cwd();
var args = process.argv.slice(2)
var root = process.cwd()
function toJSON(data) {
return JSON.stringify(data, null, 2);
}
function toJSON (data) {
return JSON.stringify(data, null, 2)
}
if(!args.length) {
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(text) {
var data = himalaya.parse(text);
var json = toJSON(data);
process.stdout.write(json);
});
process.stdin.on('end', function() {
process.exit(0);
});
return;
}
if (!args.length) {
process.stdin.resume()
process.stdin.setEncoding('utf8')
process.stdin.on('data', function (text) {
var data = himalaya.parse(text)
var json = toJSON(data)
process.stdout.write(json)
})
process.stdin.on('end', function () {
process.exit(0)
})
return
}
var flag = args[0].toLowerCase();
var flag = args[0].toLowerCase()
if(flag === '-h' || flag === '--help') {
var h = help.toString();
var msg = h.substring(h.indexOf('*') + 2, h.lastIndexOf('*'));
return console.log(msg);
}
if (flag === '-h' || flag === '--help') {
var h = help.toString()
var msg = h.substring(h.indexOf('*') + 2, h.lastIndexOf('*'))
return console.log(msg)
}
if(flag === '-v' || flag === '--version') {
var pkg = require('../package.json');
return console.log(pkg.version);
}
if (flag === '-v' || flag === '--version') {
var pkg = require('../package.json')
return console.log(pkg.version)
}
var src = path.join(root, args[0]);
var dest = args[1]
? path.join(root, args[1])
: null;
var src = path.join(root, args[0])
var dest = args[1]
? path.join(root, args[1])
: null
var text = fs.readFileSync(src);
var data = himalaya.parse(text);
var cout = toJSON(data);
var text = fs.readFileSync(src)
var data = himalaya.parse(text)
var cout = toJSON(data)
if(dest) {
fs.writeFileSync(dest, cout);
} else {
console.log(cout);
}
if (dest) {
fs.writeFileSync(dest, cout)
} else {
console.log(cout)
}
})()
{
"name": "himalaya",
"version": "0.2.2",
"description": "HTML to JSON parser",
"main": "index.js",
"version": "0.2.3",
"author": "Chris Andrejewski <christopher.andrejewski@gmail.com>",
"bin": {
"himalaya": "./bin/himalaya.js"
},
"scripts": {
"test": "mocha",
"himalaya": "./bin/himalaya.js"
"bugs": {
"url": "https://github.com/andrejewski/himalaya/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/andrejewski/himalaya.git"
"dependencies": {
"paul": "0.0.3"
},
"devDependencies": {
"ava": "^0.16.0",
"babel-polyfill": "^6.16.0",
"babel-preset-es2015": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
"babel-regenerator-runtime": "^6.5.0",
"del": "^2.2.2",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-sourcemaps": "^2.1.1",
"source-map-support": "^0.4.3",
"standard": "^8.4.0"
},
"homepage": "https://github.com/andrejewski/himalaya",
"keywords": [
"ast",
"html",
"parser",
"ast",
"json"
"json",
"parser"
],
"author": "Chris Andrejewski <christopher.andrejewski@gmail.com>",
"license": "ISC",
"bugs": {
"url": "https://github.com/andrejewski/himalaya/issues"
"main": "lib/index.js",
"repository": {
"type": "git",
"url": "https://github.com/andrejewski/himalaya.git"
},
"homepage": "https://github.com/andrejewski/himalaya",
"devDependencies": {
"mocha": "^3.1.0"
},
"dependencies": {
"paul": "0.0.3"
"scripts": {
"himalaya": "./bin/himalaya.js",
"prepublish": "standard --fix && fixpack && npm run test",
"test": "gulp --silent && ava"
}
}

@@ -1,267 +0,144 @@

var h = require('../');
var assert = require('assert');
import test from 'ava'
import himalaya from '../'
function print(s) {
console.log(JSON.stringify(s, null, 2));
}
/*
These tests mainly serve as a gauntlet for generic use.
Do not add any more of these kinds of tests, instead
test the more granular bits.
// README demo
// print(h.parse(["<div class='post post-featured'><p>Himalaya parsed me...</p><!-- ...and I liked it. --></div>"]));
// return;
TODO: remove overlapping tests
*/
describe('himalaya', function() {
describe('parse(String) Object', function() {
it('should return the AST of given HTML', function() {
var h1 = "<html><h1>Hello, World</h1></html>";
var d1 = [{
type: 'Element',
tagName: 'html',
attributes: {},
children: [{
type: 'Element',
tagName: 'h1',
attributes: {},
children: [{
type: 'Text',
content: 'Hello, World'
}]
}]
}];
assert.deepEqual(d1, h.parse(h1));
test('parse() should pass the Hello World case', t => {
const html = '<html><h1>Hello, World</h1></html>'
const data = [{
type: 'Element',
tagName: 'html',
attributes: {},
children: [{
type: 'Element',
tagName: 'h1',
attributes: {},
children: [{
type: 'Text',
content: 'Hello, World'
}]
}]
}]
t.deepEqual(data, himalaya.parse(html))
})
var h2 = "<div class='section widget'><b disabled>Poop</b><p>Pee</p></div>";
var d2 = [{
type: 'Element',
tagName: 'div',
attributes: {
className: ['section', 'widget']
},
children: [{
type: 'Element',
tagName: 'b',
attributes: {
disabled: 'disabled'
},
children: [{
type: 'Text',
content: 'Poop'
}]
}, {
type: 'Element',
tagName: 'p',
attributes: {},
children: [{
type: 'Text',
content: 'Pee'
}]
}]
}];
assert.deepEqual(d2, h.parse(h2));
test('parse() should work for mixed attributes', t => {
const html = "<div class='section widget'><b disabled>Poop</b><p>Pee</p></div>"
const data = [{
type: 'Element',
tagName: 'div',
attributes: {
className: ['section', 'widget']
},
children: [{
type: 'Element',
tagName: 'b',
attributes: {
disabled: 'disabled'
},
children: [{
type: 'Text',
content: 'Poop'
}]
}, {
type: 'Element',
tagName: 'p',
attributes: {},
children: [{
type: 'Text',
content: 'Pee'
}]
}]
}]
t.deepEqual(data, himalaya.parse(html))
})
var h3 = "<b><!--comment text-->words</b>";
var d3 = [{
type: 'Element',
tagName: 'b',
attributes: {},
children: [{
type: 'Comment',
content: 'comment text'
}, {
type: 'Text',
content: 'words'
}]
}];
assert.deepEqual(d3, h.parse(h3));
test('parse() should work for commented html', t => {
const html = '<b><!--comment text-->words</b>'
const data = [{
type: 'Element',
tagName: 'b',
attributes: {},
children: [{
type: 'Comment',
content: 'comment text'
}, {
type: 'Text',
content: 'words'
}]
}]
t.deepEqual(data, himalaya.parse(html))
})
var h4 = "<div style='width: 360px; height: 120px; background-color: #fff'></div>";
var d4 = [{
type: 'Element',
tagName: 'div',
attributes: {
style: {
width: '360px',
height: '120px',
backgroundColor: '#fff'
}
},
children: []
}];
assert.deepEqual(d4, h.parse(h4));
test('parse() should work for style properties', t => {
const html = "<div style='width: 360px; height: 120px; background-color: #fff'></div>"
const data = [{
type: 'Element',
tagName: 'div',
attributes: {
style: {
width: '360px',
height: '120px',
backgroundColor: '#fff'
}
},
children: []
}]
t.deepEqual(data, himalaya.parse(html))
})
var h5 = "<div data-num=0 data-word='poop' data-cake='2'></div>";
var d5 = [{
type: 'Element',
tagName: 'div',
attributes: {
dataset: {
num: 0,
word: 'poop',
cake: 2
}
},
children: []
}];
assert.deepEqual(d5, h.parse(h5));
test('parse() should work on data-* attributes', t => {
const html = "<div data-num=0 data-word='poop' data-cake='2'></div>"
const data = [{
type: 'Element',
tagName: 'div',
attributes: {
dataset: {
num: 0,
word: 'poop',
cake: 2
}
},
children: []
}]
t.deepEqual(data, himalaya.parse(html))
})
var h6 = "<p>One two<p>three four";
var d6 = [{
type: 'Element',
tagName: 'p',
attributes: {},
children: [{
type: 'Text',
content: 'One two'
}]
}, {
type: 'Element',
tagName: 'p',
attributes: {},
children: [{
type: 'Text',
content: 'three four'
}]
}];
assert.deepEqual(d6, h.parse(h6));
});
});
test('should work on unclosed tags', t => {
const html = '<p>One two<p>three four'
const data = [{
type: 'Element',
tagName: 'p',
attributes: {},
children: [{
type: 'Text',
content: 'One two'
}]
}, {
type: 'Element',
tagName: 'p',
attributes: {},
children: [{
type: 'Text',
content: 'three four'
}]
}]
t.deepEqual(data, himalaya.parse(html))
})
describe('parseTag(String, Array[String]) Object', function() {
describe('return {stack: Array[Name]}', function() {
it('should be the given stack for void elements', function() {
var text = '<meta charset="utf8">';
var s1 = [];
var s2 = ['root'];
assert.deepEqual(s1, h.parseTag(text, s1).stack);
assert.deepEqual(s2, h.parseTag(text, s2).stack);
});
it('should be the given stack for childless elements', function() {
var text = '<script type="text/javascript">kill(9);</script>';
var s1 = [];
var s2 = ['root'];
assert.deepEqual(s1, h.parseTag(text, s1).stack);
assert.deepEqual(s2, h.parseTag(text, s2).stack);
});
it('should be the correct stack for nested elements', function() {
var text = '<p>Peanuts</div>';
var s1 = ['root', 'div'];
var s2 = ['div', 'span'];
var s3 = ['div', 'div', 'table'];
function x(s) {
return h.parseTag(text, s.concat('div')).stack;
}
assert.deepEqual(s1, x(s1));
assert.deepEqual(s2, x(s2));
assert.deepEqual(s3, x(s3));
});
});
describe('return {tag: Object}', function() {
it('should have the correct `tagName` property', function() {
var text1 = '<p>Words and letters</p>';
var name1 = h.parseTag(text1, []).tag.tagName;
assert.equal('p', name1);
var text2 = '<ng-element>Words and letters</ng-element>';
var name2 = h.parseTag(text2, []).tag.tagName;
assert.equal('ng-element', name2);
});
});
});
describe('parseAttrs(String) Object', function() {
it('should return {str:String} starting at the end of attributes', function() {
var text1 = ' data-attr=0 type="text" disabled />...';
var results = h.parseAttrs(text1);
assert.equal('/>...', results.str);
var text2 = ' />...';
var results = h.parseAttrs(text2);
assert.equal('/>...', results.str);
var text3 = ' data-attr=0 type="text" disabled >...';
var results = h.parseAttrs(text3);
assert.equal('>...', results.str);
var text4 = ' >...';
var results = h.parseAttrs(text4);
assert.equal('>...', results.str);
});
describe('return {attributes:Object}', function() {
it('should have all attributes', function() {
var text = ' data-attr=0 type="text" disabled >...'
var data = {
dataset: {
attr: 0
},
type: 'text',
disabled: 'disabled'
};
assert.deepEqual(data, h.parseAttrs(text).attributes);
});
it('should handle attributes with no quotes', function() {
var text = ' dumb = little stupid=quirks>...';
var data = {
dumb: 'little',
stupid: 'quirks'
};
assert.deepEqual(data, h.parseAttrs(text).attributes);
});
it('should handle attributes with whitespace between the equals (=)', function() {
var text = ' dumb = "stuff" please = no>...';
var data = {
dumb: 'stuff',
please: 'no'
};
assert.deepEqual(data, h.parseAttrs(text).attributes);
});
it('should group all data-* in the `dataset` Object', function() {
var text = ' data-attr=0 data-name="Chris" type="text" disabled >...';
var data = h.parseAttrs(text).attributes;
assert.equal(0, data.dataset.attr);
assert.equal('Chris', data.dataset.name);
assert(!data.dataset.type);
assert(!data.dataset.disabled);
});
it('should put parsed styles in the `style` attribute', function() {
var text = 'style="width: 20px; height: 40px; font-size: 12px" >';
var data = {
style: {
width: '20px',
height: '40px',
fontSize: '12px'
}
};
assert.deepEqual(data, h.parseAttrs(text).attributes);
});
});
});
describe('parseStyle(String) Object', function() {
it('should return an hashmap of style declarations', function() {
var style = 'color: #000; height: 80px';
var data = {
color: '#000',
height: '80px'
};
assert.deepEqual(data, h.parseStyle(style));
});
it('should camelCase CSS properties', function() {
var style = [
'background-color: #fff',
'border-right: 1px solid #000',
'border-top-left-radius: 4px'
].join(';');
var data = {
backgroundColor: '#fff',
borderRight: '1px solid #000',
borderTopLeftRadius: '4px'
};
assert.deepEqual(data, h.parseStyle(style));
});
});
});
test('should not set custom attrs to zeroes', t => {
const html = "<div custom-attr=''></div>"
const data = [{
type: 'Element',
tagName: 'div',
attributes: {customAttr: ''},
children: []
}]
t.deepEqual(data, himalaya.parse(html))
})

@@ -1,185 +0,188 @@

var himalaya = require('..');
var translations = require('../translate');
var toHTML = translations.toHTML;
var toJade = translations.toJade;
var toPug = translations.toPug;
var assert = require('assert');
import test from 'ava'
import himalaya from '../lib'
import translate from '../lib/translate'
const {toHTML, toJade, toPug} = translate
describe('translations', function() {
describe('toHTML(ast) html', function() {
it('should handle simple conversions', function() {
var str1 = '<h1>Text</h1>';
assert.equal(toHTML(himalaya.parse(str1)), str1);
test('toHTML() should handle simple conversions', t => {
const str1 = '<h1>Text</h1>'
t.is(toHTML(himalaya.parse(str1)), str1)
var str2 = 'Text';
assert.equal(toHTML(himalaya.parse(str2)), str2);
const str2 = 'Text'
t.is(toHTML(himalaya.parse(str2)), str2)
var str3 = '<!--Comment-->';
assert.equal(toHTML(himalaya.parse(str3)), str3);
});
const str3 = '<!--Comment-->'
t.is(toHTML(himalaya.parse(str3)), str3)
})
it('should work for void elements', function() {
var meta = "<meta charset='utf8'>";
assert.equal(toHTML(himalaya.parse(meta)), meta);
test('toHTML() should work for void elements', t => {
const meta = "<meta charset='utf8'>"
t.is(toHTML(himalaya.parse(meta)), meta)
var link = "<link rel='stylesheet' href='file.css'>";
assert.equal(toHTML(himalaya.parse(link)), link);
});
const link = "<link rel='stylesheet' href='file.css'>"
t.is(toHTML(himalaya.parse(link)), link)
})
it('should build data-* attributes properly', function() {
var elem = "<div data-one='5' data-two='five'></div>";
assert.equal(toHTML(himalaya.parse(elem)), elem);
});
test('toHTML() should build data-* attributes properly', t => {
const elem = "<div data-one='5' data-two='five'></div>"
t.is(toHTML(himalaya.parse(elem)), elem)
})
it('should build the style attribute properly', function() {
var elem = "<div style='color: #fff; font-size: 12px'></div>";
assert.equal(toHTML(himalaya.parse(elem)), elem);
});
test('toHTML() should build the style attribute properly', t => {
const elem = "<div style='color: #fff; font-size: 12px'></div>"
t.is(toHTML(himalaya.parse(elem)), elem)
})
it('should do basic escaping if a value contains either single or double quotes', function() {
var html = '<div data-val="cake is \'good\'"></div>';
assert.equal(toHTML(himalaya.parse(html)), html);
});
test('toHTML() should do basic escaping if a value contains either single or double quotes', t => {
const html = '<div data-val="cake is \'good\'"></div>'
t.is(toHTML(himalaya.parse(html)), html)
})
it('should preserve whitespace', function() {
var html = [
"<html> ",
" <h1> Document </h1>",
"</html> "
].join('\n');
assert.equal(toHTML(himalaya.parse(html)), html);
});
test('toHTML() should preserve whitespace', t => {
const html = [
'<html> ',
' <h1> Document </h1>',
'</html> '
].join('\n')
t.is(toHTML(himalaya.parse(html)), html)
})
it('should close void tags when doctype is xml', function() {
var html = "<img src='bar.png'>";
var xml = "<img src='bar.png'></img>";
var jsonHTML = himalaya.parse(html);
var jsonXML = himalaya.parse(xml);
test('toHTML() should close void tags when doctype is xml', t => {
const html = "<img src='bar.png'>"
const xml = "<img src='bar.png'></img>"
const jsonHTML = himalaya.parse(html)
const jsonXML = himalaya.parse(xml)
assert.equal(toHTML(jsonHTML), html);
assert.equal(toHTML(jsonHTML, {
doctype: 'xml'
}), xml);
t.is(toHTML(jsonHTML), html)
t.is(toHTML(jsonHTML, {
doctype: 'xml'
}), xml)
assert.equal(toHTML(jsonXML), html);
assert.equal(toHTML(jsonXML, {
doctype: 'xml'
}), xml);
});
t.is(toHTML(jsonXML), html)
t.is(toHTML(jsonXML, {
doctype: 'xml'
}), xml)
})
it('should write out boolean attributes when doctype is xml', function() {
var html = "<script src='bar.js' async></script>";
var xml = "<script src='bar.js' async='async'></script>";
var jsonHTML = himalaya.parse(html);
var jsonXML = himalaya.parse(xml);
test('toHTML() should write out boolean attributes when doctype is xml', t => {
const html = "<script src='bar.js' async></script>"
const xml = "<script src='bar.js' async='async'></script>"
const jsonHTML = himalaya.parse(html)
const jsonXML = himalaya.parse(xml)
assert.equal(toHTML(jsonHTML), html);
assert.equal(toHTML(jsonHTML, {
doctype: 'xml'
}), xml);
t.is(toHTML(jsonHTML), html)
t.is(toHTML(jsonHTML, {
doctype: 'xml'
}), xml)
assert.equal(toHTML(jsonXML), html);
assert.equal(toHTML(jsonXML, {
doctype: 'xml'
}), xml);
});
});
t.is(toHTML(jsonXML), html)
t.is(toHTML(jsonXML, {
doctype: 'xml'
}), xml)
})
describe('toJade(ast, options) jade', function() {
it('should handle plain text', function() {
var html = 'This is text.';
var jade = '| This is text.';
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should handle multi-line plain text', function() {
var html = 'This is multiline text.\nLook newlines.';
var jade = '| This is multiline text.\n| Look newlines.';
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should handle inline comments', function() {
var html = '<!-- Comment -->';
var jade = '// Comment ';
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should handle multi-line comments', function() {
var html = [
"<!--",
" This is a multiline comment.",
" Look newlines.",
"-->"
].join('\n');
var jade = [
"//",
" This is a multiline comment.",
" Look newlines."
].join('\n');
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should write short-hand tag ids', function() {
var html = "<article id='story'></article>";
var jade = "article#story";
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should write short-hand tag classes', function() {
var html = "<article class='story story--main'></article>";
var jade = "article.story.story--main";
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should ignore `div` if an id or class(es) are provided', function() {
var htmlId = "<div id='block'></div>";
var jadeId = "#block";
assert.equal(toJade(himalaya.parse(htmlId)), jadeId);
test('toJade() should handle plain text', t => {
const html = 'This is text.'
const jade = '| This is text.'
t.is(toJade(himalaya.parse(html)), jade)
})
var htmlClass = "<div class='block'></div>";
var jadeClass = ".block";
assert.equal(toJade(himalaya.parse(htmlClass)), jadeClass);
test('toJade() should handle multi-line plain text', t => {
const html = 'This is multiline text.\nLook newlines.'
const jade = '| This is multiline text.\n| Look newlines.'
t.is(toJade(himalaya.parse(html)), jade)
})
var htmlClasses = "<div class='block block--jumbo'></div>";
var jadeClasses = ".block.block--jumbo";
assert.equal(toJade(himalaya.parse(htmlClasses)), jadeClasses);
});
it('should write attributes', function() {
var html = "<canvas width='500' height='400'></canvas>";
var jade = "canvas(width='500', height='400')";
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should write data-* attributes', function() {
var html = "<div data-one='5' data-two='five'></div>";
var jade = "div(data-one='5', data-two='five')";
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should do basic escaping if a value contains either single or double quotes', function() {
var html = '<div data-val="cake is \'good\'"></div>';
var jade = 'div(data-val="cake is \'good\'")';
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should write the style attribute', function() {
var html = "<b style='font-weight: bold; font-style: italics'>Word</b>";
var jade = "b(style='font-weight: bold; font-style: italics') Word";
assert.equal(toJade(himalaya.parse(html)), jade);
});
it('should appropriate place tag inner text', function() {
var htmlInline = "<h1>Hello</h1>";
var jadeInline = "h1 Hello";
assert.equal(toJade(himalaya.parse(htmlInline)), jadeInline);
test('toJade() should handle inline comments', t => {
const html = '<!-- Comment -->'
const jade = '// Comment '
t.is(toJade(himalaya.parse(html)), jade)
})
var htmlMultiline = "<h1>Hello\nWorld</h1>";
var jadeMultiline = "h1.\n Hello\n World";
assert.equal(toJade(himalaya.parse(htmlMultiline)), jadeMultiline);
});
it('should work for script and style tags', function() {
var htmlScript = "<script type='text/javascript'>console.log('yes');</script>";
var jadeScript = "script(type='text/javascript').\n console.log('yes');";
assert.equal(toJade(himalaya.parse(htmlScript)), jadeScript);
test('toJade() should handle multi-line comments', t => {
const html = [
'<!--',
' This is a multiline comment.',
' Look newlines.',
'-->'
].join('\n')
const jade = [
'//',
' This is a multiline comment.',
' Look newlines.'
].join('\n')
t.is(toJade(himalaya.parse(html)), jade)
})
var htmlStyle = "<style>h1 {color: #fff;} .text {font-size: 12px;}</style>";
var jadeStyle = "style.\n h1 {color: #fff;} .text {font-size: 12px;}";
assert.equal(toJade(himalaya.parse(htmlStyle)), jadeStyle);
});
});
describe('toPug(ast, options)', function() {
it('should be an alias for toJade(ast, options)', function() {
assert.equal(toJade, toPug);
});
});
});
test('toJade() should write short-hand tag ids', t => {
const html = "<article id='story'></article>"
const jade = 'article#story'
t.is(toJade(himalaya.parse(html)), jade)
})
test('toJade() should write short-hand tag classes', t => {
const html = "<article class='story story--main'></article>"
const jade = 'article.story.story--main'
t.is(toJade(himalaya.parse(html)), jade)
})
test('toJade() should ignore `div` if an id or class(es) are provided', t => {
const htmlId = "<div id='block'></div>"
const jadeId = '#block'
t.is(toJade(himalaya.parse(htmlId)), jadeId)
const htmlClass = "<div class='block'></div>"
const jadeClass = '.block'
t.is(toJade(himalaya.parse(htmlClass)), jadeClass)
const htmlClasses = "<div class='block block--jumbo'></div>"
const jadeClasses = '.block.block--jumbo'
t.is(toJade(himalaya.parse(htmlClasses)), jadeClasses)
})
test('toJade() should write attributes', t => {
const html = "<canvas width='500' height='400'></canvas>"
const jade = "canvas(width='500', height='400')"
t.is(toJade(himalaya.parse(html)), jade)
})
test('toJade() should write data-* attributes', t => {
const html = "<div data-one='5' data-two='five'></div>"
const jade = "div(data-one='5', data-two='five')"
t.is(toJade(himalaya.parse(html)), jade)
})
test('toJade() should do basic escaping if a value contains either single or double quotes', t => {
const html = '<div data-val="cake is \'good\'"></div>'
const jade = 'div(data-val="cake is \'good\'")'
t.is(toJade(himalaya.parse(html)), jade)
})
test('toJade() should write the style attribute', t => {
const html = "<b style='font-weight: bold; font-style: italics'>Word</b>"
const jade = "b(style='font-weight: bold; font-style: italics') Word"
t.is(toJade(himalaya.parse(html)), jade)
})
test('toJade() should appropriate place tag inner text', t => {
const htmlInline = '<h1>Hello</h1>'
const jadeInline = 'h1 Hello'
t.is(toJade(himalaya.parse(htmlInline)), jadeInline)
const htmlMultiline = '<h1>Hello\nWorld</h1>'
const jadeMultiline = 'h1.\n Hello\n World'
t.is(toJade(himalaya.parse(htmlMultiline)), jadeMultiline)
})
test('toJade() should work for script and style tags', t => {
const htmlScript = "<script type='text/javascript'>console.log('yes');\nconsole.log('no');</script>"
const jadeScript = "script(type='text/javascript').\n console.log('yes');\n console.log('no');"
t.is(toJade(himalaya.parse(htmlScript)), jadeScript)
const htmlStyle = '<style>\nh1 {color: #fff;}\n.text {font-size: 12px;}</style>'
const jadeStyle = 'style.\n h1 {color: #fff;}\n .text {font-size: 12px;}'
t.is(toJade(himalaya.parse(htmlStyle)), jadeStyle)
})
test('toPug() should be an alias for toJade(ast, options)', t => {
t.is(toJade, toPug)
})

@@ -1,215 +0,1 @@

var paul = require('paul');
// c/p'd from ../index.js
var voidTags = [
"!doctype", "area", "base", "br", "col", "command",
"embed", "hr", "img", "input", "keygen", "link",
"meta", "param", "source", "track", "wbr"
];
function serializeAttr(attr, value, isXml) {
if (!isXml && attr === value) return attr;
var text = value.toString();
var quoteEscape = text.indexOf('\'') !== -1;
var quote = quoteEscape ? '\"' : '\'';
return attr + '=' + quote + text + quote;
}
// stolen from underscore.string
function dasherize(str) {
return str.trim()
.replace(/([A-Z])/g, '-$1')
.replace(/[-_\s]+/g, '-')
.toLowerCase();
}
function inlineStyle(style) {
return Object.keys(style).reduce(function(css, key) {
return css + '; ' + dasherize(key) + ': ' + style[key];
}, '').slice(2);
}
var toHTML = function(tree, options) {
options = options || {};
var dtype = options.doctype;
var html = paul.walk(tree, function _html(node, walk) {
if (node.type === 'Text') return node.content;
if (node.type === 'Comment') {
return '<!--' + node.content + '-->';
}
var tag = '<' + node.tagName;
var attrs = node.attributes;
for (var attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
var val = attrs[attr];
if (attr === 'dataset') {
for (var prop in val) {
if (val.hasOwnProperty(prop)) {
var key = 'data-' + dasherize(prop);
tag += ' ' + serializeAttr(key, val[prop], dtype === 'xml');
}
}
} else if (attr === 'style') {
tag += ' ' + serializeAttr(attr, inlineStyle(val));
} else if (attr === 'className') {
tag += ' ' + serializeAttr('class', val.join(' '));
} else {
tag += ' ' + serializeAttr(dasherize(attr), val, dtype === 'xml');
}
}
}
var lowTagName = node.tagName.toLowerCase();
if (dtype !== 'xml' && ~voidTags.indexOf(lowTagName)) {
if (!dtype && lowTagName === '!doctype') {
dtype = doctypeShortcut(tag);
}
return tag + '>';
}
tag += '>';
var innerds = typeof node.content === 'string' ?
node.content :
walk(node.children || []).join('')
return tag + innerds + '</' + node.tagName + '>';
});
if (html.join) html = html.join('');
return html;
}
var newline = '\n';
var toJade = function(tree, options) {
options = options || {};
var dtype = options.doctype;
var ident = options.indentation || ' ';
var multi = multilineText(ident);
function isWhitespaceNode(node) {
return !(node.type === 'Text' && !node.content.trim());
}
if (tree.filter) tree = tree.filter(isWhitespaceNode);
var jade = paul.walk(tree, function(node, walk, depth) {
if (node.type === 'Text') {
return multi(node.content, depth, '| ');
}
if (node.type === 'Comment') {
var text = node.content;
return ~text.indexOf(newline) ?
multi('//', depth) + newline + multi(text, depth + 1) :
multi('//' + text, depth);
}
var tag = node.tagName;
if (node.attributes.id) {
tag += '#' + node.attributes.id;
}
if (node.attributes.className) {
tag += '.' + node.attributes.className.join('.');
}
if (node.tagName === 'div' && tag.length > 3) {
tag = tag.slice(3);
}
tag = multi(tag, depth);
var attrs = node.attributes;
var props = Object.keys(attrs).filter(function(key) {
return key !== 'className' && key !== 'id';
});
if (props.length) {
tag += '(';
tag += props.map(function(prop) {
var val = attrs[prop];
if (prop === 'dataset') {
return Object.keys(val).map(function(attr) {
return serializeAttr('data-' + dasherize(attr), val[attr], dtype === 'xml');
}).join(', ');
} else if (prop === 'style') {
return serializeAttr(prop, inlineStyle(val));
} else {
return serializeAttr(dasherize(prop), val, dtype === 'xml');
}
}).join(', ');
tag += ')';
}
var lowTagName = node.tagName.toLowerCase();
if (~voidTags.indexOf(lowTagName)) {
if (lowTagName === '!doctype') {
if (!dtype) dtype = doctypeShortcut(tag);
return multi('doctype ' + dtype, depth);
}
return tag;
} else if (typeof node.content === 'string') {
if (!node.content) return tag;
return tag + '.' + newline + multi(node.content, depth + 1);
} else {
if (!node.children.length) return tag;
if (node.children.length === 1 && node.children[0].type === 'Text') {
var text = node.children[0].content;
return ~text.indexOf(newline) ?
tag + '.' + newline + multi(text, depth + 1) :
tag + ' ' + text;
}
return tag + newline +
walk(node.children.filter(isWhitespaceNode), depth + 1).join(newline);
}
}, 0);
if (jade.join) jade = jade.join(newline);
return jade;
}
function multilineText(ident) {
var fmt = !~ident.indexOf('\t') ?
function(line) {
return line.replace(/\t/g, ident);
} :
function(line) {
return line;
};
function indent(depth, str) {
while (depth--) {
str = ident + str;
}
return str;
}
return function(str, depth, lead) {
lead = lead || '';
var lines = str
.split(newline).map(fmt)
.filter(function(line) {
return !!line.trim();
});
var start = maxSharedIndent(lines);
return lines.map(function(line) {
return indent(depth, lead + line.slice(start));
}).join(newline);
}
}
function maxSharedIndent(lines) {
return lines.reduce(function(num, line) {
return Math.min(num, line.length - line.trimLeft().length);
}, Infinity);
}
// see http://jade-lang.com/reference/doctype/
function doctypeShortcut(str) {
function has(q) {
return ~str.indexOf(q);
}
if (has('Transitional')) return 'transitional';
if (has('Strict')) return 'strict';
if (has('Frameset')) return 'frameset';
if (has('Basic')) return 'basic';
if (has('1.1')) return '1.1';
if (has('Mobile')) return 'mobile';
return 'html';
}
module.exports = {
toHTML: toHTML,
toJade: toJade,
toPug: toJade
};
module.exports = require('./lib/translate')

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