angular-cn/aio/tools/transforms/helpers/utils.js

115 lines
2.8 KiB
JavaScript
Raw Normal View History

module.exports = {
/**
* Transform the values of an object via a mapper function
* @param {Object} obj
* @param {Function} mapper
*/
mapObject(obj, mapper) {
const mappedObj = {};
Object.keys(obj).forEach(key => { mappedObj[key] = mapper(key, obj[key]); });
return mappedObj;
},
/**
* Parses the attributes from a string taken from an HTML element start tag
* E.g. ` a="one" b="two" `
* @param {string} str
*/
parseAttributes(str) {
const attrMap = {};
let index = 0;
skipSpace();
while(index < str.length) {
takeAttribute();
skipSpace();
}
function takeAttribute() {
const key = takeKey();
skipSpace();
if (tryEquals()) {
skipSpace();
const quote = tryQuote();
attrMap[key] = takeValue(quote);
// skip the closing quote or whitespace
index++;
} else {
attrMap[key] = true;
}
}
function skipSpace() {
while(index < str.length && /\s/.test(str[index])) {
index++;
}
}
function tryEquals() {
if (str[index] === '=') {
index++;
return true;
}
}
function takeKey() {
let startIndex = index;
while(index < str.length && /[^\s=]/.test(str[index])) {
index++;
}
return str.substring(startIndex, index);
}
function tryQuote() {
const quote = str[index];
if (['"', '\''].indexOf(quote) !== -1) {
index++;
return quote;
}
}
function takeValue(quote) {
let startIndex = index;
if (quote) {
while(index < str.length && str[index] !== quote) {
index++;
}
if (index >= str.length) {
throw new Error(`Unterminated quoted attribute value in \`${str}\`. Starting at ${startIndex}. Expected a ${quote} but got "end of string".`);
}
} else {
while(index < str.length && /\S/.test(str[index])) {
index++;
}
}
return str.substring(startIndex, index);
}
return attrMap;
},
renderAttributes(attrMap) {
return Object.keys(attrMap).map(key =>
attrMap[key] === false ? '' :
attrMap[key] === true ? ` ${key}` :
` ${key}="${attrMap[key].replace(/"/g, '&quot;')}"`).join('');
},
/**
* Merge the specified properties from the source to the target document
* @param {Document} target The document to receive the properties from the source
* @param {Document} source The document from which to get the properties to merge
* @param {string[]} properties A collection of the names of the properties to merge
*/
mergeProperties(target, source, properties) {
properties.forEach(property => {
if (source.hasOwnProperty(property)) {
target[property] = source[property];
}
});
},
};