WayfinderでExt.tree用のjsonを出力する

WayfinderはMODXのメニューを自動生成してくれます。
Ext.treeは独自のjavascript配列を解釈してWindowsのExplorer風のツリーを表示します。

jsonの形式は
[{
  key1:value,
  key2:value,
  key3:{
    key1:value,
    key2:value
  },
  key3:{
    key1:value,
    key2:value,
    key3:{
      key1:value,
      key2:value
    }
  }
}]

と配列の要素を「,(カンマ)」で区切って記述しますが、Wayfinderでは最後の要素を意識しないので、最後の要素のあとにもカンマがついてしまいます。
$RowLastTplと$parentRowLastTplを使えるようにします。

ドキュメントエイリアス:(ページ名).json
テンプレート:(blank)
コンテンツタイプ:text/jacvascript
内容:【【Wayfinder? &startId=`0` &config=`Ext_menu`】】

&config=で設定ファイルを使用することができます。
assets/snippets/wayfinder/configs/Ext_menu.config.php

<?php
$removeNewLines = "true";
$outerTpl = "@CODE:【【+wf.wrapper+】】";
$rowTpl = "@CODE:{
 href:'javascript:getDoc(\'【+wf.link+】\',\'【+wf.linktext+】\');void(0);',
 text:'【+wf.linktext+】(【+wf.subitemcount+】)',
 id:【+wf.docid+】,
 leaf:true,
 cls: 'file'
【+wf.wrapper+】},";
$parentRowTpl = "@CODE:{
 href:'javascript:getDoc(\'【+wf.link+】\',\'【+wf.linktext+】\');void(0);',
 text:'【+wf.linktext+】(【+wf.subitemcount+】)',
 id:【+wf.docid+】,
 cls:'folder',
children:【【+wf.wrapper+】】},";
$rowLastTpl = "@CODE:{
 href:'javascript:getDoc(\'【+wf.link+】\',\'【+wf.linktext+】\');void(0);',
 text:'【+wf.linktext+】(【+wf.subitemcount+】)',
 id:【+wf.docid+】,
 leaf:true,
 cls: 'file'
【+wf.wrapper+】}";
$parentRowLastTpl = "@CODE:{
 href:'javascript:getDoc(\'【+wf.link+】\',\'【+wf.linktext+】\');void(0);',
 text:'【+wf.linktext+】(【+wf.subitemcount+】)',
 id:【+wf.docid+】,
 cls:'folder',
children:【【+wf.wrapper+】】}";
$innerTpl = "@CODE:【+wf.wrapper+】";
?>

(「【」と「】」は実際は「[」と「]」です)   

assets/snippets/wayfinder/wayfinder.inc.php
98行目あたり

if ($counter == ($numSubItems)) $docInfo['last'] = 1;
   //Determine if document has children  

160行目あたり、

        } elseif ($resource['isfolder'] && $this->_templates['parentRowTpl'] && ($resource['level'] < $this->_config['level'] || $this->_config['level'] == 0) && $numChildren && $resource['last']) {
            $usedTemplate = 'parentRowLastTpl';
        } elseif ($resource['isfolder'] && $this->_templates['parentRowTpl'] && ($resource['level'] < $this->_config['level'] || $this->_config['level'] == 0) && $numChildren) {
            $usedTemplate = 'parentRowTpl';
        } elseif ($resource['level'] > 1 && $this->_templates['innerRowTpl']) {
            $usedTemplate = 'innerRowTpl';
        } elseif($resource['last']) {
            $usedTemplate = 'rowLastTpl';
        } else {
            $usedTemplate = 'rowTpl';
        }  

出力の結果はこちら、
http://www.tonttu.net/Ext_menu.json

Ext.treeは次のように解釈します。
 href要素でリンククリック動作、
 text要素で表示文字列、
 id要素でID、
 leaf要素がtrueの場合、終端、
 cls要素でアイコン画像、'file'、'folder'を指定してあります。

Extの記述。ここではWindowダイアログの中にTreePanelを表示しています。

  var treeWindow = new Ext.Window({
   id         :winid,
   title      :winid,
   layout     :'fit',
   width      :240,
   height     :360,
   minWidth   :64,
   closable   :false,
   collapsible:true,
   bodyStyle:'background-color: white;',
   items:treepanel = new Ext.tree.TreePanel({
    autoScroll :true,
    loader: new Ext.tree.TreeLoader({
     dataUrl:'/Ext_menu.json'
    }),
    root: treeroot = new Ext.tree.AsyncTreeNode({
     text: 'Root',
     id:'root'
    })
   })]
  });
  treeroot.expand();
  treeWindow.show();