Added editor
This commit is contained in:
+169
@@ -0,0 +1,169 @@
|
||||
/*jslint node:true */
|
||||
|
||||
var common = require('./common');
|
||||
|
||||
function validateOptions (userOptions) {
|
||||
var options = common.copyOptions(userOptions);
|
||||
common.ensureFlagExists('ignoreDeclaration', options);
|
||||
common.ensureFlagExists('ignoreAttributes', options);
|
||||
common.ensureFlagExists('ignoreText', options);
|
||||
common.ensureFlagExists('ignoreComment', options);
|
||||
common.ensureFlagExists('ignoreCdata', options);
|
||||
common.ensureFlagExists('compact', options);
|
||||
common.ensureFlagExists('fullTagEmptyElement', options);
|
||||
common.ensureSpacesExists(options);
|
||||
if (typeof options.spaces === 'number') {
|
||||
options.spaces = Array(options.spaces + 1).join(' ');
|
||||
}
|
||||
common.ensureKeyExists('declaration', options);
|
||||
common.ensureKeyExists('attributes', options);
|
||||
common.ensureKeyExists('text', options);
|
||||
common.ensureKeyExists('comment', options);
|
||||
common.ensureKeyExists('cdata', options);
|
||||
common.ensureKeyExists('type', options);
|
||||
common.ensureKeyExists('name', options);
|
||||
common.ensureKeyExists('elements', options);
|
||||
return options;
|
||||
}
|
||||
|
||||
function writeIndentation (options, depth, firstLine) {
|
||||
return (!firstLine && options.spaces ? '\n' : '') + Array(depth + 1).join(options.spaces);
|
||||
}
|
||||
|
||||
function writeAttributes (attributes) {
|
||||
var key, result = '';
|
||||
for (key in attributes) {
|
||||
if (attributes.hasOwnProperty(key)) {
|
||||
result += ' ' + key + '="' + attributes[key] + '"';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function writeDeclaration (declaration, options) {
|
||||
return '<?xml' + writeAttributes(declaration[options.attributesKey]) + '?>';
|
||||
}
|
||||
|
||||
function writeComment (element, options) {
|
||||
return options.ignoreComment ? '' : '<!--' + element[options.commentKey] + '-->';
|
||||
}
|
||||
|
||||
function writeCdata (element, options) {
|
||||
return options.ignoreCdata ? '' : '<![CDATA[' + element[options.cdataKey] + ']]>';
|
||||
}
|
||||
|
||||
function writeText (element, options) {
|
||||
return options.ignoreText ? '' : element[options.textKey].replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function writeElement (element, options, depth) {
|
||||
var xml = '';
|
||||
xml += '<' + element.name;
|
||||
if (element[options.attributesKey]) {
|
||||
xml += writeAttributes(element[options.attributesKey]);
|
||||
}
|
||||
if (options.fullTagEmptyElement || (element[options.elementsKey] && element[options.elementsKey].length) || (element[options.attributesKey] && element[options.attributesKey]['xml:space'] === 'preserve')) {
|
||||
xml += '>';
|
||||
if (element[options.elementsKey] && element[options.elementsKey].length) {
|
||||
xml += writeElements(element[options.elementsKey], options, depth + 1);
|
||||
}
|
||||
xml += (options.spaces && element[options.elementsKey] && element[options.elementsKey].length && (element[options.elementsKey].length > 1 || element[options.elementsKey][0].type !== 'text') ? '\n' : '') + Array(depth + 1).join(options.spaces);
|
||||
xml += '</' + element.name + '>';
|
||||
} else {
|
||||
xml += '/>';
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
|
||||
function writeElements (elements, options, depth, firstLine) {
|
||||
var indent = writeIndentation(options, depth, firstLine);
|
||||
return elements.reduce(function (xml, element) {
|
||||
switch (element.type) {
|
||||
case 'element': return xml + indent + writeElement(element, options, depth);
|
||||
case 'comment': return xml + indent + writeComment(element, options);
|
||||
case 'cdata': return xml + indent + writeCdata(element, options);
|
||||
case 'text': return xml + writeText(element, options);
|
||||
}
|
||||
}, '');
|
||||
}
|
||||
|
||||
function hasContent (element, options, skipText) {
|
||||
var key;
|
||||
for (key in element) {
|
||||
if (element.hasOwnProperty(key)) {
|
||||
switch (key) {
|
||||
case options.textKey:
|
||||
if (!skipText) {
|
||||
return true;
|
||||
}
|
||||
break; // skip to next key
|
||||
case options.parentKey:
|
||||
case options.attributesKey:
|
||||
break; // skip to next key
|
||||
case options.cdataKey:
|
||||
case options.commentKey:
|
||||
case options.declarationKey:
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function writeElementCompact (element, name, options, depth, indent) {
|
||||
var xml = '';
|
||||
if (name) {
|
||||
xml += '<' + name;
|
||||
if (element[options.attributesKey]) {
|
||||
xml += writeAttributes(element[options.attributesKey]);
|
||||
}
|
||||
if (options.fullTagEmptyElement || hasContent(element, options) || element[options.attributesKey] && element[options.attributesKey]['xml:space'] === 'preserve') {
|
||||
xml += '>';
|
||||
} else {
|
||||
xml += '/>';
|
||||
return xml;
|
||||
}
|
||||
}
|
||||
xml += writeElementsCompact(element, options, depth + 1, false);
|
||||
if (name) {
|
||||
xml += (indent ? writeIndentation(options, depth, false) : '') + '</' + name + '>';
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
|
||||
function writeElementsCompact (element, options, depth, firstLine) {
|
||||
var key, xml = '';
|
||||
for (key in element) {
|
||||
if (element.hasOwnProperty(key)) {
|
||||
switch (key) {
|
||||
case options.declarationKey: xml += writeDeclaration(element[options.declarationKey], options); break;
|
||||
case options.attributesKey: case options.parentKey: break; // skip
|
||||
case options.textKey: xml += writeText(element, options); break;
|
||||
case options.cdataKey: xml += writeIndentation(options, depth, firstLine) + writeCdata(element, options); break;
|
||||
case options.commentKey: xml += writeIndentation(options, depth, firstLine) + writeComment(element, options); break;
|
||||
default: xml += writeIndentation(options, depth, firstLine) + writeElementCompact(element[key], key, options, depth, hasContent(element[key], options, true));
|
||||
}
|
||||
firstLine = firstLine && !xml;
|
||||
}
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
|
||||
module.exports = function (js, options) {
|
||||
'use strict';
|
||||
options = validateOptions(options);
|
||||
var xml = '';
|
||||
if (options.compact) {
|
||||
xml = writeElementsCompact(js, options, 0, true);
|
||||
} else {
|
||||
if (js[options.declarationKey]) {
|
||||
xml += writeDeclaration(js[options.declarationKey], options);
|
||||
}
|
||||
if (js[options.elementsKey] && js[options.elementsKey].length) {
|
||||
xml += writeElements(js[options.elementsKey], options, 0, !xml);
|
||||
}
|
||||
}
|
||||
return xml;
|
||||
};
|
||||
Reference in New Issue
Block a user