This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.
mightyscape-1.1-deprecated/extensions/svgo-inkscape/node_modules/svgo/lib/svgo/js2svg.js
2020-07-30 01:16:18 +02:00

326 lines
7.0 KiB
JavaScript

'use strict';
var EXTEND = require('whet.extend'),
textElem = require('../../plugins/_collections.js').elemsGroups.textContent.concat('title');
var defaults = {
doctypeStart: '<!DOCTYPE',
doctypeEnd: '>',
procInstStart: '<?',
procInstEnd: '?>',
tagOpenStart: '<',
tagOpenEnd: '>',
tagCloseStart: '</',
tagCloseEnd: '>',
tagShortStart: '<',
tagShortEnd: '/>',
attrStart: '="',
attrEnd: '"',
commentStart: '<!--',
commentEnd: '-->',
cdataStart: '<![CDATA[',
cdataEnd: ']]>',
textStart: '',
textEnd: '',
indent: ' ',
regEntities: /[&'"<>]/g,
regValEntities: /[&"<>]/g,
encodeEntity: encodeEntity,
pretty: false
};
var entities = {
'&': '&amp;',
'\'': '&apos;',
'"': '&quot;',
'>': '&gt;',
'<': '&lt;',
};
/**
* Convert SVG-as-JS object to SVG (XML) string.
*
* @param {Object} data input data
* @param {Object} config config
*
* @return {Object} output data
*/
module.exports = function(data, config) {
return new JS2SVG(config).convert(data);
};
function JS2SVG(config) {
if (config) {
this.config = EXTEND(true, {}, defaults, config);
} else {
this.config = defaults;
}
if (this.config.pretty) {
this.config.doctypeEnd += '\n';
this.config.procInstEnd += '\n';
this.config.commentEnd += '\n';
this.config.cdataEnd += '\n';
this.config.tagShortEnd += '\n';
this.config.tagOpenEnd += '\n';
this.config.tagCloseEnd += '\n';
this.config.textEnd += '\n';
}
this.indentLevel = 0;
this.textContext = null;
}
function encodeEntity(char) {
return entities[char];
}
/**
* Start conversion.
*
* @param {Object} data input data
*
* @return {String}
*/
JS2SVG.prototype.convert = function(data) {
var svg = '';
if (data.content) {
this.indentLevel++;
data.content.forEach(function(item) {
if (item.elem) {
svg += this.createElem(item);
} else if (item.text) {
svg += this.createText(item.text);
} else if (item.doctype) {
svg += this.createDoctype(item.doctype);
} else if (item.processinginstruction) {
svg += this.createProcInst(item.processinginstruction);
} else if (item.comment) {
svg += this.createComment(item.comment);
} else if (item.cdata) {
svg += this.createCDATA(item.cdata);
}
}, this);
}
this.indentLevel--;
return {
data: svg,
info: {
width: this.width,
height: this.height
}
};
};
/**
* Create indent string in accordance with the current node level.
*
* @return {String}
*/
JS2SVG.prototype.createIndent = function() {
var indent = '';
if (this.config.pretty && !this.textContext) {
for (var i = 1; i < this.indentLevel; i++) {
indent += this.config.indent;
}
}
return indent;
};
/**
* Create doctype tag.
*
* @param {String} doctype doctype body string
*
* @return {String}
*/
JS2SVG.prototype.createDoctype = function(doctype) {
return this.config.doctypeStart +
doctype +
this.config.doctypeEnd;
};
/**
* Create XML Processing Instruction tag.
*
* @param {Object} instruction instruction object
*
* @return {String}
*/
JS2SVG.prototype.createProcInst = function(instruction) {
return this.config.procInstStart +
instruction.name +
' ' +
instruction.body +
this.config.procInstEnd;
};
/**
* Create comment tag.
*
* @param {String} comment comment body
*
* @return {String}
*/
JS2SVG.prototype.createComment = function(comment) {
return this.config.commentStart +
comment +
this.config.commentEnd;
};
/**
* Create CDATA section.
*
* @param {String} cdata CDATA body
*
* @return {String}
*/
JS2SVG.prototype.createCDATA = function(cdata) {
return this.config.cdataStart +
cdata +
this.config.cdataEnd;
};
/**
* Create element tag.
*
* @param {Object} data element object
*
* @return {String}
*/
JS2SVG.prototype.createElem = function(data) {
// beautiful injection for obtaining SVG information :)
if (
data.isElem('svg') &&
data.hasAttr('width') &&
data.hasAttr('height')
) {
this.width = data.attr('width').value;
this.height = data.attr('height').value;
}
// empty element and short tag
if (data.isEmpty()) {
return this.createIndent() +
this.config.tagShortStart +
data.elem +
this.createAttrs(data) +
this.config.tagShortEnd;
// non-empty element
} else {
var tagOpenStart = this.config.tagOpenStart,
tagOpenEnd = this.config.tagOpenEnd,
tagCloseStart = this.config.tagCloseStart,
tagCloseEnd = this.config.tagCloseEnd,
openIndent = this.createIndent(),
textIndent = '',
processedData = '',
dataEnd = '';
if (this.textContext) {
tagOpenStart = defaults.tagOpenStart;
tagOpenEnd = defaults.tagOpenEnd;
tagCloseStart = defaults.tagCloseStart;
tagCloseEnd = defaults.tagCloseEnd;
openIndent = '';
} else if (data.isElem(textElem)) {
if (this.config.pretty) {
textIndent += openIndent + this.config.indent;
}
this.textContext = data;
}
processedData += this.convert(data).data;
if (this.textContext == data) {
this.textContext = null;
if (this.config.pretty) dataEnd = '\n';
}
return openIndent +
tagOpenStart +
data.elem +
this.createAttrs(data) +
tagOpenEnd +
textIndent +
processedData +
dataEnd +
this.createIndent() +
tagCloseStart +
data.elem +
tagCloseEnd;
}
};
/**
* Create element attributes.
*
* @param {Object} elem attributes object
*
* @return {String}
*/
JS2SVG.prototype.createAttrs = function(elem) {
var attrs = '';
elem.eachAttr(function(attr) {
attrs += ' ' +
attr.name +
this.config.attrStart +
String(attr.value).replace(this.config.regValEntities, this.config.encodeEntity) +
this.config.attrEnd;
}, this);
return attrs;
};
/**
* Create text node.
*
* @param {String} text text
*
* @return {String}
*/
JS2SVG.prototype.createText = function(text) {
return this.createIndent() +
this.config.textStart +
text.replace(this.config.regEntities, this.config.encodeEntity) +
(this.textContext ? '' : this.config.textEnd);
};