packages/wxeact-cli/lib/build-xml.js
function replaceString(from, str, prefix, ignores) {
  // 替换字符串中 {{}} 包含的表达式

  // 获取类似 a.b.c 表达式中第一个有效变量名 a
  function getFirstWord(word) {
    return word.match(/[_a-z][\w\d]*/i)[0];
  }

  // 检查类似 a.b.c 格式表达式是否忽略绑定
  function shouldIgnore(word, matchs, n) {
    if (word[0] === '"' || word[0] === "'" || /^\d+$/.test(word)) return true;
    let w = getFirstWord(word);
    if (ignores.hasOwnProperty(w) || (matchs && inText(matchs, n))) {
      return true;
    }
    if (['state', 'props'].indexOf(w) < 0) {
      console.error(`'${from.fromSrc}' 中发现无效变量引用 '${word}'，XML模板中只能引用组件'props'和'state'中的数据。`.red);
    }

    return false;
  }

  if (prefix) {
    prefix += '.';
  } else {
    prefix = '';
  }
  return str.replace(/\{\{([^}]+)\}\}/ig, function (matchs, words) {
    // matchs 是{{xxxxx}}格式的字符串
    // words  是{{}}中间的表达式

    // ...foo
    if (/^\s*\.\.\.[\w_][\w\d\-_.\[\]]*\s*$/.test(words)) {
      let word = words.match(/\s*\.\.\.([\w_][\w\d\-_.\[\]]*)/)[1].trim();
      if (shouldIgnore(word)) {
        return matchs;
      }
      return `{{...${prefix}${word}}}`;
    }

    let isArray = /{{\s*\[/.test(matchs);
    if (!isArray) {
      //支持对象简写
      let arrays = words.split(',');
      if (arrays.length > 1) {
        let isObject = true;
        let props = arrays.map(function (str) {
          if (!isObject) return;
          // str 为对象中的一个属性， 可能为 a:b / a / ...a / ...a.b
          str = str.trim();

          let arr = str.split(':');
          if (arr.length === 1) {
            // 如果属性表达式中不包含冒号

            // 如果为简写属性表达式，例如 {foo}
            if (/^[a-z_][\w\d]*$/i.test(str)) {
              if (ignores[str]) {
                return str + ':' + str;
              }
              return str + ':' + prefix + str;
            }

            // 属性展开表达式 ...foo
            if (/^\.{3}[a-z_][\w\d.\[\]]*$/i.test(str)) {
              let word = str.substr(3);
              if (shouldIgnore(word)) {
                return str;
              }
              return '...' + prefix + word;
            }

            // 判定 ${matchs} 不为对象表达式
            isObject = false;
            return;
          }

          // 存在冒号的对象属性表达式

          let word = arr[1].trim();
          // foo:2.3
          if (/^[\d.]+$/.test(word)) {
            return arr[0] + ':' + word;
          }

          // foo:bar
          // 'foo':bar
          if (shouldIgnore(word)) {
            return str;
          }

          // foo:bar
          // 'foo':bar
          // foo
          return arr[0] + ':' + prefix + word;
        });

        //console.log('isObject', isObject);
        if (isObject) {
          return '{{' + props.join(',') + '}}';
        }
      }
    }


    return matchs.replace(/[^\.\w'"]([a-z_\$][\w\d\._\$]*)/ig, function (match, word, n) {
      if (shouldIgnore(word, matchs, n)) {
        return match;
      }
      return match[0] + prefix + word;
    });
  });
}
function replaceString(from, str, prefix, ignores) {
  // 替换字符串中 {{}} 包含的表达式

  // 获取类似 a.b.c 表达式中第一个有效变量名 a
  function getFirstWord(word) {
    return word.match(/[_a-z][\w\d]*/i)[0];
  }

  // 检查类似 a.b.c 格式表达式是否忽略绑定
  function shouldIgnore(word, matchs, n) {
    if (word[0] === '"' || word[0] === "'" || /^\d+$/.test(word)) return true;
    let w = getFirstWord(word);
    if (ignores.hasOwnProperty(w) || (matchs && inText(matchs, n))) {
      return true;
    }
    if (['state', 'props'].indexOf(w) < 0) {
      console.error(`'${from.fromSrc}' 中发现无效变量引用 '${word}'，XML模板中只能引用组件'props'和'state'中的数据。`.red);
    }

    return false;
  }

  if (prefix) {
    prefix += '.';
  } else {
    prefix = '';
  }
  return str.replace(/\{\{([^}]+)\}\}/ig, function (matchs, words) {
    // matchs 是{{xxxxx}}格式的字符串
    // words  是{{}}中间的表达式

    // ...foo
    if (/^\s*\.\.\.[\w_][\w\d\-_.\[\]]*\s*$/.test(words)) {
      let word = words.match(/\s*\.\.\.([\w_][\w\d\-_.\[\]]*)/)[1].trim();
      if (shouldIgnore(word)) {
        return matchs;
      }
      return `{{...${prefix}${word}}}`;
    }

    let isArray = /{{\s*\[/.test(matchs);
    if (!isArray) {
      //支持对象简写
      let arrays = words.split(',');
      if (arrays.length > 1) {
        let isObject = true;
        let props = arrays.map(function (str) {
          if (!isObject) return;
          // str 为对象中的一个属性， 可能为 a:b / a / ...a / ...a.b
          str = str.trim();

          let arr = str.split(':');
          if (arr.length === 1) {
            // 如果属性表达式中不包含冒号

            // 如果为简写属性表达式，例如 {foo}
            if (/^[a-z_][\w\d]*$/i.test(str)) {
              if (ignores[str]) {
                return str + ':' + str;
              }
              return str + ':' + prefix + str;
            }

            // 属性展开表达式 ...foo
            if (/^\.{3}[a-z_][\w\d.\[\]]*$/i.test(str)) {
              let word = str.substr(3);
              if (shouldIgnore(word)) {
                return str;
              }
              return '...' + prefix + word;
            }

            // 判定 ${matchs} 不为对象表达式
            isObject = false;
            return;
          }

          // 存在冒号的对象属性表达式

          let word = arr[1].trim();
          // foo:2.3
          if (/^[\d.]+$/.test(word)) {
            return arr[0] + ':' + word;
          }

          // foo:bar
          // 'foo':bar
          if (shouldIgnore(word)) {
            return str;
          }

          // foo:bar
          // 'foo':bar
          // foo
          return arr[0] + ':' + prefix + word;
        });

        //console.log('isObject', isObject);
        if (isObject) {
          return '{{' + props.join(',') + '}}';
        }
      }
    }


    return matchs.replace(/[^\.\w'"]([a-z_\$][\w\d\._\$]*)/ig, function (match, word, n) {
      if (shouldIgnore(word, matchs, n)) {
        return match;
      }
      return match[0] + prefix + word;
    });
  });
}
function replaceString ( from , str , prefix , ignores ) { // 替换字符串中 {{}} 包含的表达式 // 获取类似 a.b.c 表达式中第一个有效变量名 a function getFirstWord ( word ) { return word . match ( / [_a-z][\w\d]* / i ) [ 0 ] ; } // 检查类似 a.b.c 格式表达式是否忽略绑定 function shouldIgnore ( word , matchs , n ) { if ( word [ 0 ] === '"' || word [ 0 ] === "'" || / ^\d+$ / . test ( word ) ) return true ; let w = getFirstWord ( word ) ; if ( ignores . hasOwnProperty ( w ) || ( matchs && inText ( matchs , n ) ) ) { return true ; } if ( [ 'state' , 'props' ] . indexOf ( w ) < 0 ) { console . error ( ` ${ from . fromSrc } 用组 件'pr o } return false ; } if ( prefix ) { prefix += '.' ; } else { prefix = '' ; } return str . replace ( / \{\{([^}]+)\}\} / ig , function ( matchs , words ) { // matchs 是{{xxxxx}}格式的字符串 // words  是{{}}中间的表达式 // ...foo if ( / ^\s*\.\.\.[\w_][\w\d\-_.\[\]]*\s*$ / . test ( words ) ) { let word = words . match ( / \s*\.\.\.([\w_][\w\d\-_.\[\]]*) / ) [ 1 ] . trim ( ) ; if ( shouldIgnore ( word ) ) { return matchs ; } return ` ${ prefix } ${ word } ` ; } let isArray = / {{\s*\[ / . test ( matchs ) ; if ( ! isArray ) { //支持对象简写 let arrays = words . split ( ',' ) ; if ( arrays . length > 1 ) { let isObject = true ; let props = arrays . map ( function ( str ) { if ( ! isObject ) return ; // str 为对象中的一个属性， 可能为 a:b / a / ...a / ...a.b str = str . trim ( ) ; let arr = str . split ( ':' ) ; if ( arr . length === 1 ) { // 如果属性表达式中不包含冒号 // 如果为简写属性表达式，例如 {foo} if ( / ^[a-z_][\w\d]*$ / i . test ( str ) ) { if ( ignores [ str ] ) { return str + ':' + str ; } return str + ':' + prefix + str ; } // 属性展开表达式 ...foo if ( / ^\.{3}[a-z_][\w\d.\[\]]*$ / i . test ( str ) ) { let word = str . substr ( 3 ) ; if ( shouldIgnore ( word ) ) { return str ; } return '...' + prefix + word ; } // 判定 ${matchs} 不为对象表达式 isObject = false ; return ; } // 存在冒号的对象属性表达式 let word = arr [ 1 ] . trim ( ) ; // foo:2.3 if ( / ^[\d.]+$ / . test ( word ) ) { return arr [ 0 ] + ':' + word ; } // foo:bar // 'foo':bar if ( shouldIgnore ( word ) ) { return str ; } // foo:bar // 'foo':bar // foo return arr [ 0 ] + ':' + prefix + word ; } ) ; //console.log('isObject', isObject); if ( isObject ) { return '{{' + props . join ( ',' ) + '}}' ; } } } return matchs . replace ( / [^\.\w'"]([a-z_\$][\w\d\._\$]*) / ig , function ( match , word , n ) { if ( shouldIgnore ( word , matchs , n ) ) { return match ; } return match [ 0 ] + prefix + word ; } ) ; } ) ; }
将带数据绑定的字符串替换
@param {Object} from
@param {string} str     原始字符串
@param {string} prefix  前缀
@param {object} ignores 忽略的字符串map
@returns {string}
将带数据绑定的字符串替换