元派遣プログラマの自称技術系ブログです。雑記とか自作のオープンソースプロジェクトの話とか。
Javaとか組込とかできます。お仕事ください。

javascriptで都合よくhtmlフラグメントを生成する関数

JavascriptでちょっとしたHTMLをjavascriptオブジェクトから作る関数を作った。類似品を検索したけど見つけられなかった。もし似たようなのがあったら教えてください。

例えばこんなjsオブジェクトから、

var src=["div",{class:1,text:"",},[
    ["div",[
      "AAAA",
      "BBBB",
      ["span",["CCCC"]],
    ]],
    "DDDD",
    ["span","EEEE"],
  ]];

こうやって

var tags=j2t(src,2);
console.log(tags);

こんな文字列を作る

<div class="1" text="">
  <div>
    AAAA
    BBBB
    <span>
      CCCC
    </span>
  </div>
  DDDD
  <span>EEEE</span>
</div>

ソース

  /**
   * javascriptオブジェクトをHTMLフラグメントに変換します。
   * OBJ:=[tagname,({attr}),([OBJ,]|text)]
   * 2,3番目のフラグメントは省略可能。
   * 2番目はタグの属性、3番目は子要素を示す。
   * 3番目の要素が配列の場合は
   */
  function j2t(v,indent=0)
  {
    function isHashArray(a){return (Object.prototype.toString.call(a) === '[object Object]');};
    function isArray(a){return Array.isArray(a);};
    function repeat(s,n){var r="";for(var i=0;i<n;i++){r+=s};return r};
    var rsp=repeat(" ",indent);
    function _o2t(v,depth){
      var pindent=(indent>0 && depth>0?"\n"+repeat(rsp,depth):"");
      var sindent=(indent>0?"\n"+repeat(rsp,depth):"");
      if(!isArray(v)){
        return pindent+v;
      }
      var attr=(v.length>1 && isHashArray(v[1]))?v[1]:null;
      var tags=(v.length==2 && isArray(v[1]))?v[1]:((v.length==3 && isArray(v[2]))?v[2]:null);
      var text=(v.length==2 && !isArray(v[1]))?v[1]:((v.length==3 && !isArray(v[2]))?v[2]:null);
      var s=pindent+"<"+v[0];
      if(attr){
        for(var i in attr){
          s+=" "+i+"=\""+attr[i]+"\"";
        }
      }
      if(tags){
        s+=">";
        for(var i of tags){
          s=s+_o2t(i,depth+1);
        }
        s+=sindent+"</"+v[0]+">";
      }else if(text){
        s+=">"+text+"</"+v[0]+">";

      }else{
        s+="/>";
      }
      return s;
    }
    return _o2t(v,0);
  }

仕様

j2t関数の1番目の引数は変換元のオブジェクト。入れ子になった最大3要素の配列。1番目にタグ名、2番目に属性、3番目に子要素の情報を書く。2,3番目は省略可能。3番目が配列の場合は再帰的に展開する。文字列の場合は単一の文字要素として展開する。

2番目の引数は出力のインデント数。省略時は0でインデントなし。

戻り値は文字列。


頭が悪いので再帰的に参照するオブジェクトを放り込むと死ぬ。