code: func substituteParams(toReplace, words string, dicts map[string]interface{}) string {
  	// non empty scalar node remain unchanged
  	// except it has double chevron bracket
  	if toReplace != "" && (strings.Index(toReplace, "<<") < 0 && strings.Index(toReplace, ">>") < 0) {
  		return toReplace
  	}
  	if words == "" {
  		return toReplace
  	}
  
  	removeParamBracket := func(param string) string {
  		param = strings.TrimSpace(param)
  		return param[2 : len(param)-2]
  	}
  
  	// search params
  	params := dcRe.FindAllString(words, -1)
  
  	// substitute the params
  	for _, p := range params {
  		pVal, ok := getParamValue(removeParamBracket(p), dicts)
  		if !ok {
  			// only replace if param is found
  			continue
  		}
  		words = strings.Replace(words, p, pVal, -1)
  	}
  	return words
  }
docs: // substituteParams substitute all params inside double chevron to the correct value
  // param value will be obtained from dicts map