Previously only the `description` and `usageNotes` were being copied over from the call-member of the decorator interface. Important properties such as `shortDescription` were missed. These are now added and the code has been refactored to make it simpler and clearer to update which properties get copied as the requirements change. PR Close #24289
		
			
				
	
	
		
			115 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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, '"')}"`).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];
 | 
						|
      }
 | 
						|
    });
 | 
						|
  },
 | 
						|
};
 |