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

xml-formatter

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

xml-formatter - npm Package Compare versions

Comparing version 1.2.1 to 2.0.0

.eslintignore

418

dist/browser/xml-formatter.js
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
},{}],2:[function(require,module,exports){
module.exports = function() {
return function debug() {
// empty mock of debug module for browser usage
};
};
},{}],3:[function(require,module,exports){
/**
* Module dependencies.
* @typedef {Object} ParsingOptions
* @property {function(node)} filter Returns false to exclude a node. Default is true.
*/
var debug = require('debug')('xml-parser');
/**
* Expose `parse`.
*/
module.exports = parse;
/**
* Parse the given string of `xml`.
* Parse the given XML string into an object.
*
* @param {String} xml
* @param {Object} [options]
* @config {Boolean} [trim=true]
* @config {Boolean} [stripComments=true]
* @param {ParsingOptions} [options]
* @return {Object}
* @api public
*/
function parse(xml, options = {}) {
function parse(xml, options) {
options.filter = options.filter || (() => true);
// trim content
if (!options || options.trim) {
xml = xml.trim();
}
function nextChild() {
return tag() || content() || comment() || cdata();
}
// strip comments
if (!options || options.stripComments) {
xml = xml.replace(/<!--[\s\S]*?-->/g, '');
}
function nextRootChild() {
match(/\s*/);
return tag(true) || comment() || doctype() || processingInstruction(false);
}
return document();
function document() {
const decl = declaration();
const children = [];
let documentRootNode;
let child = nextRootChild();
/**
* XML document.
*/
while (child) {
if (child.node.type === 'Element') {
if (documentRootNode) {
throw new Error('Found multiple root nodes');
}
documentRootNode = child.node;
}
function document() {
if (!child.excluded) {
children.push(child.node);
}
var decl = declaration();
var child;
var children = [];
var documentRootNode;
child = nextRootChild();
}
while (child = nextRootChild()) {
if (child.name !== '#comment') {
if (documentRootNode) {
throw new Error('Found multiple root nodes');
if (!documentRootNode) {
throw new Error('Failed to parse XML');
}
documentRootNode = child;
}
children.push(child);
return {
declaration: decl ? decl.node : null,
root: documentRootNode,
children
};
}
return {
declaration: decl,
root: documentRootNode,
children: children
};
}
function declaration() {
return processingInstruction(true);
}
/**
* Declaration.
*/
function processingInstruction(matchDeclaration) {
const m = matchDeclaration ? match(/^<\?(xml)\s*/) : match(/^<\?([\w-:.]+)\s*/);
if (!m) return;
function declaration() {
var m = match(/^<\?xml\s*/);
if (!m) return;
// tag
const node = {
name: m[1],
type: 'ProcessingInstruction',
attributes: {}
};
// tag
var node = {
attributes: {}
};
// attributes
while (!(eos() || is('?>'))) {
const attr = attribute();
if (!attr) return node;
node.attributes[attr.name] = attr.value;
}
// attributes
while (!(eos() || is('?>'))) {
var attr = attribute();
if (!attr) return node;
node.attributes[attr.name] = attr.value;
match(/\?>/);
return {
excluded: matchDeclaration ? false : options.filter(node) === false,
node
};
}
match(/\?>\s*/);
function tag(matchRoot) {
const m = match(/^<([\w-:.]+)\s*/);
if (!m) return;
return node;
}
// name
const node = {
type: 'Element',
name: m[1],
attributes: {},
children: []
};
/**
* Tag.
*/
// attributes
while (!(eos() || is('>') || is('?>') || is('/>'))) {
const attr = attribute();
if (!attr) return node;
node.attributes[attr.name] = attr.value;
}
function tag() {
debug('tag %j', xml);
var m = match(/^<([\w-:.]+)\s*/);
if (!m) return;
const excluded = matchRoot ? false : options.filter(node) === false;
// name
var node = {
name: m[1],
attributes: {},
children: []
};
// self closing tag
if (match(/^\s*\/>/)) {
node.children = null;
return {
excluded,
node
};
}
// attributes
while (!(eos() || is('>') || is('?>') || is('/>'))) {
var attr = attribute();
if (!attr) return node;
node.attributes[attr.name] = attr.value;
}
match(/\??>/);
// self closing tag
if (match(/^\s*\/>/)) {
node.children = null;
return node;
}
if (!excluded) {
// children
let child = nextChild();
while (child) {
if (!child.excluded) {
node.children.push(child.node);
}
child = nextChild();
}
}
match(/\??>/);
// closing
match(/^<\/[\w-:.]+>/);
// children
var child;
while (child = nextChild()) {
node.children.push(child);
return {
excluded,
node
};
}
// closing
match(/^<\/[\w-:.]+>/);
function doctype() {
const m = match(/^<!DOCTYPE\s+[^>]*>/);
if (m) {
const node = {
type: 'DocumentType',
content: m[0]
};
return {
excluded: options.filter(node) === false,
node
};
}
}
return node;
}
function cdata() {
const m = match(/^<!\[CDATA\[[^\]\]>]*]]>/);
if (m) {
const node = {
type: 'CDATA',
content: m[0]
};
return {
excluded: options.filter(node) === false,
node
};
}
}
function nextChild() {
return tag() || content() || comment();
}
function comment() {
const m = match(/^<!--[\s\S]*?-->/);
if (m) {
const node = {
type: 'Comment',
content: m[0]
};
return {
excluded: options.filter(node) === false,
node
};
}
}
function nextRootChild() {
return tag() || comment();
}
function content() {
const m = match(/^([^<]+)/);
if (m) {
const node = {
type: 'Text',
content: m[1]
};
return {
excluded: options.filter(node) === false,
node
};
}
}
function comment() {
var m = match(/^<!--[\s\S]*?-->/);
if (m) {
return {
name: '#comment',
content: m[0]
};
function attribute() {
const m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/);
if (!m) return;
return {name: m[1], value: strip(m[2])}
}
}
/**
* Text content.
*/
/**
* Strip quotes from `val`.
*/
function strip(val) {
return val.replace(/^['"]|['"]$/g, '');
}
function content() {
debug('content %j', xml);
var m = match(/^([^<]+)/);
if (m) {
return {
name: '#text',
content: m[1]
};
/**
* Match `re` and advance the string.
*/
function match(re) {
const m = xml.match(re);
if (!m) return;
xml = xml.slice(m[0].length);
return m;
}
}
/**
* Attribute.
*/
/**
* End-of-source.
*/
function eos() {
return 0 === xml.length;
}
function attribute() {
debug('attribute %j', xml);
var m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/);
if (!m) return;
return { name: m[1], value: strip(m[2]) }
}
/**
* Check for `prefix`.
*/
function is(prefix) {
return 0 === xml.indexOf(prefix);
}
/**
* Strip quotes from `val`.
*/
xml = xml.trim();
function strip(val) {
return val.replace(/^['"]|['"]$/g, '');
}
return document();
}
/**
* Match `re` and advance the string.
*/
module.exports = parse;
function match(re) {
var m = xml.match(re);
if (!m) return;
xml = xml.slice(m[0].length);
return m;
}
/**
* End-of-source.
*/
function eos() {
return 0 == xml.length;
}
/**
* Check for `prefix`.
*/
function is(prefix) {
return 0 == xml.indexOf(prefix);
}
}
},{"debug":2}],"xml-formatter":[function(require,module,exports){
},{}],"xml-formatter":[function(require,module,exports){
function newLine(output) {
output.content += output.options.lineSeparator;
var i;
let i;
for (i = 0; i < output.level; i++) {

@@ -238,7 +256,10 @@ output.content += output.options.indentation;

function processNode(node, output, preserveSpace) {
if (node.name === '#text' || node.name === '#comment') {
if (typeof node.content === 'string') {
processContentNode(node, output, preserveSpace);
} else if (node.type === 'Element') {
processElement(node, output, preserveSpace);
} else if (node.type === 'ProcessingInstruction') {
processProcessingIntruction(node, output, preserveSpace);
} else {
// Assuming that we only have 3 types of node (#text, #comment and element)
processElement(node, output, preserveSpace);
throw new Error('Unknown node type: ' + node.type);
}

@@ -265,2 +286,5 @@ }

appendContent(output, '/>');
} else if (node.children.length === 0) {
// empty node
appendContent(output, '></' + node.name + '>');
} else {

@@ -272,8 +296,8 @@

var nodePreserveSpace = node.attributes['xml:space'] === 'preserve';
let nodePreserveSpace = node.attributes['xml:space'] === 'preserve';
if (!nodePreserveSpace && output.options.collapseContent) {
var containsTextNodes = node.children.some(function(child) {
return child.name === '#text';
const containsTextNodes = node.children.some(function(child) {
return child.type === 'Text';
});

@@ -305,8 +329,9 @@

function processDeclaration(declaration, output) {
if (declaration) {
appendContent(output, '<?xml');
processAttributes(output, declaration.attributes);
appendContent(output, '?>');
function processProcessingIntruction(node, output) {
if (output.content.length > 0) {
newLine(output);
}
appendContent(output, '<?' + node.name);
processAttributes(output, node.attributes);
appendContent(output, '?>');
}

@@ -320,5 +345,4 @@

* @param {Object} options
* @config {Boolean} [debug=false] displays a tree of the parsed XML before formatting
* @config {String} [indentation=' '] The value used for indentation
* @config {Boolean} [stripComments=false] True to strip the comments
* @config {function(node)} [filter] Return false to exclude the node.
* @config {Boolean} [collapseContent=false] True to keep content in the same line as the element. Only works if element contains at least one text node

@@ -328,23 +352,17 @@ * @config {String} [lineSeparator='\r\n'] The line separator to use

*/
function format(xml, options) {
function format(xml, options = {}) {
options = options || {};
options.debug = options.debug === true;
options.indentation = options.indentation || ' ';
options.stripComments = options.stripComments === true;
options.collapseContent = options.collapseContent === true;
options.lineSeparator = options.lineSeparator || '\r\n';
var parse = require('xml-parser-xo');
var parsedXml = parse(xml, {stripComments: options.stripComments});
const parse = require('xml-parser-xo');
const parsedXml = parse(xml, {filter: options.filter});
const output = {content: '', level: 0, options: options};
if (options.debug) {
var inspect = require('util').inspect;
console.log(inspect(parsedXml, { colors: true, depth: Infinity }));
if (parsedXml.declaration) {
processProcessingIntruction(parsedXml.declaration, output);
}
var output = {content: '', level: 0, options: options};
processDeclaration(parsedXml.declaration, output);
parsedXml.children.forEach(function(child) {

@@ -360,2 +378,2 @@ processNode(child, output, false);

},{"util":1,"xml-parser-xo":3}]},{},[]);
},{"xml-parser-xo":1}]},{},[]);
function newLine(output) {
output.content += output.options.lineSeparator;
var i;
let i;
for (i = 0; i < output.level; i++) {

@@ -14,7 +14,10 @@ output.content += output.options.indentation;

function processNode(node, output, preserveSpace) {
if (node.name === '#text' || node.name === '#comment') {
if (typeof node.content === 'string') {
processContentNode(node, output, preserveSpace);
} else if (node.type === 'Element') {
processElement(node, output, preserveSpace);
} else if (node.type === 'ProcessingInstruction') {
processProcessingIntruction(node, output, preserveSpace);
} else {
// Assuming that we only have 3 types of node (#text, #comment and element)
processElement(node, output, preserveSpace);
throw new Error('Unknown node type: ' + node.type);
}

@@ -41,2 +44,5 @@ }

appendContent(output, '/>');
} else if (node.children.length === 0) {
// empty node
appendContent(output, '></' + node.name + '>');
} else {

@@ -48,8 +54,8 @@

var nodePreserveSpace = node.attributes['xml:space'] === 'preserve';
let nodePreserveSpace = node.attributes['xml:space'] === 'preserve';
if (!nodePreserveSpace && output.options.collapseContent) {
var containsTextNodes = node.children.some(function(child) {
return child.name === '#text';
const containsTextNodes = node.children.some(function(child) {
return child.type === 'Text';
});

@@ -81,8 +87,9 @@

function processDeclaration(declaration, output) {
if (declaration) {
appendContent(output, '<?xml');
processAttributes(output, declaration.attributes);
appendContent(output, '?>');
function processProcessingIntruction(node, output) {
if (output.content.length > 0) {
newLine(output);
}
appendContent(output, '<?' + node.name);
processAttributes(output, node.attributes);
appendContent(output, '?>');
}

@@ -96,5 +103,4 @@

* @param {Object} options
* @config {Boolean} [debug=false] displays a tree of the parsed XML before formatting
* @config {String} [indentation=' '] The value used for indentation
* @config {Boolean} [stripComments=false] True to strip the comments
* @config {function(node)} [filter] Return false to exclude the node.
* @config {Boolean} [collapseContent=false] True to keep content in the same line as the element. Only works if element contains at least one text node

@@ -104,23 +110,17 @@ * @config {String} [lineSeparator='\r\n'] The line separator to use

*/
function format(xml, options) {
function format(xml, options = {}) {
options = options || {};
options.debug = options.debug === true;
options.indentation = options.indentation || ' ';
options.stripComments = options.stripComments === true;
options.collapseContent = options.collapseContent === true;
options.lineSeparator = options.lineSeparator || '\r\n';
var parse = require('xml-parser-xo');
var parsedXml = parse(xml, {stripComments: options.stripComments});
const parse = require('xml-parser-xo');
const parsedXml = parse(xml, {filter: options.filter});
const output = {content: '', level: 0, options: options};
if (options.debug) {
var inspect = require('util').inspect;
console.log(inspect(parsedXml, { colors: true, depth: Infinity }));
if (parsedXml.declaration) {
processProcessingIntruction(parsedXml.declaration, output);
}
var output = {content: '', level: 0, options: options};
processDeclaration(parsedXml.declaration, output);
parsedXml.children.forEach(function(child) {

@@ -127,0 +127,0 @@ processNode(child, output, false);

{
"name": "xml-formatter",
"version": "1.2.1",
"repository": "chrisbottin/xml-formatter",
"description": "Converts XML into a human readable format (pretty print) while respecting the xml:space attribute",
"version": "2.0.0",
"repository": "github:chrisbottin/xml-formatter",
"bugs": {
"url": "https://github.com/chrisbottin/xml-formatter/issues"
},
"homepage": "https://github.com/chrisbottin/xml-formatter#readme",
"description": "Converts a XML string into a human readable format (pretty print) while respecting the xml:space attribute",
"author": "Chris Bottin <chrisbottin@gmail.com>",
"license": "MIT",
"main": "index.js",
"scripts": {
"test": "node_modules/.bin/mocha",
"prepublishOnly": "npm test && npm run dist:prepare && npm run dist:build",
"test": "mocha",
"prepublishOnly": "eslint . && npm test && npm run dist:prepare && npm run dist:build",
"dist:prepare": "rm -rf ./dist && mkdir -p ./dist/browser",
"dist:build": "node_modules/.bin/browserify -r ./index.js:xml-formatter -o ./dist/browser/xml-formatter.js"
"dist:build": "browserify -r ./index.js:xml-formatter -o ./dist/browser/xml-formatter.js"
},

@@ -18,2 +24,4 @@ "engines": {

"xml",
"pretty",
"print",
"pretty-print",

@@ -26,17 +34,12 @@ "indent",

],
"author": "Chris Bottin",
"license": "MIT",
"dependencies": {
"xml-parser-xo": "^2.1.1"
"xml-parser-xo": "^3.0.0"
},
"devDependencies": {
"browserify": "^13.1.1",
"chai": "^3.5.0",
"gulp": "^4.0.2",
"mocha": "^6.2.1",
"stream-assert": "^2.0.3"
},
"browser": {
"util": false
"chai": "^4.2.0",
"eslint": "^6.8.0",
"glob": "^7.1.6",
"mocha": "^6.2.1"
}
}

@@ -48,4 +48,8 @@

var options = {indentation: ' ', stripComments: true, collapseContent: true, lineSeparator: '\n'};
var formattedXml = format(xml, options);
var formattedXml = format(xml, {
indentation: ' ',
filter: (node) => node.type !== 'Comment',
collapseContent: true,
lineSeparator: '\n'
});

@@ -65,5 +69,4 @@ console.log(formattedXml);

- `stripComments` (Boolean, default=`true`) True to strip the comments.
- `filter` (function(node)) Function to filter out unwanted nodes by returning false.
- `indentation` (String, default=`' '`) The value used for indentation.
- `debug` (Boolean, default=`false`) Displays a tree of the parsed XML before formatting.
- `collapseContent` (Boolean, default=`false`] True to keep content in the same line as the element. Only works if element contains at least one text node

@@ -70,0 +73,0 @@ - `lineSeparator` (String, default=`\r\n`) Specify the line separator to use

Sorry, the diff of this file is not supported yet

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