<commit_before>// ZJU-cs-basic-opt
// model.js - 获取数据

var DEBUG = 1;
var url_list = {
    index: "index.asp",
    login: "login/check.asp",
    login_succ: "index_student.asp",
    logout: "login/logout.asp"
};
var url_handler = {
    index: {
        lesson_announce: ["function", function($o) {
            $ob = $o.find('span[style="font-weight: 400"]');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        _method: "GET"
    },
    login: {
        login_fail: ["reg", /alert\('(.+?)'\)/, 1],             //注释一发：reg为regexp的缩写，正则表达式；function为函数，参数为parse的jQuery对象。
        login_succ: ["reg", /index_student[.]asp/, 0],
        _method: "POST"
    },
    login_succ: {
        user_info: ["reg", /(.+?)<\/TD>/, 1],
        lesson_info: ["function", function($o) {
            $ob = $o.find('span[style="font-weight: 400"]');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        lesson_announce: ["function", function($o) {
            $ob = $o.find('td > marquee');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        lesson_title: ["function", function($o) {
            $ob = $o.find('td[valign=middle] > b');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        task_title: ["function", function() {
            return ['上机实验', '课程作业', '课程资料', '课程讲稿'];
        }],
        task_obj: ["function", function($o) {
            var retobj = [], turl = [];
            $o.find("a").each(function() {
                if (this.innerHTML == '上机实验')
                turl[0] = this.href.replace(/&/g, '&');
                if (this.innerHTML == '课程作业')
                turl[1] = this.href.replace(/&/g, '&');
                if (this.innerHTML == '课程资料')
                turl[2] = this.href.replace(/&/g, '&');
                if (this.innerHTML == '课程讲稿')
                turl[3] = this.href.replace(/&/g, '&');
            });
            for (var i in turl)
            {
                var pagename = '';
                switch(parseInt(i))
                {
                    case 0:
                        pagename = 'jobexam/ExamList.asp';break;
                    case 1:
                        pagename = 'jobexam/ExamList.asp';break;
                    case 2:
                        pagename = 'courceinfo/resource.asp';break;
                    case 3:
                        pagename = 'courceinfo/jianggao.asp';break;
                    default:
                        break;
                }
                retobj[i] = pagename+'?flag='+(i%2).toString()+'&'+$.param(getArgs(turl[i].match(/[^?]+$/)[0]));
            }
            return retobj;
            /**************************
                 以下func: getArgs 源自 ->
             http://www.jsann.com/post/JS_GET_parameters_to_obtain.html
            **************************/
            function getArgs(url){
                var args = {};
                var match = null;
                var search = url;
                var reg = /(?:([^&]+)=([^&]+))/g;
                while((match = reg.exec(search))!==null){
                    args[match[1]] = match[2];
                }
                return args;
            }
        }],
        _method: "GET"
    },
    logout: {
        _method: "GET"
    },
    task0: {
        notification: ["function", function($o) {
            return $o.find("font").eq(0).parent().text();
        }],
        data: ["function", function($o) {
            var no = [], req = [], stt = [], ddl = [], dlr = [], prb = [], upl = [];
            var $trs = $o.find('tr[bordercolor="#e9f0f4"][bgcolor="#f8f3fb"]');
            $trs.each(function() {
                $c = $(this).children();
                no.push($c.eq(0).html());
                req.push($c.eq(1).html());
                stt.push($c.eq(2).html());
                ddl.push($c.eq(3).html());
                dlr.push(th($c.eq(4).children('a').attr('href')));
                prb.push($c.eq(5).children('a').attr('href'));
                upl.push($c.eq(6).children('a').attr('href'));
            });
            function th(u){return '../'+/teacher\.data.+$/.exec(u)[0]}
            return {no:no,req:req,stt:stt,ddl:ddl,dlr:dlr,prb:prb,upl:upl};
        }],
        _method: "GET"
    },
    task1: {
        notification: ["function", function($o) {
            return $o.find("font").eq(0).parent().text();
        }],
        data: ["function", function($o) {
            var no = [], req = [], stt = [], ddl = [], dlr = [], prb = [], upl = [];
            var $trs = $o.find('tr[bordercolor="#e9f0f4"][bgcolor="#f8f3fb"]');
            $trs.each(function() {
                $c = $(this).children();
                no.push($c.eq(0).html());
                req.push($c.eq(1).html());
                stt.push($c.eq(2).html());
                ddl.push($c.eq(3).html());
                dlr.push(th($c.eq(4).children('a').attr('href')));
                prb.push($c.eq(5).children('a').attr('href'));
                upl.push($c.eq(6).children('a').attr('href'));
            });
            function th(u){return '../'+/teacherdata.+$/.exec(u)[0]}
            return {no:no,req:req,stt:stt,ddl:ddl,dlr:dlr,prb:prb,upl:upl};
        }],
        _method: "GET"
    },
    task2: {
        // id 资料号 资料主题 资料描述 发布日期 操作
        data: ["function", function($o) {
            var nod = [], res = [], sbj = [], des = [], tim = [], opr = [];
            var $trs = $o.find('tr[bgcolor="#FFFFFF"]');
            $trs.each(function() {
                $c = $(this).children();
                nod.push($c.eq(0).html());
                res.push($c.eq(1).html());
                sbj.push($c.eq(2).html());
                des.push($c.eq(3).html());
                tim.push($c.eq(4).html());
                opr.push(th($c.eq(5).children('a').attr('href')));
            });
            function th(u){return '../'+/teacherdata.+$/.exec(u)[0]}
            return [nod,res,sbj,des,tim,opr];
        }],
        _method: "GET"
    },
    task3: {
        // id 章节号 讲稿标题 讲稿描述 操作
        data: ["function", function($o) {
            var nod = [], chn = [], cht = [], chd = [], opr = [];
            var $trs = $o.find('tr[bgcolor="#FFFFFF"]');
            $trs.each(function() {
                $c = $(this).children();
                nod.push($c.eq(0).html());
                chn.push($c.eq(1).html());
                cht.push($c.eq(2).html());
                chd.push($c.eq(3).html());
                opr.push(th($c.eq(4).children('a').attr('href')));
            });
            function th(u){return '../'+/teacherdata.+$/.exec(u)[0]}
            return [nod,chn,cht,chd,opr];
        }],
        _method: "GET"
    }
};
function cmodel(vw)
{
    jQuery.ajaxSetup({
        async: true,
        error: function() {
            vw.myAlert("发送网络请求失败。");
        }
    });
    try {
        this.tn = location.href.match(/tt=(\w+)[&]/)[1];
        this.linksuffix = '?tt='+this.tn+'&tn='+this.tn;
    }
    catch(e) {
        console.error('错误：无法获知具体的链接参数');
    }
    if ($.browser.mozilla)      //for firefox
    {
        alert('本脚本不能良好地支持firefox浏览器，尤其是在奇怪的编码问题方面');
    }
    this.init();
}
cmodel.prototype = {
    init: function() {
        this.updateCookies(this.getAllCookie());
    },
    getAllCookie: function() {
        var retobj = [];
        var o1 = document.cookie.split(';');
        for (var i in o1)
        {
            var o2 = o1[i].split('=');
            retobj.push({key: o2[0], value: o2[1]});
        }
        return retobj;
    },
    updateCookies: function(arr) {
        if (typeof arr.length == 'undefined') arr = [arr];
        for (var i in arr)
        {
            document.cookie = arr[i].key + '=' + arr[i].value + "; expires=Mon, 26 Jul 1997 05:00:00 GMT; path=/cstcx";
            document.cookie = arr[i].key + '=' + arr[i].value + "; expires=Tue, 11 Mar 2036 13:12:31 GMT; path=/cstcx";
        }
    },
    clearCookies: function() {
        var arr = document.cookie.split(';');
        for (var i in arr)
        {
            var o2 = arr[i].split('=');
            document.cookie = o2[0] + '=' + '' + "; expires=Mon, 26 Jul 1997 05:00:00 GMT; path=/cstcx";
        }
    },
    fetch: function(location, data, callback) {
        if (typeof data == 'undefined') data = '';
        var f_obj = url_handler[location];
        var retstr = '';
        fetch_callback_1 = this._fetch_cb;
        if (typeof callback == 'undefined') callback = function() {};
        if (f_obj._method == 'GET')
        {
            $.get(url_list[location], this.linksuffix+'&'+data, function(data){retstr=data;callback(fetch_callback_1(retstr, f_obj));}, "html");
        }
        else if(f_obj._method == 'POST')
        {
            $.post(url_list[location]+this.linksuffix, data, function(data){retstr=data;callback(fetch_callback_1(retstr, f_obj));}, "html");
        }
    },
    _fetch_cb: function(retstr, f_obj) {
        var retobj = {};
        var $o = $(retstr);
        for (e in f_obj)
        {
            if (e != '_method')
            {
                if (f_obj[e][0] == 'reg')
                {
                    if (f_obj[e][1].test(retstr))
                    {
                        try {
                            retobj[e] = [];
                            var matches = retstr.match(f_obj[e][1]);
                            retobj[e] = matches[f_obj[e][2]];
                        }
                        catch(e)
                        {
                            retobj[e] = 0;
                        }
                    }
                    else
                    {
                        retobj[e] = 0;
                    }
                }
                else
                {
                    retobj[e] = f_obj[e][1]($o);
                }

            }
        }
        if (DEBUG) console.debug(retobj);
        return retobj;
    }
}

<commit_msg>大计基网站变了<commit_after>// ZJU-cs-basic-opt
// model.js - 获取数据

var DEBUG = 1;
var url_list = {
    index: "index.asp",
    login: "login/check.asp",
    login_succ: "index_student.asp",
    logout: "login/logout.asp"
};
var url_handler = {
    index: {
        lesson_announce: ["function", function($o) {
            $ob = $o.find('span[style="font-weight: 400"]');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        _method: "GET"
    },
    login: {
        login_fail: ["reg", /alert\('(.+?)'\)/, 1],             //注释一发：reg为regexp的缩写，正则表达式；function为函数，参数为parse的jQuery对象。
        login_succ: ["reg", /index_student[.]asp/, 0],
        _method: "POST"
    },
    login_succ: {
        user_info: ["reg", /(.+?)<\/TD>/, 1],
        lesson_info: ["function", function($o) {
            $ob = $o.find('span[style="font-weight: 400"]');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        lesson_announce: ["function", function($o) {
            $ob = $o.find('td > marquee');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        lesson_title: ["function", function($o) {
            $ob = $o.find('td[valign=middle] > b');
            var ret = [];
            for (var i=0;i<$ob.length;i++)
                ret.push($ob.eq(i).html());
            return ret;
        }],
        task_title: ["function", function() {
            return ['上机实验', '课程作业', '课程资料', '课程讲稿'];
        }],
        task_obj: ["function", function($o) {
            var retobj = [], turl = [];
            $o.find("a").each(function() {
                if (this.innerHTML == '上机实验')
                turl[0] = this.href.replace(/&/g, '&');
                if (this.innerHTML == '课程作业')
                turl[1] = this.href.replace(/&/g, '&');
                if (this.innerHTML == '课程资料')
                turl[2] = this.href.replace(/&/g, '&');
                if (this.innerHTML == '课程讲稿')
                turl[3] = this.href.replace(/&/g, '&');
            });
            for (var i in turl)
            {
                var pagename = '';
                switch(parseInt(i))
                {
                    case 0:
                        pagename = 'jobexam/ExamList.asp';break;
                    case 1:
                        pagename = 'jobexam/ExamList.asp';break;
                    case 2:
                        pagename = 'courceinfo/resource.asp';break;
                    case 3:
                        pagename = 'courceinfo/jianggao.asp';break;
                    default:
                        break;
                }
                retobj[i] = pagename+'?flag='+(i%2).toString()+'&'+$.param(getArgs(turl[i].match(/[^?]+$/)[0]));
            }
            return retobj;
            /**************************
                 以下func: getArgs 源自 ->
             http://www.jsann.com/post/JS_GET_parameters_to_obtain.html
            **************************/
            function getArgs(url){
                var args = {};
                var match = null;
                var search = url;
                var reg = /(?:([^&]+)=([^&]+))/g;
                while((match = reg.exec(search))!==null){
                    args[match[1]] = match[2];
                }
                return args;
            }
        }],
        _method: "GET"
    },
    logout: {
        _method: "GET"
    },
    task0: {
        notification: ["function", function($o) {
            return $o.find("font").eq(0).parent().text();
        }],
        data: ["function", function($o) {
            var no = [], req = [], stt = [], ddl = [], dlr = [], prb = [], upl = [];
            var $trs = $o.find('tr[bordercolor="#e9f0f4"][bgcolor="#f8f3fb"]');
            $trs.each(function() {
                $c = $(this).children();
                no.push($c.eq(0).html());
                req.push($c.eq(1).html());
                stt.push($c.eq(2).html());
                ddl.push($c.eq(3).html());
                dlr.push(th($c.eq(4).children('a').attr('href')));
                prb.push($c.eq(5).children('a').attr('href'));
                upl.push($c.eq(6).children('a').attr('href'));
            });
            function th(u){return '../'+/teacher\.data.+$/.exec(u)[0]}
            return {no:no,req:req,stt:stt,ddl:ddl,dlr:dlr,prb:prb,upl:upl};
        }],
        _method: "GET"
    },
    task1: {
        notification: ["function", function($o) {
            return $o.find("font").eq(0).parent().text();
        }],
        data: ["function", function($o) {
            var no = [], req = [], stt = [], ddl = [], dlr = [], prb = [], upl = [];
            var $trs = $o.find('tr[bordercolor="#e9f0f4"][bgcolor="#f8f3fb"]');
            $trs.each(function() {
                $c = $(this).children();
                no.push($c.eq(0).html());
                req.push($c.eq(1).html());
                stt.push($c.eq(2).html());
                ddl.push($c.eq(3).html());
                dlr.push(th($c.eq(4).children('a').attr('href')));
                prb.push($c.eq(5).children('a').attr('href'));
                upl.push($c.eq(6).children('a').attr('href'));
            });
            function th(u){return '../'+/teacher\.data.+$/.exec(u)[0]}
            return {no:no,req:req,stt:stt,ddl:ddl,dlr:dlr,prb:prb,upl:upl};
        }],
        _method: "GET"
    },
    task2: {
        // id 资料号 资料主题 资料描述 发布日期 操作
        data: ["function", function($o) {
            var nod = [], res = [], sbj = [], des = [], tim = [], opr = [];
            var $trs = $o.find('tr[bgcolor="#FFFFFF"]');
            $trs.each(function() {
                $c = $(this).children();
                nod.push($c.eq(0).html());
                res.push($c.eq(1).html());
                sbj.push($c.eq(2).html());
                des.push($c.eq(3).html());
                tim.push($c.eq(4).html());
                opr.push(th($c.eq(5).children('a').attr('href')));
            });
            function th(u){return '../'+/teacher\.data.+$/.exec(u)[0]}
            return [nod,res,sbj,des,tim,opr];
        }],
        _method: "GET"
    },
    task3: {
        // id 章节号 讲稿标题 讲稿描述 操作
        data: ["function", function($o) {
            var nod = [], chn = [], cht = [], chd = [], opr = [];
            var $trs = $o.find('tr[bgcolor="#FFFFFF"]');
            $trs.each(function() {
                $c = $(this).children();
                nod.push($c.eq(0).html());
                chn.push($c.eq(1).html());
                cht.push($c.eq(2).html());
                chd.push($c.eq(3).html());
                opr.push(th($c.eq(4).children('a').attr('href')));
            });
            function th(u){return '../'+/teacher\.data.+$/.exec(u)[0]}
            return [nod,chn,cht,chd,opr];
        }],
        _method: "GET"
    }
};
function cmodel(vw)
{
    jQuery.ajaxSetup({
        async: true,
        error: function() {
            vw.myAlert("发送网络请求失败。");
        }
    });
    try {
        this.tn = location.href.match(/tt=(\w+)[&]/)[1];
        this.linksuffix = '?tt='+this.tn+'&tn='+this.tn;
    }
    catch(e) {
        console.error('错误：无法获知具体的链接参数');
    }
    if ($.browser.mozilla)      //for firefox
    {
        alert('本脚本不能良好地支持firefox浏览器，尤其是在奇怪的编码问题方面');
    }
    this.init();
}
cmodel.prototype = {
    init: function() {
        this.updateCookies(this.getAllCookie());
    },
    getAllCookie: function() {
        var retobj = [];
        var o1 = document.cookie.split(';');
        for (var i in o1)
        {
            var o2 = o1[i].split('=');
            retobj.push({key: o2[0], value: o2[1]});
        }
        return retobj;
    },
    updateCookies: function(arr) {
        if (typeof arr.length == 'undefined') arr = [arr];
        for (var i in arr)
        {
            document.cookie = arr[i].key + '=' + arr[i].value + "; expires=Mon, 26 Jul 1997 05:00:00 GMT; path=/cstcx";
            document.cookie = arr[i].key + '=' + arr[i].value + "; expires=Tue, 11 Mar 2036 13:12:31 GMT; path=/cstcx";
        }
    },
    clearCookies: function() {
        var arr = document.cookie.split(';');
        for (var i in arr)
        {
            var o2 = arr[i].split('=');
            document.cookie = o2[0] + '=' + '' + "; expires=Mon, 26 Jul 1997 05:00:00 GMT; path=/cstcx";
        }
    },
    fetch: function(location, data, callback) {
        if (typeof data == 'undefined') data = '';
        var f_obj = url_handler[location];
        var retstr = '';
        fetch_callback_1 = this._fetch_cb;
        if (typeof callback == 'undefined') callback = function() {};
        if (f_obj._method == 'GET')
        {
            $.get(url_list[location], this.linksuffix+'&'+data, function(data){retstr=data;callback(fetch_callback_1(retstr, f_obj));}, "html");
        }
        else if(f_obj._method == 'POST')
        {
            $.post(url_list[location]+this.linksuffix, data, function(data){retstr=data;callback(fetch_callback_1(retstr, f_obj));}, "html");
        }
    },
    _fetch_cb: function(retstr, f_obj) {
        var retobj = {};
        var $o = $(retstr);
        for (e in f_obj)
        {
            if (e != '_method')
            {
                if (f_obj[e][0] == 'reg')
                {
                    if (f_obj[e][1].test(retstr))
                    {
                        try {
                            retobj[e] = [];
                            var matches = retstr.match(f_obj[e][1]);
                            retobj[e] = matches[f_obj[e][2]];
                        }
                        catch(e)
                        {
                            retobj[e] = 0;
                        }
                    }
                    else
                    {
                        retobj[e] = 0;
                    }
                }
                else
                {
                    retobj[e] = f_obj[e][1]($o);
                }

            }
        }
        if (DEBUG) console.debug(retobj);
        return retobj;
    }
}

<|endoftext|>


<commit_before>/**
# Components

    component(name, url);

Loads component from url registers it as "name". (Components are registered
separately from other objects.)

Returns a promise of the component once loaded.

    component('path/to/name');

If just a path is provided, the name of the component will be
inferred.

**Note**: the extension `.component.html` is appended to urls.

Instances of the component will automatically be inserted as expected once
loaded.

**Also note**: you can usually avoid the pattern:

    component(...).then(c => b8r.insertComponent(c, target))

By simply binding the component to the target and letting nature take its
course.

    b8r.insertComponent(component, element, data);

insert a component by name or by passing a component record (e.g. promised by
component() or produced by makeComponent)

If no element is provided, the component will be appended to `document.body`.

Data will be passed to the component's load method and registered as the
component's private instance data. (Usually data is passed automatically
from parent components or via binding, e.g. `data-path="path.to.data` binds that
data to the component).

    b8r.removeComponent(elt); // removes the component's class and instance and empties the element

If elt has a component in it (i.e. has the attribute data-component-id) removes the
element's contents, removes the component-id, and removes any class that ends with '-component'.
Note that `removeComponent` does not preserve children!

## Creating Components Programmatically

    makeComponent(name, source, url, preserveSource); // preserveSource are optional

Create a component with the specified name, source code, and url. Use preserveSource if
you want the component's source code kept for debugging purposes.

`makeComponent` is used internally by component to create components, and by the documentation
system to create components interactively. In general you won't need to use this method at all.

## Singleton Components

    b8r.componentOnce(url [,name]);

This loads the component (if necessary) and then if there is no instance of the component
in the DOM it creates one. It replaces the pattern:

    b8r.component(url).then(c => b8r.insertComponent(c));

And doesn't run the risk of leaking multiple instances of components into the DOM.

## Container Components

    b8r.wrapWithComponent(component, element [, data_path [, attributes]]);

Sometimes you want a component *outside* an element rather than inside it.
The most common example is trying to create a specific modal or floater wrapped
inside a generic modal or floater "wrapper". You could simply use the
generic component inside the specific component but then the generic component
has no simple way to "clean itself up".

`b8r.wrapWithComponent()` returns the wrapping element.

      <button
        data-event="click:_component_.terrific"
      >Terrific</button>

In the above example the modal ends up inside the `my-custom-dialog` div. Supposing
that the modal's behavior includes removing itself on close, it will leave behind the
component itself (with nothing inside).

Instead with `wrapWithComponent` you could do this (in a component):

    <button>Terrific</button>

(Note that this example doesn't play well with the inline-documentation system!)

## Destructors

Component instances are automatically cleaned up once the component element is
removed from the DOM or its id changes (e.g. a new component is loaded over it).
If you want to force a cleanup, you can call:

    b8r.cleanupComponentInstances();

If a component has a property named `destroy` (and it's a method) it will
be called just before the instance is removed from the registry.
*/

import { asyncUpdate } from './b8r.update.js'
import { create, find, findWithin } from './b8r.dom.js'
import { ajax } from './b8r.ajax.js'
import makeStylesheet from './b8r.makeStylesheet.js'
import uuid from './uuid.js'
import { AsyncFunction } from './b8r.functions.js'

const components = {}
const componentTimeouts = []
const componentPromises = {}
const componentPreloadMap = {}

/**
## Making Components without Eval

You may prefer to create pure javascript components for any number of reasons.

    makeComponentNoEval(name, {css, html, load})

`load` is a function with the signature:

    async ({component, b8r, find, findOne, data, register, get, set, on, touch}) => {
      // same stuff you'd normally put in a component's script
    }

This should appease linters!

```
<b8r-component name="no-eval"></b8r-component>
<script>
  b8r.makeComponentNoEval('no-eval', {
    css: '._component_ > span { color: yellow; }',
    html: '<span></span>',
    load: async ({findOne}) => {
      findOne('span').textContent = 'Hello Pure Component'
    }
  })
</script>
```
*/

const makeComponentNoEval = function (name, { css, html, load }) {
  const div = document.createElement('div')
  div.innerHTML = html

  const className = `${name}-component`
  const style = css ? makeStylesheet(css.replace(/_component_/g, className), className) : false
  const updateClasses = elt => elt.setAttribute('class', elt.getAttribute('class').replace(/_component_/g, className))
  findWithin(div, '[class*="_component_"]').forEach(updateClasses)
  const component = {
    name,
    style,
    view: div,
    load: (component, b8r, find, findOne, data, register, get, set, on, touch) => {
      load({ component, b8r, find, findOne, data, register, get, set, on, touch })
    },
    path: `inline-${name}`
  }

  if (componentTimeouts[name]) {
    clearInterval(componentTimeouts[name])
  }

  find(`[data-component="${name}"]`).forEach(element => {
    // somehow things can happen in between find() and here so the
    // second check is necessary to prevent race conditions
    if (!element.closest('[data-list]') && element.dataset.component === name) {
      asyncUpdate(false, element)
    }
  })
  components[name] = component
  return component
}

const makeComponent = function (name, source, url, preserveSource) {
  let css = false; let content; let script = false; let parts; let remains

  if (!url) url = uuid()
  componentPreloadMap[name] = url

  // nothing  rest-of-component
  parts = source.split(/ rest-of-component
  parts = source.split(/


<commit_before>/**
 * The main class of the API Browser
 *
 * #asset(apibrowser/*)
 */
core.Class('api.Browser', {

	construct: function(base) {

		// Store data path
		if (!base) {
			base = "data";
		}

		this.__base = base;

		// Load initial data
		core.io.Queue.load([
			base + "/$index.jsonp",
			base + "/$template.jsonp",
			base + "/$search.jsonp"
		], this.__onLoad, this, false, "js");

		// Initialize data processor
		this.__processor = new api.Processor({
			showPrivate: true
		});

		this.__index = {};

	},

	members: {

		__onLoad : function() {

			var that = this;

			$('h3').live('click', function(event) {
				$(this).parent('li').toggleClass('unfold');
			});

			$('a').live('click', function(event) {

				var link = $(this).attr('href');

				if (link.charAt(0) == '#') {
					that.open(link.slice(1));
					return false;
				}

			});

		},

		callback: function(data, id) {

			if (id == "$index") {

				console.debug("Loaded Index");

				document.getElementById('menu-tree').innerHTML = this.__treeWalker(data, "");
				this.open(location.hash);

			} else if (id == "$template") {

				console.debug("Loaded Template");
				this.__template = core.template.Compiler.compile(data.template);

			} else if (id == "$search") {

				console.debug("Loaded Search Index");

			} else {

				console.debug("Loaded Class: " + id);

			}

		},

		__treeWalker: function(node, base) {

			var html = '';

			var filter = function(value) {
				return value.charAt(0) != "$";
			};

			var comparator = function(a, b) {

				if (node[a].$type == node[b].$type) {

					return a > b ? 1 : -1;

				} else if (node[a].$type == "Package") {

					return -1;

				} else if (node[b].$type == "Package") {

					return 1;

				} else {

					return 0;

				}

			}

			var keys = Object.keys(node).filter(filter).sort(comparator);

			for (var i=0, l=keys.length; i<l; i++) {

				var key = keys[i];
				var entry = node[key];
				var name = base ? base + "." + key : key;

				if (entry.$type == "Package") {

					html += '
' + key + '
' + this.__treeWalker(entry, name) + '

';

				} else {

					html += '
' + key + '
';

				}

			}

			return html;

		},

		open: function(hash) {

			if (hash.match(/!/)) {
				hash = hash.substr(1);
			}

			var data, params = [];

			if (hash.match(/\./)) {

				data = hash.substr(1, hash.length - 1).split('.');

				// namespace
				params.push(data[0]);

				if (data[1].match(/:/)) {
					data = data[1].split(/:/);
					params.push(data[0]); // class (id)
					params.push(data[1]); // method
				} else {
					params.push(data[1]); // class (id)
				}

			} else if (hash.match(/:/)) {

				params.push(this.__current.namespace);
				params.push(this.__current.id);
				params.push(hash.substr(1));

				hash = this.__current.namespace + '.' + this.__current.id + ':' + hash.substr(1);

			}

			var success = this.show.apply(this, params);
			if (success) {
				location.hash = hash;
			}

		},

		show: function(namespace, id, method) {

			namespace = typeof namespace == 'string' ? namespace : null;
			id = typeof id == 'string' ? id : null;
			method = typeof method == 'string' ? method : null;

			if (namespace == null || id == null) {
				return false;
			}

			var entry = this.__index[namespace + '.' + id];

			if (entry === undefined) {
				entry = this.__index[namespace + '.' + id] = {
					namespace: namespace,
					id: id
				};
			}

			if (
				entry.data === undefined
			) {

				var file = this.__base + '/' + namespace + '.' + id + '.json';
				this.load(file, function(status, json) {

					entry.data = this.__processor.processJSON(json);
					this.__current = entry;
					this.__render(entry);

				}, this);

			} else {
				this.__current = entry;
				this.__render(entry);
			}

			return true;

		},

		__render: function(entry) {

			var html = this.__template.render(entry.data);

			$('#content').html(html);

		}

	}

});

<commit_msg>Cleanup<commit_after>/**
 * The main class of the API Browser
 *
 * #asset(apibrowser/*)
 */
core.Class('api.Browser', {

	construct: function(base) {

		// Store data path
		if (!base) {
			base = "data";
		}

		this.__base = base;

		// Load initial data
		core.io.Queue.load([
			base + "/$index.jsonp",
			base + "/$template.jsonp",
			base + "/$search.jsonp"
		], this.__onLoad, this, false, "js");

		// Initialize data processor
		this.__processor = new api.Processor({
			showPrivate: true
		});

		this.__index = {};

	},

	members: {

		__onLoad : function() {

			var that = this;

			$('h3').live('click', function(event) {
				$(this).parent('li').toggleClass('unfold');
			});

			$('a').live('click', function(event) {

				var link = $(this).attr('href');
				if (link.charAt(0) == '#') {
					that.open(link.slice(1));
					return false;
				}

			});

		},

		callback: function(data, id) {

			if (id == "$index") {

				console.debug("Loaded Index");

				document.getElementById('menu-tree').innerHTML = this.__treeWalker(data, "");
				this.open(location.hash);

			} else if (id == "$template") {

				console.debug("Loaded Template");
				this.__template = core.template.Compiler.compile(data.template);

			} else if (id == "$search") {

				console.debug("Loaded Search Index");

			} else {

				console.debug("Loaded Class: " + id);

			}

		},

		__treeWalker: function(node, base) {

			var html = '';

			var filter = function(value) {
				return value.charAt(0) != "$";
			};

			var comparator = function(a, b) {

				if (node[a].$type == node[b].$type) {

					return a > b ? 1 : -1;

				} else if (node[a].$type == "Package") {

					return -1;

				} else if (node[b].$type == "Package") {

					return 1;

				} else {

					return 0;

				}

			}

			var keys = Object.keys(node).filter(filter).sort(comparator);

			for (var i=0, l=keys.length; i<l; i++) {

				var key = keys[i];
				var entry = node[key];
				var name = base ? base + "." + key : key;

				if (entry.$type == "Package") {

					html += '
' + key + '
' + this.__treeWalker(entry, name) + '

';

				} else {

					html += '
' + key + '
';

				}

			}

			return html;

		},

		open: function(hash) {

			if (hash.match(/!/)) {
				hash = hash.substr(1);
			}

			var data, params = [];

			if (hash.match(/\./)) {

				data = hash.substr(1, hash.length - 1).split('.');

				// namespace
				params.push(data[0]);

				if (data[1].match(/:/)) {
					data = data[1].split(/:/);
					params.push(data[0]); // class (id)
					params.push(data[1]); // method
				} else {
					params.push(data[1]); // class (id)
				}

			} else if (hash.match(/:/)) {

				params.push(this.__current.namespace);
				params.push(this.__current.id);
				params.push(hash.substr(1));

				hash = this.__current.namespace + '.' + this.__current.id + ':' + hash.substr(1);

			}

			var success = this.show.apply(this, params);
			if (success) {
				location.hash = hash;
			}

		},

		show: function(namespace, id, method) {

			namespace = typeof namespace == 'string' ? namespace : null;
			id = typeof id == 'string' ? id : null;
			method = typeof method == 'string' ? method : null;

			if (namespace == null || id == null) {
				return false;
			}

			var entry = this.__index[namespace + '.' + id];

			if (entry === undefined) {
				entry = this.__index[namespace + '.' + id] = {
					namespace: namespace,
					id: id
				};
			}

			if (
				entry.data === undefined
			) {

				var file = this.__base + '/' + namespace + '.' + id + '.json';
				this.load(file, function(status, json) {

					entry.data = this.__processor.processJSON(json);
					this.__current = entry;
					this.__render(entry);

				}, this);

			} else {
				this.__current = entry;
				this.__render(entry);
			}

			return true;

		},

		__render: function(entry) {

			var html = this.__template.render(entry.data);

			$('#content').html(html);

		}

	}

});

<|endoftext|>


<commit_before>const xml2js = require("xml2js");

function extractKey(xmlKey) {
    const match = /^([a-z0-9]+:)?(.+)$/i.exec(xmlKey);
    if (!match) {
        throw new Error(`Failed to extract key for response XML: ${xmlKey}`);
    }
    return match[2];
}

function findKey(baseKey, obj) {
    return Object.keys(obj).find(function __findBaseKey(itemKey) {
        const match = /^[a-z0-9]+:(.+)$/i.exec(itemKey);
        return match ? match[1] === baseKey : itemKey === baseKey;
    });
}

function getSingleValue(item) {
    return Array.isArray(item) ? getSingleValue(item[0]) : item;
}

function getValueForKey(key, obj) {
    let keys, i, keyCount;
    if (typeof obj === "object") {
        const actualKey = findKey(key, obj);
        if (actualKey && typeof obj[actualKey] !== "undefined") {
            return obj[actualKey];
        }
    }
    return undefined;
}

function parseXML(xml) {
    const parser = new xml2js.Parser({ emptyTag: true, ignoreAttrs: true });
    return new Promise(function(resolve, reject) {
        parser.parseString(xml, function __handleParseResult(err, result) {
            if (err) {
                return reject(err);
            }
            return resolve(result);
        });
    });
}

function propsToStat(props, filename, isDetailed = false) {
    const path = require("path-posix");
    // Last modified time, raw size, item type and mime
    const lastMod = getSingleValue(getValueForKey("getlastmodified", props));
    const rawSize = getSingleValue(getValueForKey("getcontentlength", props)) || "0";
    const resourceType = getSingleValue(getValueForKey("resourcetype", props));
    const mimeType = getSingleValue(getValueForKey("getcontenttype", props));
    const type = getValueForKey("collection", resourceType) ? "directory" : "file";
    const etag = getSingleValue(getValueForKey("getetag", props));
    const stat = {
        filename: filename,
        basename: path.basename(filename),
        lastmod: lastMod,
        size: parseInt(rawSize, 10),
        type: type,
        etag: etag ? etag.replace(/"/g, "") : null
    };
    if (type === "file") {
        stat.mime = mimeType && typeof mimeType === "string" ? mimeType.split(";")[0] : "";
    }
    if (isDetailed) {
        stat.props = Object.keys(props)
            .map(extractKey)
            .reduce(
                (output, propName) =>
                    Object.assign(output, {
                        [propName]: getSingleValue(getValueForKey(propName, props))
                    }),
                {}
            );
    }
    return stat;
}

function translateDiskSpace(value) {
    switch (value.toString()) {
        case "-3":
            return "unlimited";
        case "-2":
        /* falls-through */
        case "-1":
            // -1 is non-computed
            return "unknown";
        default:
            return parseInt(value, 10);
    }
}

module.exports = {
    getSingleValue,
    getValueForKey,
    parseXML,
    propsToStat,
    translateDiskSpace
};
<commit_msg>Ensure etag is a string (#167)<commit_after>const xml2js = require("xml2js");

function extractKey(xmlKey) {
    const match = /^([a-z0-9]+:)?(.+)$/i.exec(xmlKey);
    if (!match) {
        throw new Error(`Failed to extract key for response XML: ${xmlKey}`);
    }
    return match[2];
}

function findKey(baseKey, obj) {
    return Object.keys(obj).find(function __findBaseKey(itemKey) {
        const match = /^[a-z0-9]+:(.+)$/i.exec(itemKey);
        return match ? match[1] === baseKey : itemKey === baseKey;
    });
}

function getSingleValue(item) {
    return Array.isArray(item) ? getSingleValue(item[0]) : item;
}

function getValueForKey(key, obj) {
    let keys, i, keyCount;
    if (typeof obj === "object") {
        const actualKey = findKey(key, obj);
        if (actualKey && typeof obj[actualKey] !== "undefined") {
            return obj[actualKey];
        }
    }
    return undefined;
}

function parseXML(xml) {
    const parser = new xml2js.Parser({ emptyTag: true, ignoreAttrs: true });
    return new Promise(function(resolve, reject) {
        parser.parseString(xml, function __handleParseResult(err, result) {
            if (err) {
                return reject(err);
            }
            return resolve(result);
        });
    });
}

function propsToStat(props, filename, isDetailed = false) {
    const path = require("path-posix");
    // Last modified time, raw size, item type and mime
    const lastMod = getSingleValue(getValueForKey("getlastmodified", props));
    const rawSize = getSingleValue(getValueForKey("getcontentlength", props)) || "0";
    const resourceType = getSingleValue(getValueForKey("resourcetype", props));
    const mimeType = getSingleValue(getValueForKey("getcontenttype", props));
    const type = getValueForKey("collection", resourceType) ? "directory" : "file";
    const etag = getSingleValue(getValueForKey("getetag", props));
    const stat = {
        filename: filename,
        basename: path.basename(filename),
        lastmod: lastMod,
        size: parseInt(rawSize, 10),
        type: type,
        etag: typeof etag === "string" ? etag.replace(/"/g, "") : null
    };
    if (type === "file") {
        stat.mime = mimeType && typeof mimeType === "string" ? mimeType.split(";")[0] : "";
    }
    if (isDetailed) {
        stat.props = Object.keys(props)
            .map(extractKey)
            .reduce(
                (output, propName) =>
                    Object.assign(output, {
                        [propName]: getSingleValue(getValueForKey(propName, props))
                    }),
                {}
            );
    }
    return stat;
}

function translateDiskSpace(value) {
    switch (value.toString()) {
        case "-3":
            return "unlimited";
        case "-2":
        /* falls-through */
        case "-1":
            // -1 is non-computed
            return "unknown";
        default:
            return parseInt(value, 10);
    }
}

module.exports = {
    getSingleValue,
    getValueForKey,
    parseXML,
    propsToStat,
    translateDiskSpace
};
<|endoftext|>


<commit_before>/*
	This file is part of the "jQuery.Syntax" project, and is licensed under the GNU AGPLv3.

	Copyright 2010 Samuel Williams. All rights reserved.

	For more information, please see http://www.oriontransfer.co.nz/software/jquery-syntax

	This program is free software: you can redistribute it and/or modify it under the terms
	of the GNU Affero General Public License as published by the Free Software Foundation,
	either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License along with this
	program. If not, see <http://www.gnu.org/licenses/>.
*/

/*global Function: true, ResourceLoader: true, Syntax: true, alert: false, jQuery: true */

// ECMAScript 5! Why wasn't this done before!?
if (!Function.prototype.bind) {
	Function.prototype.bind = function (target) {
		var args = Array.prototype.slice.call(arguments, 1), fn = this;

		return function () {
			return fn.apply(target, args);
		};
	};
}

function ResourceLoader (loader) {
	this.dependencies = {};
	this.loading = {};
	this.loader = loader;
}

ResourceLoader.prototype._finish = function (name) {
	var deps = this.dependencies[name];

	if (deps) {
		// I'm not sure if this makes me want to cry... or laugh... or kill!?
		var chain = this._loaded.bind(this, name);

		for (var i = 0; i < deps.length; i += 1) {
			chain = this.get.bind(this, deps[i], chain);
		}

		chain();
	} else {
		this._loaded(name);
	}
};

ResourceLoader.prototype._loaded = function (name) {
	// When the script has been succesfully loaded, we expect the script
	// to register with this loader (i.e. this[name]).
	var resource = this[name], loading = this.loading[name];

	// Clear the loading list
	this.loading[name] = null;

	if (!resource) {
		alert("Could not load resource named " + name);
	} else {
		for (var i = 0; i < loading.length; i += 1) {
			loading[i](resource);
		}
	}
};

ResourceLoader.prototype.dependency = function (current, next) {
	 // if it is already loaded, it isn't a dependency
	if (this[next]) {
		return;
	}

	if (this.dependencies[current]) {
		this.dependencies[current].push(next);
	} else {
		this.dependencies[current] = [next];
	}
};

ResourceLoader.prototype.get = function (name, callback) {
	if (this[name]) {
		callback(this[name]);
	} else if (this.loading[name]) {
		this.loading[name].push(callback);
	} else {
		this.loading[name] = [callback];
		this.loader(name, this._finish.bind(this, name));
	}
};

var Syntax = {
	root: null,
	aliases: {},
	styles: {},
	lib: {},
	defaultOptions: {
		cacheScripts: true
	},

	brushes: new ResourceLoader(function (name, callback) {
		name = Syntax.aliases[name] || name;

		Syntax.getResource('jquery.syntax.brush', name, callback);
	}),

	layouts: new ResourceLoader(function (name, callback) {
		Syntax.getResource('jquery.syntax.layout', name, callback);
	}),

	loader: new ResourceLoader(function (name, callback) {
		Syntax.getResource('jquery.syntax', name, callback);
	}),

	getStyles: function (path) {
		var link = jQuery('<link>');
		jQuery("head").append(link);

		link.attr({
			rel: "stylesheet",
			type: "text/css",
			href: path
		});
	},

	getScript: function (path, callback) {
		jQuery.ajax({
			type: "GET",
			url: path,
			success: callback,
			error: function(xhr, status, error) {
				alert("Could not load resource: " + path + " " + error);
			},
			dataType: "script",
			cache: Syntax.defaultOptions.cacheScripts
		});
	},

	getResource: function (prefix, name, callback) {
		var basename = prefix + "." + name;

		if (this.styles[basename]) {
			this.getStyles(this.root + this.styles[basename]);
		}

		Syntax.getScript(this.root + basename + '.js', callback);
	},

	alias: function (name, aliases) {
		Syntax.aliases[name] = name;

		for (var i = 0; i < aliases.length; i += 1) {
			Syntax.aliases[aliases[i]] = name;
		}
	},

	brushAliases: function (brush) {
		var aliases = [];

		for (var name in Syntax.aliases) {
			if (Syntax.aliases[name] === brush) {
				aliases.push(name);
			}
		}

		return aliases;
	},

	brushNames: function () {
		var names = [];

		for (var name in Syntax.aliases) {
			if (name === Syntax.aliases[name]) {
				names.push(name);
			}
		}

		return names;
	},

	extractBrushName: function (className) {
		// brush names are by default lower case - normalize so we can detect it.
		className = className.toLowerCase();

		var match = className.match(/brush-([\S]+)/);

		if (match) {
			return match[1];
		} else {
			var classes = className.split(/ /);

			if (jQuery.inArray("syntax", classes) !== -1) {
				for (var i = 0; i < classes.length; i += 1) {
					var name = Syntax.aliases[classes[i]];

					if (name) {
						return name;
					}
				}
			}
		}

		return null;
	}
};

jQuery(function() {
	if (Syntax.root == null) {
		// Initialize root based on current script path.
		var scripts = $('script').filter(function(){
			return this.src.match(/jquery\.syntax/);
		});

		var first = scripts.get(0);

		if (first) {
			// Calculate the basename for the given script src.
			var root = first.src.match(/.*\//);

			if (root) {
				Syntax.root = root[0];
			}
		}
	}
});

jQuery.fn.syntax = function (options, callback) {
	var elements = this;

	Syntax.loader.get('core', function () {
		Syntax.highlight(elements, options, callback);
	});
};

jQuery.syntax = function (options, callback) {
	options = options || {};
	var context = options.context;

	if (options.root) {
		Syntax.root = options.root;
	}

	options = jQuery.extend(Syntax.defaultOptions, options)

	options.blockSelector = options.blockSelector || 'pre.syntax:not(.highlighted)';
	options.inlineSelector = options.inlineSelector || 'code.syntax:not(.highlighted)';

	options.blockLayout = options.blockLayout || 'list';
	options.inlineLayout = options.inlineLayout || 'inline';

	// Allow the user to specify callbacks without replacement.
	if (typeof options.replace == "undefined")
		options.replace = true;

	jQuery(options.blockSelector, context).each(function () {
		jQuery(this).syntax(jQuery.extend({}, options, {
			brush: Syntax.extractBrushName(this.className),
			layout: options.blockLayout
		}), callback);
	});

	jQuery(options.inlineSelector, context).each(function () {
		jQuery(this).syntax(jQuery.extend({}, options, {
			brush: Syntax.extractBrushName(this.className),
			layout: options.inlineLayout
		}), callback);
	});
};
<commit_msg>Added cache options for style sheets.<commit_after>/*
	This file is part of the "jQuery.Syntax" project, and is licensed under the GNU AGPLv3.

	Copyright 2010 Samuel Williams. All rights reserved.

	For more information, please see http://www.oriontransfer.co.nz/software/jquery-syntax

	This program is free software: you can redistribute it and/or modify it under the terms
	of the GNU Affero General Public License as published by the Free Software Foundation,
	either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
	without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License along with this
	program. If not, see <http://www.gnu.org/licenses/>.
*/

/*global Function: true, ResourceLoader: true, Syntax: true, alert: false, jQuery: true */

// ECMAScript 5! Why wasn't this done before!?
if (!Function.prototype.bind) {
	Function.prototype.bind = function (target) {
		var args = Array.prototype.slice.call(arguments, 1), fn = this;

		return function () {
			return fn.apply(target, args);
		};
	};
}

function ResourceLoader (loader) {
	this.dependencies = {};
	this.loading = {};
	this.loader = loader;
}

ResourceLoader.prototype._finish = function (name) {
	var deps = this.dependencies[name];

	if (deps) {
		// I'm not sure if this makes me want to cry... or laugh... or kill!?
		var chain = this._loaded.bind(this, name);

		for (var i = 0; i < deps.length; i += 1) {
			chain = this.get.bind(this, deps[i], chain);
		}

		chain();
	} else {
		this._loaded(name);
	}
};

ResourceLoader.prototype._loaded = function (name) {
	// When the script has been succesfully loaded, we expect the script
	// to register with this loader (i.e. this[name]).
	var resource = this[name], loading = this.loading[name];

	// Clear the loading list
	this.loading[name] = null;

	if (!resource) {
		alert("Could not load resource named " + name);
	} else {
		for (var i = 0; i < loading.length; i += 1) {
			loading[i](resource);
		}
	}
};

ResourceLoader.prototype.dependency = function (current, next) {
	 // if it is already loaded, it isn't a dependency
	if (this[next]) {
		return;
	}

	if (this.dependencies[current]) {
		this.dependencies[current].push(next);
	} else {
		this.dependencies[current] = [next];
	}
};

ResourceLoader.prototype.get = function (name, callback) {
	if (this[name]) {
		callback(this[name]);
	} else if (this.loading[name]) {
		this.loading[name].push(callback);
	} else {
		this.loading[name] = [callback];
		this.loader(name, this._finish.bind(this, name));
	}
};

var Syntax = {
	root: null,
	aliases: {},
	styles: {},
	lib: {},
	defaultOptions: {
		cacheScripts: true,
		cacheStyleSheets: true
	},

	brushes: new ResourceLoader(function (name, callback) {
		name = Syntax.aliases[name] || name;

		Syntax.getResource('jquery.syntax.brush', name, callback);
	}),

	layouts: new ResourceLoader(function (name, callback) {
		Syntax.getResource('jquery.syntax.layout', name, callback);
	}),

	loader: new ResourceLoader(function (name, callback) {
		Syntax.getResource('jquery.syntax', name, callback);
	}),

	getStyles: function (path) {
		var link = jQuery('<link>');
		jQuery("head").append(link);

		if (!Syntax.defaultOptions.cacheStyleSheets) {
			path = path + "?" + Math.random()
		}

		link.attr({
			rel: "stylesheet",
			type: "text/css",
			href: path
		});
	},

	getScript: function (path, callback) {
		jQuery.ajax({
			type: "GET",
			url: path,
			success: callback,
			error: function(xhr, status, error) {
				alert("Could not load resource: " + path + " " + error);
			},
			dataType: "script",
			cache: Syntax.defaultOptions.cacheScripts
		});
	},

	getResource: function (prefix, name, callback) {
		var basename = prefix + "." + name;

		if (this.styles[basename]) {
			this.getStyles(this.root + this.styles[basename]);
		}

		Syntax.getScript(this.root + basename + '.js', callback);
	},

	alias: function (name, aliases) {
		Syntax.aliases[name] = name;

		for (var i = 0; i < aliases.length; i += 1) {
			Syntax.aliases[aliases[i]] = name;
		}
	},

	brushAliases: function (brush) {
		var aliases = [];

		for (var name in Syntax.aliases) {
			if (Syntax.aliases[name] === brush) {
				aliases.push(name);
			}
		}

		return aliases;
	},

	brushNames: function () {
		var names = [];

		for (var name in Syntax.aliases) {
			if (name === Syntax.aliases[name]) {
				names.push(name);
			}
		}

		return names;
	},

	extractBrushName: function (className) {
		// brush names are by default lower case - normalize so we can detect it.
		className = className.toLowerCase();

		var match = className.match(/brush-([\S]+)/);

		if (match) {
			return match[1];
		} else {
			var classes = className.split(/ /);

			if (jQuery.inArray("syntax", classes) !== -1) {
				for (var i = 0; i < classes.length; i += 1) {
					var name = Syntax.aliases[classes[i]];

					if (name) {
						return name;
					}
				}
			}
		}

		return null;
	}
};

jQuery(function() {
	if (Syntax.root == null) {
		// Initialize root based on current script path.
		var scripts = $('script').filter(function(){
			return this.src.match(/jquery\.syntax/);
		});

		var first = scripts.get(0);

		if (first) {
			// Calculate the basename for the given script src.
			var root = first.src.match(/.*\//);

			if (root) {
				Syntax.root = root[0];
			}
		}
	}
});

jQuery.fn.syntax = function (options, callback) {
	var elements = this;

	Syntax.loader.get('core', function () {
		Syntax.highlight(elements, options, callback);
	});
};

jQuery.syntax = function (options, callback) {
	options = options || {};
	var context = options.context;

	if (options.root) {
		Syntax.root = options.root;
	}

	options = jQuery.extend(Syntax.defaultOptions, options)

	options.blockSelector = options.blockSelector || 'pre.syntax:not(.highlighted)';
	options.inlineSelector = options.inlineSelector || 'code.syntax:not(.highlighted)';

	options.blockLayout = options.blockLayout || 'list';
	options.inlineLayout = options.inlineLayout || 'inline';

	// Allow the user to specify callbacks without replacement.
	if (typeof options.replace == "undefined")
		options.replace = true;

	jQuery(options.blockSelector, context).each(function () {
		jQuery(this).syntax(jQuery.extend({}, options, {
			brush: Syntax.extractBrushName(this.className),
			layout: options.blockLayout
		}), callback);
	});

	jQuery(options.inlineSelector, context).each(function () {
		jQuery(this).syntax(jQuery.extend({}, options, {
			brush: Syntax.extractBrushName(this.className),
			layout: options.inlineLayout
		}), callback);
	});
};
<|endoftext|>


<commit_before>'use strict';

angular.module('uiCropper').directive('uiCropper', ['$timeout', 'cropHost', 'cropPubSub', function ($timeout, CropHost, CropPubSub) {
    return {
        restrict: 'E',
        scope: {
            image: '=',
            resultImage: '=',
            resultArrayImage: '=?',
            resultBlob: '=?',
            urlBlob: '=?',
            chargement: '=?',
            cropject: '=?',
            maxCanvasDimensions: '=?',
            minCanvasDimensions: '=?',
            canvasScalemode: '@?', /* String. If set to 'full-width' the directive uses all width available */
            /* and the canvas expands in height as much as it need to maintain the aspect ratio */
            /* if set to 'fixed-height', the directive is restricted by a parent element in height */

            changeOnFly: '=?',
            liveView: '=?',
            initMaxArea: '=?',
            areaCoords: '=?',
            areaType: '@',
            areaMinSize: '=?',
            areaInitSize: '=?',
            areaInitCoords: '=?',
            areaInitIsRelativeToImage: '=?', /* Boolean: If true the areaInitCoords and areaInitSize is scaled according to canvas size. */
            /* No matter how big/small the canvas is, the resultImage remains the same */
            /* Example: areaInitCoords are {x: 100, y: 100}, areaInitSize {w: 100, h: 100}   */
            /* Image is 1000x1000
             /* if canvas is 500x500 Crop coordinates will be x: 50, y: 50, w: 50, h: 50 */
            /* if canvas is 100x100 crop coordinates will be x: 10, y: 10, w: 10, h: 10 */
            areaMinRelativeSize: '=?',
            resultImageSize: '=?',
            resultImageFormat: '@',
            resultImageQuality: '=?',

            aspectRatio: '=?',
            allowCropResizeOnCorners: '=?',

            dominantColor: '=?',
            paletteColor: '=?',
            paletteColorLength: '=?',

            onChange: '&',
            onLoadBegin: '&',
            onLoadDone: '&',
            onLoadError: '&'
        },
        template: '<canvas></canvas>',
        controller: ['$scope', function ($scope) {
            $scope.events = new CropPubSub();
        }],
        link: function (scope, element) {
            // Init Events Manager
            var events = scope.events;

            // Init Crop Host
            var cropHost = new CropHost(element.find('canvas'), {}, events);

            if (scope.canvasScalemode) {
                cropHost.setScalemode(scope.canvasScalemode);
            } else {
                cropHost.setScalemode('fixed-height');
            }

            element.addClass(cropHost.getScalemode());

            // Store Result Image to check if it's changed
            var storedResultImage;

            var updateAreaCoords = function (scope) {
                scope.areaCoords = cropHost.getAreaCoords();
            };

            var updateResultImage = function (scope, force, callback) {
                if (scope.image !== '' && (!scope.liveView.block || force)) {
                    var resultImageObj = cropHost.getResultImage();
                    var resultImage;
                    if (angular.isArray(resultImageObj)) {
                        resultImage = resultImageObj[0].dataURI;
                        scope.resultArrayImage = resultImageObj;
                    } else {
                        resultImage = resultImageObj.dataURI;
                    }

                    var urlCreator = window.URL || window.webkitURL;
                    if (storedResultImage !== resultImage) {
                        storedResultImage = resultImage;
                        scope.resultImage = resultImage;
                        if (scope.liveView.callback) {
                            scope.liveView.callback(resultImage);
                        }
                        if (callback) {
                            callback(resultImage);
                        }
                        cropHost.getResultImageDataBlob().then(function (blob) {
                            scope.resultBlob = blob;
                            scope.urlBlob = urlCreator.createObjectURL(blob);
                        });

                        if (scope.resultImage) {
                            cropHost.getDominantColor(scope.resultImage).then(function (dominantColor) {
                                scope.dominantColor = dominantColor;
                            });
                            cropHost.getPalette(scope.resultImage).then(function (palette) {
                                scope.paletteColor = palette;
                            });
                        }

                        updateAreaCoords(scope);
                        scope.onChange({
                            $dataURI: scope.resultImage
                        });
                    }
                }
            };

            if (scope.liveView && typeof scope.liveView.block === 'boolean') {
                scope.liveView.render = function (callback) {
                    updateResultImage(scope, true, callback);
                };
            } else {
                scope.liveView = {block: false};
            }

            var updateCropject = function (scope) {
                var areaCoords = cropHost.getAreaCoords();

                var dimRatio = {
                    x: cropHost.getArea().getImage().width / cropHost.getArea().getCanvasSize().w,
                    y: cropHost.getArea().getImage().height / cropHost.getArea().getCanvasSize().h
                };

                scope.cropject = {
                    canvasSize: cropHost.getArea().getCanvasSize(),
                    areaCoords: areaCoords,
                    cropWidth: areaCoords.w,
                    cropHeight: areaCoords.h,
                    cropTop: areaCoords.y,
                    cropLeft: areaCoords.x,
                    cropImageWidth: Math.round(areaCoords.w * dimRatio.x),
                    cropImageHeight: Math.round(areaCoords.h * dimRatio.y),
                    cropImageTop: Math.round(areaCoords.y * dimRatio.y),
                    cropImageLeft: Math.round(areaCoords.x * dimRatio.x)
                };
            };

            // Wrapper to safely exec functions within $apply on a running $digest cycle
            var fnSafeApply = function (fn) {
                return function () {
                    $timeout(function () {
                        scope.$apply(function (scope) {
                            fn(scope);
                        });
                    });
                };
            };

            // Will get the users language settings, and return the appropriate loading text
            var printLoadMsg = function () {
                var language = window.navigator.userLanguage || window.navigator.language;

                switch (language) {
                    case 'nl':
                    case 'nl_NL':
                        return 'Aan het laden';

                    case 'fr':
                    case 'fr-FR':
                        return 'Chargement';

                    case 'es':
                    case 'es-ES':
                        return 'Cargando';

                    case 'ca':
                    case 'ca-ES':
                        return 'Càrrega';

                    case 'de':
                    case 'de-DE':
                        return 'Laden';

                    default:
                        return 'Loading';
                }
            };

            if (!scope.chargement) {
                scope.chargement = printLoadMsg();
            }
            var displayLoading = function () {
                element.append('
' + scope.chargement + '...
');
            };

            // Setup CropHost Event Handlers
            events
                .on('load-start', fnSafeApply(function (scope) {
                    scope.onLoadBegin({});
                }))
                .on('load-done', fnSafeApply(function (scope) {
                    var children = element.children();
                    angular.forEach(children, function (child) {
                        if (angular.element(child).hasClass('loading')) {
                            angular.element(child).remove();
                        }
                    });
                    updateCropject(scope);
                    scope.onLoadDone({});
                }))
                .on('load-error', fnSafeApply(function (scope) {
                    scope.onLoadError({});
                }))
                .on('area-move area-resize', fnSafeApply(function (scope) {
                    if (scope.changeOnFly === 'true') {
                        updateResultImage(scope);
                    }
                    updateCropject(scope);
                }))
                .on('image-updated', fnSafeApply(function (scope) {
                    cropHost.setAreaMinRelativeSize(scope.areaMinRelativeSize);
                }))
                .on('area-move-end area-resize-end image-updated', fnSafeApply(function (scope) {
                    updateResultImage(scope);
                    updateCropject(scope);
                }));

            // Sync CropHost with Directive's options
            scope.$watch('image', function (newVal) {
                if (newVal) {
                    displayLoading();
                }
                // cancel timeout if necessary
                if (scope.timeout !== null) {
                    $timeout.cancel(scope.timeout);
                }
                scope.timeout = $timeout(function () {
                    scope.timeout = null;
                    cropHost.setInitMax(scope.initMaxArea);
                    cropHost.setNewImageSource(scope.image);
                }, 100);
            });
            scope.$watch('areaType', function () {
                cropHost.setAreaType(scope.areaType);
                updateResultImage(scope);
            });
            scope.$watch('areaMinSize', function () {
                cropHost.setAreaMinSize(scope.areaMinSize);
                updateResultImage(scope);
            });
            scope.$watch('areaMinRelativeSize', function () {
                if (scope.image !== '') {
                    cropHost.setAreaMinRelativeSize(scope.areaMinRelativeSize);
                    updateResultImage(scope);
                }
            });
            scope.$watch('areaInitSize', function () {
                cropHost.setAreaInitSize(scope.areaInitSize);
                updateResultImage(scope);
            });
            scope.$watch('areaInitCoords', function () {
                cropHost.setAreaInitCoords(scope.areaInitCoords);
                cropHost.areaInitIsRelativeToImage = scope.areaInitIsRelativeToImage;
                updateResultImage(scope);
            });
            scope.$watch('maxCanvasDimensions', function () {
                cropHost.setMaxCanvasDimensions(scope.maxCanvasDimensions);
            });
            scope.$watch('minCanvasDimensions', function () {
                cropHost.setMinCanvasDimensions(scope.minCanvasDimensions);
            });
            scope.$watch('resultImageFormat', function () {
                cropHost.setResultImageFormat(scope.resultImageFormat);
                updateResultImage(scope);
            });
            scope.$watch('resultImageQuality', function () {
                cropHost.setResultImageQuality(scope.resultImageQuality);
                updateResultImage(scope);
            });
            scope.$watch('resultImageSize', function () {
                cropHost.setResultImageSize(scope.resultImageSize);
                updateResultImage(scope);
            });
            scope.$watch('paletteColorLength', function () {
                cropHost.setPaletteColorLength(scope.paletteColorLength);
            });
            scope.$watch('aspectRatio', function () {
                if (typeof scope.aspectRatio === 'string' && scope.aspectRatio !== '') {
                    scope.aspectRatio = parseInt(scope.aspectRatio);
                }
                if (scope.aspectRatio) {
                    cropHost.setAspect(scope.aspectRatio);
                }
            });
            scope.$watch('allowCropResizeOnCorners', function () {
                if (scope.allowCropResizeOnCorners) {
                    cropHost.setAllowCropResizeOnCorners(scope.allowCropResizeOnCorners);
                }
            });

            // Update CropHost dimensions when the directive element is resized
            scope.$watch(
                function () {
                    if (cropHost.getScalemode() === 'fixed-height') {
                        return [element[0].clientWidth, element[0].clientHeight];
                    }
                    if (cropHost.getScalemode() === 'full-width') {
                        return element[0].clientWidth;
                    }
                },
                function (value) {

                    if (cropHost.getScalemode() === 'fixed-height') {
                        if (value[0] > 0 && value[1] > 0) {
                            cropHost.setMaxDimensions(value[0], value[1]);
                            updateResultImage(scope);
                        }
                    }
                    if (cropHost.getScalemode() === 'full-width') {
                        if (value > 0) {
                            cropHost.setMaxDimensions(value);
                        }
                    }
                },
                true
            );

            // Destroy CropHost Instance when the directive is destroying
            scope.$on('$destroy', function () {
                cropHost.destroy();
            });
        }
    };
}]);
<commit_msg>change-on-fly value fix<commit_after>'use strict';

angular.module('uiCropper').directive('uiCropper', ['$timeout', 'cropHost', 'cropPubSub', function ($timeout, CropHost, CropPubSub) {
    return {
        restrict: 'E',
        scope: {
            image: '=',
            resultImage: '=',
            resultArrayImage: '=?',
            resultBlob: '=?',
            urlBlob: '=?',
            chargement: '=?',
            cropject: '=?',
            maxCanvasDimensions: '=?',
            minCanvasDimensions: '=?',
            canvasScalemode: '@?', /* String. If set to 'full-width' the directive uses all width available */
            /* and the canvas expands in height as much as it need to maintain the aspect ratio */
            /* if set to 'fixed-height', the directive is restricted by a parent element in height */

            changeOnFly: '=?',
            liveView: '=?',
            initMaxArea: '=?',
            areaCoords: '=?',
            areaType: '@',
            areaMinSize: '=?',
            areaInitSize: '=?',
            areaInitCoords: '=?',
            areaInitIsRelativeToImage: '=?', /* Boolean: If true the areaInitCoords and areaInitSize is scaled according to canvas size. */
            /* No matter how big/small the canvas is, the resultImage remains the same */
            /* Example: areaInitCoords are {x: 100, y: 100}, areaInitSize {w: 100, h: 100}   */
            /* Image is 1000x1000
             /* if canvas is 500x500 Crop coordinates will be x: 50, y: 50, w: 50, h: 50 */
            /* if canvas is 100x100 crop coordinates will be x: 10, y: 10, w: 10, h: 10 */
            areaMinRelativeSize: '=?',
            resultImageSize: '=?',
            resultImageFormat: '@',
            resultImageQuality: '=?',

            aspectRatio: '=?',
            allowCropResizeOnCorners: '=?',

            dominantColor: '=?',
            paletteColor: '=?',
            paletteColorLength: '=?',

            onChange: '&',
            onLoadBegin: '&',
            onLoadDone: '&',
            onLoadError: '&'
        },
        template: '<canvas></canvas>',
        controller: ['$scope', function ($scope) {
            $scope.events = new CropPubSub();
        }],
        link: function (scope, element) {
            // Init Events Manager
            var events = scope.events;

            // Init Crop Host
            var cropHost = new CropHost(element.find('canvas'), {}, events);

            if (scope.canvasScalemode) {
                cropHost.setScalemode(scope.canvasScalemode);
            } else {
                cropHost.setScalemode('fixed-height');
            }

            element.addClass(cropHost.getScalemode());

            // Store Result Image to check if it's changed
            var storedResultImage;

            var updateAreaCoords = function (scope) {
                scope.areaCoords = cropHost.getAreaCoords();
            };

            var updateResultImage = function (scope, force, callback) {
                if (scope.image !== '' && (!scope.liveView.block || force)) {
                    var resultImageObj = cropHost.getResultImage();
                    var resultImage;
                    if (angular.isArray(resultImageObj)) {
                        resultImage = resultImageObj[0].dataURI;
                        scope.resultArrayImage = resultImageObj;
                    } else {
                        resultImage = resultImageObj.dataURI;
                    }

                    var urlCreator = window.URL || window.webkitURL;
                    if (storedResultImage !== resultImage) {
                        storedResultImage = resultImage;
                        scope.resultImage = resultImage;
                        if (scope.liveView.callback) {
                            scope.liveView.callback(resultImage);
                        }
                        if (callback) {
                            callback(resultImage);
                        }
                        cropHost.getResultImageDataBlob().then(function (blob) {
                            scope.resultBlob = blob;
                            scope.urlBlob = urlCreator.createObjectURL(blob);
                        });

                        if (scope.resultImage) {
                            cropHost.getDominantColor(scope.resultImage).then(function (dominantColor) {
                                scope.dominantColor = dominantColor;
                            });
                            cropHost.getPalette(scope.resultImage).then(function (palette) {
                                scope.paletteColor = palette;
                            });
                        }

                        updateAreaCoords(scope);
                        scope.onChange({
                            $dataURI: scope.resultImage
                        });
                    }
                }
            };

            if (scope.liveView && typeof scope.liveView.block === 'boolean') {
                scope.liveView.render = function (callback) {
                    updateResultImage(scope, true, callback);
                };
            } else {
                scope.liveView = {block: false};
            }

            var updateCropject = function (scope) {
                var areaCoords = cropHost.getAreaCoords();

                var dimRatio = {
                    x: cropHost.getArea().getImage().width / cropHost.getArea().getCanvasSize().w,
                    y: cropHost.getArea().getImage().height / cropHost.getArea().getCanvasSize().h
                };

                scope.cropject = {
                    canvasSize: cropHost.getArea().getCanvasSize(),
                    areaCoords: areaCoords,
                    cropWidth: areaCoords.w,
                    cropHeight: areaCoords.h,
                    cropTop: areaCoords.y,
                    cropLeft: areaCoords.x,
                    cropImageWidth: Math.round(areaCoords.w * dimRatio.x),
                    cropImageHeight: Math.round(areaCoords.h * dimRatio.y),
                    cropImageTop: Math.round(areaCoords.y * dimRatio.y),
                    cropImageLeft: Math.round(areaCoords.x * dimRatio.x)
                };
            };

            // Wrapper to safely exec functions within $apply on a running $digest cycle
            var fnSafeApply = function (fn) {
                return function () {
                    $timeout(function () {
                        scope.$apply(function (scope) {
                            fn(scope);
                        });
                    });
                };
            };

            // Will get the users language settings, and return the appropriate loading text
            var printLoadMsg = function () {
                var language = window.navigator.userLanguage || window.navigator.language;

                switch (language) {
                    case 'nl':
                    case 'nl_NL':
                        return 'Aan het laden';

                    case 'fr':
                    case 'fr-FR':
                        return 'Chargement';

                    case 'es':
                    case 'es-ES':
                        return 'Cargando';

                    case 'ca':
                    case 'ca-ES':
                        return 'Càrrega';

                    case 'de':
                    case 'de-DE':
                        return 'Laden';

                    default:
                        return 'Loading';
                }
            };

            if (!scope.chargement) {
                scope.chargement = printLoadMsg();
            }
            var displayLoading = function () {
                element.append('
' + scope.chargement + '...
');
            };

            // Setup CropHost Event Handlers
            events
                .on('load-start', fnSafeApply(function (scope) {
                    scope.onLoadBegin({});
                }))
                .on('load-done', fnSafeApply(function (scope) {
                    var children = element.children();
                    angular.forEach(children, function (child) {
                        if (angular.element(child).hasClass('loading')) {
                            angular.element(child).remove();
                        }
                    });
                    updateCropject(scope);
                    scope.onLoadDone({});
                }))
                .on('load-error', fnSafeApply(function (scope) {
                    scope.onLoadError({});
                }))
                .on('area-move area-resize', fnSafeApply(function (scope) {
                    if (scope.changeOnFly === true) {
                        updateResultImage(scope);
                    }
                    updateCropject(scope);
                }))
                .on('image-updated', fnSafeApply(function (scope) {
                    cropHost.setAreaMinRelativeSize(scope.areaMinRelativeSize);
                }))
                .on('area-move-end area-resize-end image-updated', fnSafeApply(function (scope) {
                    updateResultImage(scope);
                    updateCropject(scope);
                }));

            // Sync CropHost with Directive's options
            scope.$watch('image', function (newVal) {
                if (newVal) {
                    displayLoading();
                }
                // cancel timeout if necessary
                if (scope.timeout !== null) {
                    $timeout.cancel(scope.timeout);
                }
                scope.timeout = $timeout(function () {
                    scope.timeout = null;
                    cropHost.setInitMax(scope.initMaxArea);
                    cropHost.setNewImageSource(scope.image);
                }, 100);
            });
            scope.$watch('areaType', function () {
                cropHost.setAreaType(scope.areaType);
                updateResultImage(scope);
            });
            scope.$watch('areaMinSize', function () {
                cropHost.setAreaMinSize(scope.areaMinSize);
                updateResultImage(scope);
            });
            scope.$watch('areaMinRelativeSize', function () {
                if (scope.image !== '') {
                    cropHost.setAreaMinRelativeSize(scope.areaMinRelativeSize);
                    updateResultImage(scope);
                }
            });
            scope.$watch('areaInitSize', function () {
                cropHost.setAreaInitSize(scope.areaInitSize);
                updateResultImage(scope);
            });
            scope.$watch('areaInitCoords', function () {
                cropHost.setAreaInitCoords(scope.areaInitCoords);
                cropHost.areaInitIsRelativeToImage = scope.areaInitIsRelativeToImage;
                updateResultImage(scope);
            });
            scope.$watch('maxCanvasDimensions', function () {
                cropHost.setMaxCanvasDimensions(scope.maxCanvasDimensions);
            });
            scope.$watch('minCanvasDimensions', function () {
                cropHost.setMinCanvasDimensions(scope.minCanvasDimensions);
            });
            scope.$watch('resultImageFormat', function () {
                cropHost.setResultImageFormat(scope.resultImageFormat);
                updateResultImage(scope);
            });
            scope.$watch('resultImageQuality', function () {
                cropHost.setResultImageQuality(scope.resultImageQuality);
                updateResultImage(scope);
            });
            scope.$watch('resultImageSize', function () {
                cropHost.setResultImageSize(scope.resultImageSize);
                updateResultImage(scope);
            });
            scope.$watch('paletteColorLength', function () {
                cropHost.setPaletteColorLength(scope.paletteColorLength);
            });
            scope.$watch('aspectRatio', function () {
                if (typeof scope.aspectRatio === 'string' && scope.aspectRatio !== '') {
                    scope.aspectRatio = parseInt(scope.aspectRatio);
                }
                if (scope.aspectRatio) {
                    cropHost.setAspect(scope.aspectRatio);
                }
            });
            scope.$watch('allowCropResizeOnCorners', function () {
                if (scope.allowCropResizeOnCorners) {
                    cropHost.setAllowCropResizeOnCorners(scope.allowCropResizeOnCorners);
                }
            });

            // Update CropHost dimensions when the directive element is resized
            scope.$watch(
                function () {
                    if (cropHost.getScalemode() === 'fixed-height') {
                        return [element[0].clientWidth, element[0].clientHeight];
                    }
                    if (cropHost.getScalemode() === 'full-width') {
                        return element[0].clientWidth;
                    }
                },
                function (value) {

                    if (cropHost.getScalemode() === 'fixed-height') {
                        if (value[0] > 0 && value[1] > 0) {
                            cropHost.setMaxDimensions(value[0], value[1]);
                            updateResultImage(scope);
                        }
                    }
                    if (cropHost.getScalemode() === 'full-width') {
                        if (value > 0) {
                            cropHost.setMaxDimensions(value);
                        }
                    }
                },
                true
            );

            // Destroy CropHost Instance when the directive is destroying
            scope.$on('$destroy', function () {
                cropHost.destroy();
            });
        }
    };
}]);
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict'

const program = require('commander');
const miteApi = require('mite-api');
const chalk = require('chalk');
const async = require('async');
const tableLib = require('table')
const table = tableLib.table;

const pkg = require('./../package.json');
const config = require('./config.js');
const formater = require('./lib/formater');
const BUDGET_TYPE = formater.BUDGET_TYPE;
const SORT_OPTIONS = [
  'id',
  'name',
  'customer',
  'customer_name',
  'customer_id',
  'updated_at',
  'created_at',
  'hourly_rate',
  'rate',
  'budget',
];
const SORT_OPTIONS_DEFAULT = 'name';

program
  .version(pkg.version)
  .description('list, filter & search for projects')
  .option(
    '--sort <column>',
    `optional column the results should be case-insensitive ordered by `+
    `(default: "${SORT_OPTIONS_DEFAULT}"), ` +
    `valid values: ${SORT_OPTIONS.join(', ')}`,
    (value) => {
      if (SORT_OPTIONS.indexOf(value) === -1) {
        console.error(
          'Invalid value for sort option: "%s", valid values are: ',
          value,
          SORT_OPTIONS.join(', ')
        );
        process.exit(2);
      }
      return value;
    },
    SORT_OPTIONS_DEFAULT // default sor
  )
  .option(
    '--search <query>',
    'optional search string which must be somewhere in the project’s name ' +
    '(case insensitive)'
  )
  .option(
    '--customer_id <id>',
    'optional id of a customer (use mite customer) to filter the projects by'
  )
  .option(
    '--customer <regexp>',
    'optional client-side filter for customer names, case-insensitive'
  )
  .option(
    '-a, --archived <true|false>',
    'When used will only show either archived users or not archived users',
    ((val) => {
      if (typeof val !== 'string') {
        return val;
      }
      return ['true', 'yes', 'ja', 'ok', '1'].indexOf(val.toLowerCase()) > -1;
    }),
    false // default archive argument
  )
  .parse(process.argv);

const opts = {
  limit: 10000,
  name: program.search,
  customer_id: program.customer_id
};

const mite = miteApi(config.get());

async.parallel([
  async.apply(mite.getProjects, opts),
  async.apply(mite.getArchivedProjects, opts)
], (err, results) => {

  if (err) {
    throw err;
  }
  // merge archived and not archived projects together in one array
  const allProjects = [].concat(results[0], results[1]);
  // proclaim an array of tabular data by mapping and filtering the data
  const tableData = allProjects
    .map((e) => e.project)
    .filter((p) => {
      if (program.archived === null) {
        return true;
      }
      return program.archived === p.archived;
    })
    .filter((p) => {
      // filter by customer regexp, skip if no cli argument was given
      if (!program.customer) {
        return true;
      }
      const regexp = new RegExp(program.customer, 'i');
      return regexp.exec(p.customer_name) || regexp.exec(String(p.customer_id));
    })
    .sort((a, b) => {
      if (!program.sort) return 0;
      let sortByAttributeName = program.sort;
      if (sortByAttributeName === 'customer') {
        sortByAttributeName = 'customer_name';
      }
      if (sortByAttributeName === 'rate') {
        sortByAttributeName = 'hourly_rate';
      }
      var val1 = String(a[sortByAttributeName]).toLowerCase();
      var val2 = String(b[sortByAttributeName]).toLowerCase();
      if (val1 > val2) {
        return 1;
      } else if (val1 < val2) {
        return -1;
      } else {
        return 0;
      }
    })
    .map((data) => {
      let budget = formater.budget(data.budget_type, data.budget);
      if (!data.budget) {
        budget = '-'
      }
      let rate = formater.budget(BUDGET_TYPE.CENTS, data.hourly_rate);
      if (!data.hourly_rate) {
        rate = '-';
      }
      let customer = data.customer_name + ' (' + data.customer_id + ')';
      if (!data.customer_id) {
        customer = '-';
      }
      return [
        data.id,
        data.name,
        customer,
        budget,
        rate,
        data.note.replace(/\r?\n/g, ' '),
      ].map((v) => {
        if (data.archived) {
          return chalk.grey(v);
        }
        return v;
      })
    });
  tableData.unshift([
    'id',
    'name',
    'customer',
    'budget',
    'rate',
    'note',
  ].map((v) => chalk.bold(v)));
  const tableConfig = {
    border: tableLib.getBorderCharacters('norc'),
    columns: {
      1: {
        wrapWord: true,
      },
      3: {
        alignment: 'right',
      },
      4: {
        alignment: 'right',
      },
      5: {
        width: 50,
        wrapWord: true,
      }
    }
  };

  console.log(table(tableData, tableConfig));
});
<commit_msg>feat(projects): adds format option<commit_after>#!/usr/bin/env node
'use strict'

const program = require('commander');
const miteApi = require('mite-api');
const chalk = require('chalk');
const async = require('async');

const DataOutput = require('./lib/data-output');
const pkg = require('./../package.json');
const config = require('./config.js');
const formater = require('./lib/formater');
const BUDGET_TYPE = formater.BUDGET_TYPE;
const SORT_OPTIONS = [
  'id',
  'name',
  'customer',
  'customer_name',
  'customer_id',
  'updated_at',
  'created_at',
  'hourly_rate',
  'rate',
  'budget',
];
const SORT_OPTIONS_DEFAULT = 'name';

program
  .version(pkg.version)
  .description('list, filter & search for projects')
  .option(
    '--sort <column>',
    `optional column the results should be case-insensitive ordered by `+
    `(default: "${SORT_OPTIONS_DEFAULT}"), ` +
    `valid values: ${SORT_OPTIONS.join(', ')}`,
    (value) => {
      if (SORT_OPTIONS.indexOf(value) === -1) {
        console.error(
          'Invalid value for sort option: "%s", valid values are: ',
          value,
          SORT_OPTIONS.join(', ')
        );
        process.exit(2);
      }
      return value;
    },
    SORT_OPTIONS_DEFAULT // default sor
  )
  .option(
    '--search <query>',
    'optional search string which must be somewhere in the project’s name ' +
    '(case insensitive)'
  )
  .option(
    '--customer_id <id>',
    'optional id of a customer (use mite customer) to filter the projects by'
  )
  .option(
    '--customer <regexp>',
    'optional client-side filter for customer names, case-insensitive'
  )
  .option(
    '-a, --archived <true|false>',
    'When used will only show either archived users or not archived users',
    ((val) => {
      if (typeof val !== 'string') {
        return val;
      }
      return ['true', 'yes', 'ja', 'ok', '1'].indexOf(val.toLowerCase()) > -1;
    }),
    false // default archive argument
  )
  .option(
    '-f, --format <format>',
    'defines the output format, valid options are ' + DataOutput.FORMATS.join(', '),
    'table',
  )
  .parse(process.argv);

const opts = {
  limit: 10000,
  name: program.search,
  customer_id: program.customer_id
};

const mite = miteApi(config.get());

async.parallel([
  async.apply(mite.getProjects, opts),
  async.apply(mite.getArchivedProjects, opts)
], (err, results) => {

  if (err) {
    throw err;
  }
  // merge archived and not archived projects together in one array
  const allProjects = [].concat(results[0], results[1]);
  // proclaim an array of tabular data by mapping and filtering the data
  const tableData = allProjects
    .map((e) => e.project)
    .filter((p) => {
      if (program.archived === null) {
        return true;
      }
      return program.archived === p.archived;
    })
    .filter((p) => {
      // filter by customer regexp, skip if no cli argument was given
      if (!program.customer) {
        return true;
      }
      const regexp = new RegExp(program.customer, 'i');
      return regexp.exec(p.customer_name) || regexp.exec(String(p.customer_id));
    })
    .sort((a, b) => {
      if (!program.sort) return 0;
      let sortByAttributeName = program.sort;
      if (sortByAttributeName === 'customer') {
        sortByAttributeName = 'customer_name';
      }
      if (sortByAttributeName === 'rate') {
        sortByAttributeName = 'hourly_rate';
      }
      var val1 = String(a[sortByAttributeName]).toLowerCase();
      var val2 = String(b[sortByAttributeName]).toLowerCase();
      if (val1 > val2) {
        return 1;
      } else if (val1 < val2) {
        return -1;
      } else {
        return 0;
      }
    })
    .map((data) => {
      let budget = formater.budget(data.budget_type, data.budget);
      if (!data.budget) {
        budget = '-'
      }
      let rate = formater.budget(BUDGET_TYPE.CENTS, data.hourly_rate);
      if (!data.hourly_rate) {
        rate = '-';
      }
      let customer = data.customer_name + ' (' + data.customer_id + ')';
      if (!data.customer_id) {
        customer = '-';
      }
      return [
        data.id,
        data.name,
        customer,
        budget,
        rate,
        data.note.replace(/\r?\n/g, ' '),
      ].map((v) => {
        if (data.archived) {
          return chalk.grey(v);
        }
        return v;
      })
    });
  tableData.unshift([
    'id',
    'name',
    'customer',
    'budget',
    'rate',
    'note',
  ].map((v) => chalk.bold(v)));
  const columns = {
    1: {
      wrapWord: true,
    },
    3: {
      alignment: 'right',
    },
    4: {
      alignment: 'right',
    },
    5: {
      width: 50,
      wrapWord: true,
    }
  };

  console.log(DataOutput.formatData(tableData, program.format, columns));
});
<|endoftext|>