<commit_before>import cytoscape from 'cytoscape';
import dagre from 'cytoscape-dagre';
import React from 'react';
import ReactDOM from 'react-dom';

cytoscape.use(dagre);

//TODO: DRY 'recent-epics' related access between graph.js & index.js
function pushRelatedEpic(epic) {
    if (typeof(Storage) === "undefined") {
        return
    }
    var epics = [];

    const rawRecentEpics = localStorage.getItem('recent-epics');
    if (rawRecentEpics) {
        try {
            var parsed = JSON.parse(rawRecentEpics);
            if (parsed && parsed.constructor === Array) {
                epics = parsed;
            }
        } catch (err) {
            console.log('failed to parse recent-epics from local storage: ' + err);
        }
    }
    for (var i = 0; i < epics.length; i++) {
        if (epics[i].key === epic.key) {
            epics.splice(i, 1);
        }
    }
    epics.unshift(epic);
    if (epics.length > 10) {
        epics.pop();
    }
    localStorage.setItem('recent-epics', JSON.stringify(epics));
}

function categorizeStatus(s) {
    if (s == 'Backlog' || s == 'Ready for Dev') {
        return 'Backlog';
    }
    if (s == 'In Progress' || s == 'In QA on feature branch' || s == 'In Code Review' || s == 'Resolved, on staging') {
        return 'In Progress';
    }
    return s;
}

function statusToRGB(s) {
    const categorized = categorizeStatus(s);
    if (categorized == 'Backlog') {
        return '#ffffff';
    }
    if (categorized == 'In Progress') {
        return '#35e82c';
    }
    if (categorized == 'Closed') {
        return '#959595';
    }
    return '#000000';
}

class Popup extends React.Component {
    render() {
        if (this.props.selectedEpic == null) {
            return

        }

        //TODO: a hack until offsetHeight can be figured out
        const yOffset = 45;

        const style = {
            left: this.props.selectedEpic.popupPosition.x + 'px',
            top: (this.props.selectedEpic.popupPosition.y + yOffset) + 'px',
        }

        const epic = this.props.selectedEpic.epic;

        var className = 'popup';
        if (epic.flagged) {
            className = className + ' flagged';
        }

        return (

{epic.summary}

              <PopupIcon alt={'Type: ' + epic.type} imageURL={epic.typeImageURL} />
              <PopupIcon alt={'Priority: ' + epic.priority} imageURL={epic.priorityImageURL} />
              {epic.flagged ? '⚑' : ''}
              <PopupEstimate estimate={epic.estimate} />
              <PopupKey epicKey={epic.key} />
              <PopupAssignee assignee={epic.assignee} assigneeImageURL={epic.assigneeImageURL} />

                  {epic.status}
                  <PopupSprint sprints={epic.sprints} />

              <PopupLabels labels={epic.labels} />

            <PopupStatus status={epic.status} />

        )
    }
}

class PopupSprint extends React.Component {
    render() {
        const sprints = this.props.sprints;
        if (sprints.length == 0) {
            return null;
        }
        return  {sprints[sprints.length-1].name};
    }
}

class PopupIcon extends React.Component {
    render() {
        return (

        )
    }
}

class PopupAssignee extends React.Component {
    render() {
        if (this.props.assignee === '') {
            return
        }

        const alt = 'Assignee: ' + this.props.assignee;
        return (

        )
    }
}

class PopupKey extends React.Component {
    render() {
        const url = '/epics/' + this.props.epicKey + '/details';

        return (

          {this.props.epicKey}

        );
    }
}

class PopupEstimate extends React.Component {
    render() {
        return (
            {this.props.estimate === 0 ? "-" : this.props.estimate}
        );
    }
}

class PopupStatus extends React.Component {
    render() {
        const style = {
            backgroundColor: statusToRGB(this.props.status),
        }
        return

    }
}

class PopupLabels extends React.Component {
    render() {
        var labelListItems = [];
        for (var i = 0; i < this.props.labels.length; i++) {
            labelListItems.push(
{this.props.labels[i]}
);
        }
        return (

{labelListItems}

        );
    }
}

class GraphApp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            epic: {},
        };
    }

    render() {
        if (this.state.error) {
            return
Error: failed to fetch the epic

        } else if (!this.state.isLoaded) {
            return
Loading...

        } else {
            return (

					<Graph epic={this.state.epic} toggleMenu={this.props.toggleMenu} />
					<EpicStats initialEstimate={this.props.initialEstimate} epic={this.state.epic} />

            );
        }
    }

    componentDidMount() {
        const epicKey = this.props.epicKey;
        console.log('loading ' + epicKey);

        fetch("/api/epics/" + epicKey)
            .then(res => {
                if (!res.ok) {
                    throw new Error('not ok');
                }
                return res.json();
            }).then(result => {
                this.setState({
                    isLoaded: true,
                    epic: result,
                });
                console.log('loaded ' + epicKey);
            }).catch(() => {
                console.log('failed to load ' + epicKey);
                this.setState({
                    isLoaded: false,
                    error: true,
                });
            });
    }
}

class Menu extends React.Component {
    render() {
        return (

      ☰
		<input type="checkbox" id="menu-toggle" checked={this.props.showMenu} onChange={() => this.props.toggleMenu()} />

			Related epics

            <RelatedEpics epicKey={this.props.epicKey} />

        )
    }
}

class RelatedEpics extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            epics: [],
        };
    }

    render() {
        if (this.state.error) {
            return
Error: failed to fetch related epics
;
        } else if (!this.state.isLoaded) {
            return
Loading...
;
        } else {
            const epics = this.state.epics;
            if (epics.length == 0) {
                return
none!
;
            }

            var anchors = [];
            for (var i = 0; i < epics.length; i++) {
                const url = '/epics/' + epics[i].key;
                anchors.push(

                    {epics[i].key} - {epics[i].summary}

                );
            }

            return
{anchors}
;
        }
    }

    componentDidMount() {
        const epicKey = this.props.epicKey

        console.log('loading related epics for ' + epicKey);
        fetch("/api/epics/" + epicKey + "/related")
            .then(res => {
                if (!res.ok) {
                    throw new Error('not ok');
                }
                return res.json();
            })
            .then(result => {
                this.setState({
                    isLoaded: true,
                    epics: result,
                });
                console.log('loaded related epics for ' + epicKey);
            }).catch(
                () => {
                    console.log('failed to load related epics for ' + epicKey);
                    this.setState({
                        isLoaded: false,
                        error: true,
                        epics: [],
                    });
                });
    }
}

class Graph extends React.Component {
    constructor(props) {
        super(props);
        this.myRef = React.createRef();
        this.state = {
            selectedEpic: null,
        };
    }

    render() {
        return (

          <Popup selectedEpic={this.state.selectedEpic} />

        );
    }

    componentDidMount() {
        this.renderGraph(this.props.epic);
    }

    renderGraph(data) {
        const root = this.myRef.current;
        var issues = data.issues.map(function(elem) {
            return {
                data: Object.assign({
                    id: elem.key
                }, elem)
            }
        });

        var issueEdges = [];
        for (var i = 0; i < issues.length; i++) {
            var blockingIssue = issues[i].data.id;
            var blockedIssues = data.graph[blockingIssue];
            for (var j = 0; j < blockedIssues.length; j++) {
                var id = blockingIssue + '_blocks_' + blockedIssues[j];
                issueEdges.push({
                    data: {
                        id: id,
                        source: blockingIssue,
                        target: blockedIssues[j]
                    }
                });
            }
        }

        var cy = cytoscape({
            container: root,

            boxSelectionEnabled: false,
            autounselectify: true,

            layout: {
                name: 'dagre',
                directed: true
            },

            style: [{
                    selector: 'node',
                    style: {
                        'content': 'data(id)',
                        'text-opacity': 0.8,
                        'color': '#000000',
                        'font-size': 18,
                        'font-weight': 'bold',
                        'background-color': function(ele) {
                            return statusToRGB(ele.data('status'))
                        },
                        'border-width': function(ele) {
                            const sprints = ele.data('sprints');
                            if (sprints) {
                                for (var i = 0; i < sprints.length; i++) {
                                    if (sprints[i].state == 'ACTIVE' || sprints[i].state == 'CLOSED') {
                                        return 3;
                                    }
                                }
                            }
                            return 1;
                        },
                        'border-color': '#000000'
                    }
                },

                {
                    selector: 'edge',
                    style: {
                        'curve-style': 'bezier',
                        'width': 4,
                        'target-arrow-shape': 'triangle',
                        'line-color': '#9dbaea',
                        'target-arrow-color': '#9dbaea'
                    }
                }
            ],

            elements: {
                nodes: issues,
                edges: issueEdges,
            },
        });

        cy.on('tap', (evt) => {
            if (evt.target === cy) {
                this.setState({
                    selectedEpic: null,
                });
                this.props.toggleMenu(false);
            }
        });

        cy.on('tap', 'node', (evt) => {
            const epic = evt.target.data();
            const position = evt.renderedPosition;
            this.setState({
                selectedEpic: {
                    epic: epic,
                    popupPosition: position,
                }
            });
        });

        cy.on('mouseover', 'node', function(evt) {
            document.body.style.cursor = 'pointer';
        });

        cy.on('mouseout', 'node', function() {
            document.body.style.cursor = 'default';
        });
    }
}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            showMenu: false,
        }
    }

    render() {
        const issueURL = "https://" + this.props.jiraHost + "/browse/" + this.props.epicKey;
        const issueLabel = this.props.epicKey + " - " + this.props.issueSummary;
        return (

                    ⌂
					<Menu epicKey={this.props.epicKey} toggleMenu={(show) => this.toggleMenu(show)} showMenu={this.state.showMenu} />
					{issueLabel}

				<GraphApp epicKey={this.props.epicKey}
					initialEstimate={this.props.initialEstimate}
					toggleMenu={(show) => this.toggleMenu(show)} />

        )
    }

    toggleMenu(show) {
        if (show === undefined) {
            this.setState({
                showMenu: !this.state.showMenu,
            });
            return;
        }
        this.setState({
            showMenu: show,
        });
    }
}

class EpicStats extends React.Component {
    render() {
        var byStatus = this.getBreakdownByStatus();
        var rows = [];
        if (this.props.initialEstimate != 0) {
            rows.push(
Initial Estimate	{this.props.initialEstimate}
);
        }

        var totalPoints = 0;
        var statusOrder = ['Backlog', 'In Progress', 'Closed'];
        for (var i = 0; i < statusOrder.length; i++) {
            var status = statusOrder[i];
            if (byStatus[status]) {
                rows.push(
{status}	{byStatus[status]}
);
                totalPoints += byStatus[status];
            }
        }

        if (totalPoints > 0) {
            rows.push(
Total	{totalPoints}
);
            const closedPoints = byStatus['Closed'];
            const closedPercent = Math.round(closedPoints / totalPoints * 100);
            rows.push(
{closedPoints}/{totalPoints} Closed ({closedPercent}%)
)
        }

        return (

Point Breakdown

{rows}

        );
    }

    getBreakdownByStatus() {
        var epic = this.props.epic;
        var result = {};
        for (var i = 0; i < epic.issues.length; i++) {
            var status = categorizeStatus(epic.issues[i].status);
            if (result[status]) {
                result[status] += epic.issues[i].estimate;
                continue;
            }
            result[status] = epic.issues[i].estimate;
        }
        return result;
    }
}

var root = document.getElementById('root');
ReactDOM.render(<App epicKey={root.dataset.issueKey}
		issueSummary={root.dataset.issueSummary}
		initialEstimate={root.dataset.issueInitialEstimate}
		jiraHost={root.dataset.jiraHost} />, root);

var epic = {
    key: root.dataset.issueKey,
    summary: root.dataset.issueSummary
};
pushRelatedEpic(epic);<commit_msg>Fix 'NaN' in epic stats if no tickets are closed<commit_after>import cytoscape from 'cytoscape';
import dagre from 'cytoscape-dagre';
import React from 'react';
import ReactDOM from 'react-dom';

cytoscape.use(dagre);

//TODO: DRY 'recent-epics' related access between graph.js & index.js
function pushRelatedEpic(epic) {
    if (typeof(Storage) === "undefined") {
        return
    }
    var epics = [];

    const rawRecentEpics = localStorage.getItem('recent-epics');
    if (rawRecentEpics) {
        try {
            var parsed = JSON.parse(rawRecentEpics);
            if (parsed && parsed.constructor === Array) {
                epics = parsed;
            }
        } catch (err) {
            console.log('failed to parse recent-epics from local storage: ' + err);
        }
    }
    for (var i = 0; i < epics.length; i++) {
        if (epics[i].key === epic.key) {
            epics.splice(i, 1);
        }
    }
    epics.unshift(epic);
    if (epics.length > 10) {
        epics.pop();
    }
    localStorage.setItem('recent-epics', JSON.stringify(epics));
}

function categorizeStatus(s) {
    if (s == 'Backlog' || s == 'Ready for Dev') {
        return 'Backlog';
    }
    if (s == 'In Progress' || s == 'In QA on feature branch' || s == 'In Code Review' || s == 'Resolved, on staging') {
        return 'In Progress';
    }
    return s;
}

function statusToRGB(s) {
    const categorized = categorizeStatus(s);
    if (categorized == 'Backlog') {
        return '#ffffff';
    }
    if (categorized == 'In Progress') {
        return '#35e82c';
    }
    if (categorized == 'Closed') {
        return '#959595';
    }
    return '#000000';
}

class Popup extends React.Component {
    render() {
        if (this.props.selectedEpic == null) {
            return

        }

        //TODO: a hack until offsetHeight can be figured out
        const yOffset = 45;

        const style = {
            left: this.props.selectedEpic.popupPosition.x + 'px',
            top: (this.props.selectedEpic.popupPosition.y + yOffset) + 'px',
        }

        const epic = this.props.selectedEpic.epic;

        var className = 'popup';
        if (epic.flagged) {
            className = className + ' flagged';
        }

        return (

{epic.summary}

              <PopupIcon alt={'Type: ' + epic.type} imageURL={epic.typeImageURL} />
              <PopupIcon alt={'Priority: ' + epic.priority} imageURL={epic.priorityImageURL} />
              {epic.flagged ? '⚑' : ''}
              <PopupEstimate estimate={epic.estimate} />
              <PopupKey epicKey={epic.key} />
              <PopupAssignee assignee={epic.assignee} assigneeImageURL={epic.assigneeImageURL} />

                  {epic.status}
                  <PopupSprint sprints={epic.sprints} />

              <PopupLabels labels={epic.labels} />

            <PopupStatus status={epic.status} />

        )
    }
}

class PopupSprint extends React.Component {
    render() {
        const sprints = this.props.sprints;
        if (sprints.length == 0) {
            return null;
        }
        return  {sprints[sprints.length-1].name};
    }
}

class PopupIcon extends React.Component {
    render() {
        return (

        )
    }
}

class PopupAssignee extends React.Component {
    render() {
        if (this.props.assignee === '') {
            return
        }

        const alt = 'Assignee: ' + this.props.assignee;
        return (

        )
    }
}

class PopupKey extends React.Component {
    render() {
        const url = '/epics/' + this.props.epicKey + '/details';

        return (

          {this.props.epicKey}

        );
    }
}

class PopupEstimate extends React.Component {
    render() {
        return (
            {this.props.estimate === 0 ? "-" : this.props.estimate}
        );
    }
}

class PopupStatus extends React.Component {
    render() {
        const style = {
            backgroundColor: statusToRGB(this.props.status),
        }
        return

    }
}

class PopupLabels extends React.Component {
    render() {
        var labelListItems = [];
        for (var i = 0; i < this.props.labels.length; i++) {
            labelListItems.push(
{this.props.labels[i]}
);
        }
        return (

{labelListItems}

        );
    }
}

class GraphApp extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            epic: {},
        };
    }

    render() {
        if (this.state.error) {
            return
Error: failed to fetch the epic

        } else if (!this.state.isLoaded) {
            return
Loading...

        } else {
            return (

					<Graph epic={this.state.epic} toggleMenu={this.props.toggleMenu} />
					<EpicStats initialEstimate={this.props.initialEstimate} epic={this.state.epic} />

            );
        }
    }

    componentDidMount() {
        const epicKey = this.props.epicKey;
        console.log('loading ' + epicKey);

        fetch("/api/epics/" + epicKey)
            .then(res => {
                if (!res.ok) {
                    throw new Error('not ok');
                }
                return res.json();
            }).then(result => {
                this.setState({
                    isLoaded: true,
                    epic: result,
                });
                console.log('loaded ' + epicKey);
            }).catch(() => {
                console.log('failed to load ' + epicKey);
                this.setState({
                    isLoaded: false,
                    error: true,
                });
            });
    }
}

class Menu extends React.Component {
    render() {
        return (

      ☰
		<input type="checkbox" id="menu-toggle" checked={this.props.showMenu} onChange={() => this.props.toggleMenu()} />

			Related epics

            <RelatedEpics epicKey={this.props.epicKey} />

        )
    }
}

class RelatedEpics extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            epics: [],
        };
    }

    render() {
        if (this.state.error) {
            return
Error: failed to fetch related epics
;
        } else if (!this.state.isLoaded) {
            return
Loading...
;
        } else {
            const epics = this.state.epics;
            if (epics.length == 0) {
                return
none!
;
            }

            var anchors = [];
            for (var i = 0; i < epics.length; i++) {
                const url = '/epics/' + epics[i].key;
                anchors.push(

                    {epics[i].key} - {epics[i].summary}

                );
            }

            return
{anchors}
;
        }
    }

    componentDidMount() {
        const epicKey = this.props.epicKey

        console.log('loading related epics for ' + epicKey);
        fetch("/api/epics/" + epicKey + "/related")
            .then(res => {
                if (!res.ok) {
                    throw new Error('not ok');
                }
                return res.json();
            })
            .then(result => {
                this.setState({
                    isLoaded: true,
                    epics: result,
                });
                console.log('loaded related epics for ' + epicKey);
            }).catch(
                () => {
                    console.log('failed to load related epics for ' + epicKey);
                    this.setState({
                        isLoaded: false,
                        error: true,
                        epics: [],
                    });
                });
    }
}

class Graph extends React.Component {
    constructor(props) {
        super(props);
        this.myRef = React.createRef();
        this.state = {
            selectedEpic: null,
        };
    }

    render() {
        return (

          <Popup selectedEpic={this.state.selectedEpic} />

        );
    }

    componentDidMount() {
        this.renderGraph(this.props.epic);
    }

    renderGraph(data) {
        const root = this.myRef.current;
        var issues = data.issues.map(function(elem) {
            return {
                data: Object.assign({
                    id: elem.key
                }, elem)
            }
        });

        var issueEdges = [];
        for (var i = 0; i < issues.length; i++) {
            var blockingIssue = issues[i].data.id;
            var blockedIssues = data.graph[blockingIssue];
            for (var j = 0; j < blockedIssues.length; j++) {
                var id = blockingIssue + '_blocks_' + blockedIssues[j];
                issueEdges.push({
                    data: {
                        id: id,
                        source: blockingIssue,
                        target: blockedIssues[j]
                    }
                });
            }
        }

        var cy = cytoscape({
            container: root,

            boxSelectionEnabled: false,
            autounselectify: true,

            layout: {
                name: 'dagre',
                directed: true
            },

            style: [{
                    selector: 'node',
                    style: {
                        'content': 'data(id)',
                        'text-opacity': 0.8,
                        'color': '#000000',
                        'font-size': 18,
                        'font-weight': 'bold',
                        'background-color': function(ele) {
                            return statusToRGB(ele.data('status'))
                        },
                        'border-width': function(ele) {
                            const sprints = ele.data('sprints');
                            if (sprints) {
                                for (var i = 0; i < sprints.length; i++) {
                                    if (sprints[i].state == 'ACTIVE' || sprints[i].state == 'CLOSED') {
                                        return 3;
                                    }
                                }
                            }
                            return 1;
                        },
                        'border-color': '#000000'
                    }
                },

                {
                    selector: 'edge',
                    style: {
                        'curve-style': 'bezier',
                        'width': 4,
                        'target-arrow-shape': 'triangle',
                        'line-color': '#9dbaea',
                        'target-arrow-color': '#9dbaea'
                    }
                }
            ],

            elements: {
                nodes: issues,
                edges: issueEdges,
            },
        });

        cy.on('tap', (evt) => {
            if (evt.target === cy) {
                this.setState({
                    selectedEpic: null,
                });
                this.props.toggleMenu(false);
            }
        });

        cy.on('tap', 'node', (evt) => {
            const epic = evt.target.data();
            const position = evt.renderedPosition;
            this.setState({
                selectedEpic: {
                    epic: epic,
                    popupPosition: position,
                }
            });
        });

        cy.on('mouseover', 'node', function(evt) {
            document.body.style.cursor = 'pointer';
        });

        cy.on('mouseout', 'node', function() {
            document.body.style.cursor = 'default';
        });
    }
}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            showMenu: false,
        }
    }

    render() {
        const issueURL = "https://" + this.props.jiraHost + "/browse/" + this.props.epicKey;
        const issueLabel = this.props.epicKey + " - " + this.props.issueSummary;
        return (

                    ⌂
					<Menu epicKey={this.props.epicKey} toggleMenu={(show) => this.toggleMenu(show)} showMenu={this.state.showMenu} />
					{issueLabel}

				<GraphApp epicKey={this.props.epicKey}
					initialEstimate={this.props.initialEstimate}
					toggleMenu={(show) => this.toggleMenu(show)} />

        )
    }

    toggleMenu(show) {
        if (show === undefined) {
            this.setState({
                showMenu: !this.state.showMenu,
            });
            return;
        }
        this.setState({
            showMenu: show,
        });
    }
}

class EpicStats extends React.Component {
    render() {
        var byStatus = this.getBreakdownByStatus();
        var rows = [];
        if (this.props.initialEstimate != 0) {
            rows.push(
Initial Estimate	{this.props.initialEstimate}
);
        }

        var totalPoints = 0;
        var statusOrder = ['Backlog', 'In Progress', 'Closed'];
        for (var i = 0; i < statusOrder.length; i++) {
            var status = statusOrder[i];
            if (byStatus[status]) {
                rows.push(
{status}	{byStatus[status]}
);
                totalPoints += byStatus[status];
            }
        }

        if (totalPoints > 0) {
            rows.push(
Total	{totalPoints}
);
            var closedPoints = byStatus['Closed'] ? byStatus['Closed'] : 0;
            const closedPercent = Math.round(closedPoints / totalPoints * 100);
            rows.push(
{closedPoints}/{totalPoints} Closed ({closedPercent}%)
)
        }

        return (

Point Breakdown

{rows}

        );
    }

    getBreakdownByStatus() {
        var epic = this.props.epic;
        var result = {};
        for (var i = 0; i < epic.issues.length; i++) {
            var status = categorizeStatus(epic.issues[i].status);
            if (result[status]) {
                result[status] += epic.issues[i].estimate;
                continue;
            }
            result[status] = epic.issues[i].estimate;
        }
        return result;
    }
}

var root = document.getElementById('root');
ReactDOM.render(<App epicKey={root.dataset.issueKey}
		issueSummary={root.dataset.issueSummary}
		initialEstimate={root.dataset.issueInitialEstimate}
		jiraHost={root.dataset.jiraHost} />, root);

var epic = {
    key: root.dataset.issueKey,
    summary: root.dataset.issueSummary
};
pushRelatedEpic(epic);<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 airbug inc. http://airbug.com
 *
 * buganno may be freely distributed under the MIT license.
 */

//-------------------------------------------------------------------------------
// Requires
//-------------------------------------------------------------------------------

var buildbug            = require('buildbug');

//-------------------------------------------------------------------------------
// Simplify References
//-------------------------------------------------------------------------------

var buildProject        = buildbug.buildProject;
var buildProperties     = buildbug.buildProperties;
var buildScript         = buildbug.buildScript;
var buildTarget         = buildbug.buildTarget;
var enableModule        = buildbug.enableModule;
var parallel            = buildbug.parallel;
var series              = buildbug.series;
var targetTask          = buildbug.targetTask;

//-------------------------------------------------------------------------------
// Enable Modules
//-------------------------------------------------------------------------------

var aws                 = enableModule("aws");
var bugpack             = enableModule('bugpack');
var bugunit             = enableModule('bugunit');
var core                = enableModule('core');
var lintbug             = enableModule("lintbug");
var nodejs              = enableModule('nodejs');

//-------------------------------------------------------------------------------
// Values
//-------------------------------------------------------------------------------

var name                = "buganno";
var version             = "0.1.5";
var dependencies        = {
    bugpack: "0.1.14"
};

//-------------------------------------------------------------------------------
// BuildProperties
//-------------------------------------------------------------------------------

buildProperties({
    name: name,
    version: version
});

buildProperties({
    node: {
        packageJson: {
            name: "{name}}",
            version: "{{version}}",
            description: "Library for loading and parsing annotations from JavaScript files.",
            main: "./scripts/buganno-node.js",
            dependencies: dependencies,
            author: "Brian Neisler <brian@airbug.com>",
            repository: {
                type: "git",
                url: "https://github.com/airbug/buganno.git"
            },
            bugs: {
                url: "https://github.com/airbug/buganno/issues"
            },
            licenses: [
                {
                    type : "MIT",
                    url : "https://raw.githubusercontent.com/airbug/buganno/master/LICENSE"
                }
            ]
        },
        sourcePaths: [
            "../bugcore/libraries/bugcore/js/src",
            "../bugfs/libraries/bugfs/js/src",
            "./libraries/buganno/js/src"
        ],
        scriptPaths: [
            "./libraries/buganno/js/scripts",
            "./projects/buganno-node/js/scripts"
        ],
        readmePath: "./README.md",
        unitTest: {
            packageJson: {
                name: "{{name}}-test",
                version: "{{version}}",
                main: "./scripts/buganno-node.js",
                private: true,
                dependencies: dependencies,
                scripts: {
                    test: "node ./test/scripts/bugunit-run.js"
                }
            },
            sourcePaths: [
                "../buganno/libraries/buganno/js/src",
                "../bugdouble/libraries/bugdouble/js/src",
                "../bugmeta/libraries/bugmeta/js/src",
                "../bugunit/libraries/bugunit/js/src",
                "../bugyarn/libraries/bugyarn/js/src"
            ],
            scriptPaths: [
                "../buganno/libraries/buganno/js/scripts",
                "../bugunit/libraries/bugunit/js/scripts"
            ],
            testPaths: [
                "../bugcore/libraries/bugcore/js/test",
                "../bugfs/libraries/bugfs/js/test",
                "./projects/buganno/js/test"
            ]
        }
    },
    lint: {
        targetPaths: [
            "."
        ],
        ignorePatterns: [
            ".*\\.buildbug$",
            ".*\\.bugunit$",
            ".*\\.git$",
            ".*node_modules$",
            ".*external$"
        ]
    }
});

//-------------------------------------------------------------------------------
// BuildTargets
//-------------------------------------------------------------------------------

// Clean BuildTarget
//-------------------------------------------------------------------------------

buildTarget('clean').buildFlow(
    targetTask('clean')
);

// Local BuildTarget
//-------------------------------------------------------------------------------

buildTarget('local').buildFlow(
    series([
        targetTask('clean'),
        targetTask('lint', {
            properties: {
                targetPaths: buildProject.getProperty("lint.targetPaths"),
                ignores: buildProject.getProperty("lint.ignorePatterns"),
                lintTasks: [
                    "cleanupExtraSpacingAtEndOfLines",
                    "ensureNewLineEnding",
                    "indentEqualSignsForPreClassVars",
                    "orderBugpackRequires",
                    "orderRequireAnnotations",
                    "updateCopyright"
                ]
            }
        }),
        series([
            targetTask('createNodePackage', {
                properties: {
                    packageJson: buildProject.getProperty("node.packageJson"),
                    packagePaths: {
                        ".": [buildProject.getProperty("node.readmePath")],
                        "./lib": buildProject.getProperty("node.sourcePaths"),
                        "./scripts": buildProject.getProperty("node.scriptPaths"),
                        "./test": buildProject.getProperty("node.unitTest.testPaths"),
                        "./test/lib": buildProject.getProperty("node.unitTest.sourcePaths"),
                        "./test/scripts": buildProject.getProperty("node.unitTest.scriptPaths")
                    }
                }
            }),
            targetTask('generateBugPackRegistry', {
                init: function(task, buildProject, properties) {
                    var nodePackage = nodejs.findNodePackage(
                        buildProject.getProperty("node.packageJson.name"),
                        buildProject.getProperty("node.packageJson.version")
                    );
                    task.updateProperties({
                        sourceRoot: nodePackage.getBuildPath()
                    });
                }
            }),
            targetTask('packNodePackage', {
                properties: {
                    packageName: "{{node.packageJson.name}}",
                    packageVersion: "{{node.packageJson.version}}"
                }
            }),
            targetTask('startNodeModuleTests', {
                init: function(task, buildProject, properties) {
                    var packedNodePackage = nodejs.findPackedNodePackage(
                        buildProject.getProperty("node.packageJson.name"),
                        buildProject.getProperty("node.packageJson.version")
                    );
                    task.updateProperties({
                        modulePath: packedNodePackage.getFilePath()
                        //checkCoverage: true
                    });
                }
            }),
            targetTask("s3PutFile", {
                init: function(task, buildProject, properties) {
                    var packedNodePackage = nodejs.findPackedNodePackage(buildProject.getProperty("node.packageJson.name"),
                        buildProject.getProperty("node.packageJson.version"));
                    task.updateProperties({
                        file: packedNodePackage.getFilePath(),
                        options: {
                            acl: 'public-read',
                            encrypt: true
                        }
                    });
                },
                properties: {
                    bucket: "{{local-bucket}}"
                }
            })
        ])
    ])
).makeDefault();

// Prod BuildTarget
//-------------------------------------------------------------------------------

buildTarget('prod').buildFlow(
    series([
        targetTask('clean'),
        targetTask('lint', {
            properties: {
                targetPaths: buildProject.getProperty("lint.targetPaths"),
                ignores: buildProject.getProperty("lint.ignorePatterns"),
                lintTasks: [
                    "cleanupExtraSpacingAtEndOfLines",
                    "ensureNewLineEnding",
                    "indentEqualSignsForPreClassVars",
                    "orderBugpackRequires",
                    "orderRequireAnnotations",
                    "updateCopyright"
                ]
            }
        }),
        parallel([

            //Create test node buganno package

            series([
                targetTask('createNodePackage', {
                    properties: {
                        packageJson: buildProject.getProperty("node.unitTest.packageJson"),
                        packagePaths: {
                            "./lib": buildProject.getProperty("node.sourcePaths"),
                            "./scripts": buildProject.getProperty("node.scriptPaths"),
                            "./test": buildProject.getProperty("node.unitTest.testPaths"),
                            "./test/lib": buildProject.getProperty("node.unitTest.sourcePaths"),
                            "./test/scripts": buildProject.getProperty("node.unitTest.scriptPaths")
                        }
                    }
                }),
                targetTask('generateBugPackRegistry', {
                    init: function(task, buildProject, properties) {
                        var nodePackage = nodejs.findNodePackage(
                            buildProject.getProperty("node.unitTest.packageJson.name"),
                            buildProject.getProperty("node.unitTest.packageJson.version")
                        );
                        task.updateProperties({
                            sourceRoot: nodePackage.getBuildPath()
                        });
                    }
                }),
                targetTask('packNodePackage', {
                    properties: {
                        packageName: "{{node.unitTest.packageJson.name}}",
                        packageVersion: "{{node.unitTest.packageJson.version}}"
                    }
                }),
                targetTask('startNodeModuleTests', {
                    init: function(task, buildProject, properties) {
                        var packedNodePackage = nodejs.findPackedNodePackage(
                            buildProject.getProperty("node.unitTest.packageJson.name"),
                            buildProject.getProperty("node.unitTest.packageJson.version")
                        );
                        task.updateProperties({
                            modulePath: packedNodePackage.getFilePath(),
                            checkCoverage: true
                        });
                    }
                })
            ]),

            // Create production node buganno package

            series([
                targetTask('createNodePackage', {
                    properties: {
                        packageJson: buildProject.getProperty("node.packageJson"),
                        packagePaths: {
                            ".": [buildProject.getProperty("node.readmePath")],
                            "./lib": buildProject.getProperty("node.sourcePaths"),
                            "./scripts": buildProject.getProperty("node.scriptPaths")
                        }
                    }
                }),
                targetTask('generateBugPackRegistry', {
                    init: function(task, buildProject, properties) {
                        var nodePackage = nodejs.findNodePackage(
                            buildProject.getProperty("node.packageJson.name"),
                            buildProject.getProperty("node.packageJson.version")
                        );
                        task.updateProperties({
                            sourceRoot: nodePackage.getBuildPath()
                        });
                    }
                }),
                targetTask('packNodePackage', {
                    properties: {
                        packageName: "{{node.packageJson.name}}",
                        packageVersion: "{{node.packageJson.version}}"
                    }
                }),
                targetTask("s3PutFile", {
                    init: function(task, buildProject, properties) {
                        var packedNodePackage = nodejs.findPackedNodePackage(buildProject.getProperty("node.packageJson.name"),
                            buildProject.getProperty("node.packageJson.version"));
                        task.updateProperties({
                            file: packedNodePackage.getFilePath(),
                            options: {
                                acl: 'public-read',
                                encrypt: true
                            }
                        });
                    },
                    properties: {
                        bucket: "{{prod-deploy-bucket}}"
                    }
                }),
                targetTask('npmConfigSet', {
                    properties: {
                        config: buildProject.getProperty("npmConfig")
                    }
                }),
                targetTask('npmAddUser'),
                targetTask('publishNodePackage', {
                    properties: {
                        packageName: "{{node.packageJson.name}}",
                        packageVersion: "{{node.packageJson.version}}"
                    }
                })
            ])
        ])
    ])
);

//-------------------------------------------------------------------------------
// Build Scripts
//-------------------------------------------------------------------------------

buildScript({
    dependencies: [
        "bugcore",
        "bugflow",
        "bugfs"
    ],
    script: "./lintbug.js"
});
<commit_msg>Bump version to 0.1.6<commit_after>/*
 * Copyright (c) 2014 airbug inc. http://airbug.com
 *
 * buganno may be freely distributed under the MIT license.
 */

//-------------------------------------------------------------------------------
// Requires
//-------------------------------------------------------------------------------

var buildbug            = require('buildbug');

//-------------------------------------------------------------------------------
// Simplify References
//-------------------------------------------------------------------------------

var buildProject        = buildbug.buildProject;
var buildProperties     = buildbug.buildProperties;
var buildScript         = buildbug.buildScript;
var buildTarget         = buildbug.buildTarget;
var enableModule        = buildbug.enableModule;
var parallel            = buildbug.parallel;
var series              = buildbug.series;
var targetTask          = buildbug.targetTask;

//-------------------------------------------------------------------------------
// Enable Modules
//-------------------------------------------------------------------------------

var aws                 = enableModule("aws");
var bugpack             = enableModule('bugpack');
var bugunit             = enableModule('bugunit');
var core                = enableModule('core');
var lintbug             = enableModule("lintbug");
var nodejs              = enableModule('nodejs');

//-------------------------------------------------------------------------------
// Values
//-------------------------------------------------------------------------------

var name                = "buganno";
var version             = "0.1.6";
var dependencies        = {
    bugpack: "0.1.14"
};

//-------------------------------------------------------------------------------
// BuildProperties
//-------------------------------------------------------------------------------

buildProperties({
    name: name,
    version: version
});

buildProperties({
    node: {
        packageJson: {
            name: "{name}}",
            version: "{{version}}",
            description: "Library for loading and parsing annotations from JavaScript files.",
            main: "./scripts/buganno-node.js",
            dependencies: dependencies,
            author: "Brian Neisler <brian@airbug.com>",
            repository: {
                type: "git",
                url: "https://github.com/airbug/buganno.git"
            },
            bugs: {
                url: "https://github.com/airbug/buganno/issues"
            },
            licenses: [
                {
                    type : "MIT",
                    url : "https://raw.githubusercontent.com/airbug/buganno/master/LICENSE"
                }
            ]
        },
        sourcePaths: [
            "../bugcore/libraries/bugcore/js/src",
            "../bugfs/libraries/bugfs/js/src",
            "./libraries/buganno/js/src"
        ],
        scriptPaths: [
            "./libraries/buganno/js/scripts",
            "./projects/buganno-node/js/scripts"
        ],
        readmePath: "./README.md",
        unitTest: {
            packageJson: {
                name: "{{name}}-test",
                version: "{{version}}",
                main: "./scripts/buganno-node.js",
                private: true,
                dependencies: dependencies,
                scripts: {
                    test: "node ./test/scripts/bugunit-run.js"
                }
            },
            sourcePaths: [
                "../buganno/libraries/buganno/js/src",
                "../bugdouble/libraries/bugdouble/js/src",
                "../bugmeta/libraries/bugmeta/js/src",
                "../bugunit/libraries/bugunit/js/src",
                "../bugyarn/libraries/bugyarn/js/src"
            ],
            scriptPaths: [
                "../buganno/libraries/buganno/js/scripts",
                "../bugunit/libraries/bugunit/js/scripts"
            ],
            testPaths: [
                "../bugcore/libraries/bugcore/js/test",
                "../bugfs/libraries/bugfs/js/test",
                "./projects/buganno/js/test"
            ]
        }
    },
    lint: {
        targetPaths: [
            "."
        ],
        ignorePatterns: [
            ".*\\.buildbug$",
            ".*\\.bugunit$",
            ".*\\.git$",
            ".*node_modules$",
            ".*external$"
        ]
    }
});

//-------------------------------------------------------------------------------
// BuildTargets
//-------------------------------------------------------------------------------

// Clean BuildTarget
//-------------------------------------------------------------------------------

buildTarget('clean').buildFlow(
    targetTask('clean')
);

// Local BuildTarget
//-------------------------------------------------------------------------------

buildTarget('local').buildFlow(
    series([
        targetTask('clean'),
        targetTask('lint', {
            properties: {
                targetPaths: buildProject.getProperty("lint.targetPaths"),
                ignores: buildProject.getProperty("lint.ignorePatterns"),
                lintTasks: [
                    "cleanupExtraSpacingAtEndOfLines",
                    "ensureNewLineEnding",
                    "indentEqualSignsForPreClassVars",
                    "orderBugpackRequires",
                    "orderRequireAnnotations",
                    "updateCopyright"
                ]
            }
        }),
        series([
            targetTask('createNodePackage', {
                properties: {
                    packageJson: buildProject.getProperty("node.packageJson"),
                    packagePaths: {
                        ".": [buildProject.getProperty("node.readmePath")],
                        "./lib": buildProject.getProperty("node.sourcePaths"),
                        "./scripts": buildProject.getProperty("node.scriptPaths"),
                        "./test": buildProject.getProperty("node.unitTest.testPaths"),
                        "./test/lib": buildProject.getProperty("node.unitTest.sourcePaths"),
                        "./test/scripts": buildProject.getProperty("node.unitTest.scriptPaths")
                    }
                }
            }),
            targetTask('generateBugPackRegistry', {
                init: function(task, buildProject, properties) {
                    var nodePackage = nodejs.findNodePackage(
                        buildProject.getProperty("node.packageJson.name"),
                        buildProject.getProperty("node.packageJson.version")
                    );
                    task.updateProperties({
                        sourceRoot: nodePackage.getBuildPath()
                    });
                }
            }),
            targetTask('packNodePackage', {
                properties: {
                    packageName: "{{node.packageJson.name}}",
                    packageVersion: "{{node.packageJson.version}}"
                }
            }),
            targetTask('startNodeModuleTests', {
                init: function(task, buildProject, properties) {
                    var packedNodePackage = nodejs.findPackedNodePackage(
                        buildProject.getProperty("node.packageJson.name"),
                        buildProject.getProperty("node.packageJson.version")
                    );
                    task.updateProperties({
                        modulePath: packedNodePackage.getFilePath()
                        //checkCoverage: true
                    });
                }
            }),
            targetTask("s3PutFile", {
                init: function(task, buildProject, properties) {
                    var packedNodePackage = nodejs.findPackedNodePackage(buildProject.getProperty("node.packageJson.name"),
                        buildProject.getProperty("node.packageJson.version"));
                    task.updateProperties({
                        file: packedNodePackage.getFilePath(),
                        options: {
                            acl: 'public-read',
                            encrypt: true
                        }
                    });
                },
                properties: {
                    bucket: "{{local-bucket}}"
                }
            })
        ])
    ])
).makeDefault();

// Prod BuildTarget
//-------------------------------------------------------------------------------

buildTarget('prod').buildFlow(
    series([
        targetTask('clean'),
        targetTask('lint', {
            properties: {
                targetPaths: buildProject.getProperty("lint.targetPaths"),
                ignores: buildProject.getProperty("lint.ignorePatterns"),
                lintTasks: [
                    "cleanupExtraSpacingAtEndOfLines",
                    "ensureNewLineEnding",
                    "indentEqualSignsForPreClassVars",
                    "orderBugpackRequires",
                    "orderRequireAnnotations",
                    "updateCopyright"
                ]
            }
        }),
        parallel([

            //Create test node buganno package

            series([
                targetTask('createNodePackage', {
                    properties: {
                        packageJson: buildProject.getProperty("node.unitTest.packageJson"),
                        packagePaths: {
                            "./lib": buildProject.getProperty("node.sourcePaths"),
                            "./scripts": buildProject.getProperty("node.scriptPaths"),
                            "./test": buildProject.getProperty("node.unitTest.testPaths"),
                            "./test/lib": buildProject.getProperty("node.unitTest.sourcePaths"),
                            "./test/scripts": buildProject.getProperty("node.unitTest.scriptPaths")
                        }
                    }
                }),
                targetTask('generateBugPackRegistry', {
                    init: function(task, buildProject, properties) {
                        var nodePackage = nodejs.findNodePackage(
                            buildProject.getProperty("node.unitTest.packageJson.name"),
                            buildProject.getProperty("node.unitTest.packageJson.version")
                        );
                        task.updateProperties({
                            sourceRoot: nodePackage.getBuildPath()
                        });
                    }
                }),
                targetTask('packNodePackage', {
                    properties: {
                        packageName: "{{node.unitTest.packageJson.name}}",
                        packageVersion: "{{node.unitTest.packageJson.version}}"
                    }
                }),
                targetTask('startNodeModuleTests', {
                    init: function(task, buildProject, properties) {
                        var packedNodePackage = nodejs.findPackedNodePackage(
                            buildProject.getProperty("node.unitTest.packageJson.name"),
                            buildProject.getProperty("node.unitTest.packageJson.version")
                        );
                        task.updateProperties({
                            modulePath: packedNodePackage.getFilePath(),
                            checkCoverage: true
                        });
                    }
                })
            ]),

            // Create production node buganno package

            series([
                targetTask('createNodePackage', {
                    properties: {
                        packageJson: buildProject.getProperty("node.packageJson"),
                        packagePaths: {
                            ".": [buildProject.getProperty("node.readmePath")],
                            "./lib": buildProject.getProperty("node.sourcePaths"),
                            "./scripts": buildProject.getProperty("node.scriptPaths")
                        }
                    }
                }),
                targetTask('generateBugPackRegistry', {
                    init: function(task, buildProject, properties) {
                        var nodePackage = nodejs.findNodePackage(
                            buildProject.getProperty("node.packageJson.name"),
                            buildProject.getProperty("node.packageJson.version")
                        );
                        task.updateProperties({
                            sourceRoot: nodePackage.getBuildPath()
                        });
                    }
                }),
                targetTask('packNodePackage', {
                    properties: {
                        packageName: "{{node.packageJson.name}}",
                        packageVersion: "{{node.packageJson.version}}"
                    }
                }),
                targetTask("s3PutFile", {
                    init: function(task, buildProject, properties) {
                        var packedNodePackage = nodejs.findPackedNodePackage(buildProject.getProperty("node.packageJson.name"),
                            buildProject.getProperty("node.packageJson.version"));
                        task.updateProperties({
                            file: packedNodePackage.getFilePath(),
                            options: {
                                acl: 'public-read',
                                encrypt: true
                            }
                        });
                    },
                    properties: {
                        bucket: "{{prod-deploy-bucket}}"
                    }
                }),
                targetTask('npmConfigSet', {
                    properties: {
                        config: buildProject.getProperty("npmConfig")
                    }
                }),
                targetTask('npmAddUser'),
                targetTask('publishNodePackage', {
                    properties: {
                        packageName: "{{node.packageJson.name}}",
                        packageVersion: "{{node.packageJson.version}}"
                    }
                })
            ])
        ])
    ])
);

//-------------------------------------------------------------------------------
// Build Scripts
//-------------------------------------------------------------------------------

buildScript({
    dependencies: [
        "bugcore",
        "bugflow",
        "bugfs"
    ],
    script: "./lintbug.js"
});
<|endoftext|>


<commit_before>/*
	Copyright (c) 2010 Filip Moberg, (filip@mcsquare.se)

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/

/*

	Author:		Filip Moberg
	Name:		fQuery (SuckerPunch)
	Version:	1.0
	Version name:	SuckerPunch
	Released:	2011-07-01

*/

function fQuery() {

	var args = arguments;
	var m;

	// Argument handler

	if (args[0] && args[0].substr(0,1) == "@") {

		// If first argument is an fQuery node

		fQuery._node = new Array();
		m = args[0].split(" ");
		for (i=0; i < m.length; i++) {
			fQuery._node.push(m[i].replace("@", ""));
		}

	} else if(args[0] != undefined && jQuery && jQuery(args[0])[0] !== "") {

		// If first argument is a valid jQuery selector

		fQuery.$ = jQuery(args[0]);
	}

	if (typeof(fQuery._init) == "undefined") {

		// Declare internal functions

		fQuery._internals = {
			wrapper : function() {

				var selector = sel = fQuery.$;
			},

			parseFunction : function() {

				var string = arguments[0].toString();
				var offset = string.indexOf("{");
				var head = string.substr(0, offset);
				var args = head.substr(head.indexOf("(")).replace("(","").replace(")","").replace(/ /g,"").split(",");
				var body = string.substr(offset+1,string.length-offset-2);

				return {
					head : head,
					args : args,
					body : body
				};
			},

			mergeFunctions : function() {

				var p1 = fQuery._internals.parseFunction(arguments[0]);
				var p2 = fQuery._internals.parseFunction(arguments[1]);

				var body = p1.body + p2.body;
				var args;

				if (p1.args[0] !== "") {
					args = p1.args;

					if (p2.args[0] !== "") {
						args = args.concat(p2.args);
					}
				} else if (p2.args[0] !== "") {
					args = p2.args;
				}

				if (args) {
					return new Function(args, "{"+body+"}");
				} else {
					return new Function("{"+body+"}");
				}
			},

			count : function(o) {

				// Count number of child nodes in selected object

				var c = 0;

				for (var k in o) {
					if (o.hasOwnProperty(k)) {
						++c;
					}
				}

				return c;
			}
		};

		// Set default top node wrapper

		fQuery._wrapper = fQuery._internals.wrapper;

		// Declare and initialize core functions

		fQuery._init = {
			alias : function() {

				var arr, obj, key;

				// Create alias for selected node

				if (fQuery._node && fQuery._node[0]) {

					arr = fQuery._node[0] ? fQuery._node[0].split(".") : '';
					obj = fQuery();

					for (var i in arr) {
						key = arr[i];
						obj = obj[key];
					}

					window[arguments[0]] = obj;

				} else {

					for (i=0; i < arguments.length; i++) {
						window[arguments[i]] = fQuery;
					}
				}

				fQuery._node = new Array();
			},

			extend : function() {

				var arr, arg, copy, key, n, wrapper;

				// Declare wrapper function

				var applyWrapper = function() {

					var fetchWrapper = function(o) {

						var f = fQuery._internals.parseFunction(o.wrapper);
						var body;

						if (f.body.indexOf("[FUNCTION]") != "-1") {
							return f.body.replace("[FUNCTION]", o.body);
						} else {
							return f.body + o.body;
						}
					};

					var obj = arguments[0].object;
					var wrapper = arguments[0].wrapper;

					for (var a in obj) {
						if (typeof(obj[a]) == "object") {
							new applyWrapper({object: obj[a], wrapper: wrapper});
						}
						if (typeof(obj[a]) == "function") {

							var f = fQuery._internals.parseFunction(obj[a]);

							body = f.body;
							args = f.args;

							for (var i=wrapper.length-1; i>=0; i--) {
								body = fetchWrapper({body: body, wrapper: wrapper[i]});
							}

							obj[a] = new Function(args, "{"+body+"}");
						}
					}
				};

				// Extend argument object(s) and function(s) to the end of the node chain

				for (i=0; i < fQuery._node.length; i++) {

					arr = fQuery._node[i] ? fQuery._node[i].split(".") : '';
					copy = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;
					arg = arguments[0];
					wrapper = new Array();
					wrapper.push(fQuery._wrapper);
					n = 0;

					// Crawl to the last object of the chain

					for (var k in arr) {
						if (n == arr.length-1 && typeof(arg) == "function") {
							arg = new Object();
							arg[arr[n]] = arguments[0];
						} else {
							key = arr[k];

							if (!copy['function'][key]) {

								copy['function'][key] = {};
								copy['object'][key] = {};
							}
							if (typeof(copy['object'][key]._wrapper) != "undefined") {
								wrapper.push(copy['object'][key]._wrapper);
							}

							copy['function'] = copy['function'][key];
							copy['object'] = copy['object'][key];
						}

						n++;
					}

					// Apply node wrappers (if any) to node functions

					new applyWrapper({object: arg, wrapper: wrapper});

					// Apply new object(s) to the fQuery tree

					jQuery.extend(true, copy['function'], arg);
					jQuery.extend(true, copy['object'], arg);
				}

				// If the extend targets the top node (can only be applied with an object, else fQuery would be overridden)

				if (typeof(fQuery._node[0]) == "undefined" && typeof(arguments[0]) == "object") {

					copy = new Array();
					wrapper = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;
					arg = arguments[0];
					wrapper.push(fQuery._wrapper);

					// Apply node wrappers (if any) to node functions

					new applyWrapper({object: arg, wrapper: wrapper});

					jQuery.extend(true, copy['function'], arg);

					for (var o in arg) {
						copy['object'][o] = arg[o];
					}
				}

				// Reset the _node to an empty array

				fQuery._node = new Array();
			},

			wrap : function() {

				var arr, copy, key;
				var arg = arguments[0];

				// Create wrapper for selected node(s)

				for (i=0; i < fQuery._node.length; i++) {

					arr = fQuery._node[i] ? fQuery._node[i].split(".") : '';
					copy = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;

					for (var k in arr) {
						key = arr[k];

						if (!copy['function'][key]) {

							copy['function'][key] = {};
							copy['object'][key] = {};
						}

						copy['function'] = copy['function'][key];
						copy['object'] = copy['object'][key];
					}

					copy['function']._wrapper = arg;
					copy['object']._wrapper = arg;
				}

				// Create wrapper for top node (and merge with default top node wrapper)

				if (fQuery._node.length === 0) {
					copy = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;

					arg = fQuery._internals.mergeFunctions(fQuery._internals.wrapper, arg);

					copy['function']._wrapper = arg;
					copy['object']._wrapper = arg;
				}

				// Reset the _node to an empty array

				fQuery._node = new Array();
			},

			append : function(o) {

				// Faster than jQueries append, but lets you pass through css, bind and attribute objects to jQuery.

				fQuery.$.each(function() {

					var obj = document.createElement(o.element);
					this.appendChild(obj);

					if (o.css) {
						$(obj).css(o.css);
					}

					if (o.attributes) {
						$(obj).attr(o.attributes);
					}

					if (o.bind) {
						for (var k in o.bind) {
							$(obj).bind(k, o.bind[k]);
						}
					}
				});
			},

			log : function() {

				// Check if console is available

				if (typeof(console) != "undefined") {
					console.log(arguments[0]);
				} else {
					alert(arguments[0]);
				}
			}
		};

		// Merge core functions with the fQuery object

		jQuery.extend(fQuery, fQuery._init);
	}

	return fQuery._init;
}

fQuery();
<commit_msg>Edited fquery.js via GitHub<commit_after>/*
	Copyright (c) 2010 Filip Moberg, (filip@mcsquare.se)

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/

/*

	Author:		Filip Moberg
	Name:		fQuery (SuckerPunch)
	Version:	1.0
	Version name:	SuckerPunch
	Released:	2011-07-01

*/

function fQuery() {

	var args = arguments;
	var m;

	// Argument handler

	if (args[0] && args[0].substr(0,1) == "@") {

		// If first argument is an fQuery node

		fQuery._node = new Array();
		m = args[0].split(" ");
		for (i=0; i < m.length; i++) {
			fQuery._node.push(m[i].replace("@", ""));
		}

	} else if(args[0] != undefined && jQuery && jQuery(args[0])[0] !== "") {

		// If first argument is a valid jQuery selector

		fQuery.$ = jQuery(args[0]);
	}

	if (typeof(fQuery._init) == "undefined") {

		// Declare internal functions

		fQuery._internals = {
			wrapper : function() {

				var selector = sel = fQuery.$;
			},

			parseFunction : function() {

				var string = arguments[0].toString();
				var offset = string.indexOf("{");
				var head = string.substr(0, offset);
				var args = head.substr(head.indexOf("(")).replace("(","").replace(")","").replace(/ /g,"").split(",");
				var body = string.substr(offset+1,string.length-offset-2);

				return {
					head : head,
					args : args,
					body : body
				};
			},

			mergeFunctions : function() {

				var p1 = fQuery._internals.parseFunction(arguments[0]);
				var p2 = fQuery._internals.parseFunction(arguments[1]);

				var body = p1.body + p2.body;
				var args;

				if (p1.args[0] !== "") {
					args = p1.args;

					if (p2.args[0] !== "") {
						args = args.concat(p2.args);
					}
				} else if (p2.args[0] !== "") {
					args = p2.args;
				}

				if (args) {
					return new Function(args, "{"+body+"}");
				} else {
					return new Function("{"+body+"}");
				}
			},

			count : function(o) {

				// Count number of child nodes in selected object

				var c = 0;

				for (var k in o) {
					if (o.hasOwnProperty(k)) {
						++c;
					}
				}

				return c;
			},

                        jQextend : {hasOwn:Object.prototype.hasOwnProperty,isPlainObject:function(obj){if(!obj||typeof obj!=="object"||obj.nodeType||this.isWindow(obj)){return false}if(obj.constructor&&!this.hasOwn.call(obj,"constructor")&&!this.hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false}var key;for(key in obj){}return key===undefined||this.hasOwn.call(obj,key)},isWindow:function(obj){return obj&&typeof obj==="object"&&"setInterval"in obj},isArray:Array.isArray||function(obj){return typeof obj==="array"},extend:function(){var options,name,src,copy,copyIsArray,clone,target=arguments[0]||{},i=1,length=arguments.length,deep=false;if(typeof target==="boolean"){deep=target;target=arguments[1]||{};i=2}if(typeof target!=="object"&&typeof target!=="function"){target={}}if(length===i){target=this;--i}for(;i<length;i++){if((options=arguments[i])!=null){for(name in options){src=target[name];copy=options[name];if(target===copy){continue}if(deep&&copy&&(this.isPlainObject(copy)||(copyIsArray=this.isArray(copy)))){if(copyIsArray){copyIsArray=false;clone=src&&this.isArray(src)?src:[]}else{clone=src&&this.isPlainObject(src)?src:{}}target[name]=this.extend(deep,clone,copy)}else if(copy!==undefined){target[name]=copy}}}}return target}}
		};

		// Set default top node wrapper

		fQuery._wrapper = fQuery._internals.wrapper;

		// Declare and initialize core functions

		fQuery._init = {
			alias : function() {

				var arr, obj, key;

				// Create alias for selected node

				if (fQuery._node && fQuery._node[0]) {

					arr = fQuery._node[0] ? fQuery._node[0].split(".") : '';
					obj = fQuery();

					for (var i in arr) {
						key = arr[i];
						obj = obj[key];
					}

					window[arguments[0]] = obj;

				} else {

					for (i=0; i < arguments.length; i++) {
						window[arguments[i]] = fQuery;
					}
				}

				fQuery._node = new Array();
			},

			extend : function() {

				var arr, arg, copy, key, n, wrapper;

				// Declare wrapper function

				var applyWrapper = function() {

					var fetchWrapper = function(o) {

						var f = fQuery._internals.parseFunction(o.wrapper);
						var body;

						if (f.body.indexOf("[FUNCTION]") != "-1") {
							return f.body.replace("[FUNCTION]", o.body);
						} else {
							return f.body + o.body;
						}
					};

					var obj = arguments[0].object;
					var wrapper = arguments[0].wrapper;

					for (var a in obj) {
						if (typeof(obj[a]) == "object") {
							new applyWrapper({object: obj[a], wrapper: wrapper});
						}
						if (typeof(obj[a]) == "function") {

							var f = fQuery._internals.parseFunction(obj[a]);

							body = f.body;
							args = f.args;

							for (var i=wrapper.length-1; i>=0; i--) {
								body = fetchWrapper({body: body, wrapper: wrapper[i]});
							}

							obj[a] = new Function(args, "{"+body+"}");
						}
					}
				};

				// Extend argument object(s) and function(s) to the end of the node chain

				for (i=0; i < fQuery._node.length; i++) {

					arr = fQuery._node[i] ? fQuery._node[i].split(".") : '';
					copy = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;
					arg = arguments[0];
					wrapper = new Array();
					wrapper.push(fQuery._wrapper);
					n = 0;

					// Crawl to the last object of the chain

					for (var k in arr) {
						if (n == arr.length-1 && typeof(arg) == "function") {
							arg = new Object();
							arg[arr[n]] = arguments[0];
						} else {
							key = arr[k];

							if (!copy['function'][key]) {

								copy['function'][key] = {};
								copy['object'][key] = {};
							}
							if (typeof(copy['object'][key]._wrapper) != "undefined") {
								wrapper.push(copy['object'][key]._wrapper);
							}

							copy['function'] = copy['function'][key];
							copy['object'] = copy['object'][key];
						}

						n++;
					}

					// Apply node wrappers (if any) to node functions

					new applyWrapper({object: arg, wrapper: wrapper});

					// Apply new object(s) to the fQuery tree

					jQuery.extend(true, copy['function'], arg);
					jQuery.extend(true, copy['object'], arg);
				}

				// If the extend targets the top node (can only be applied with an object, else fQuery would be overridden)

				if (typeof(fQuery._node[0]) == "undefined" && typeof(arguments[0]) == "object") {

					copy = new Array();
					wrapper = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;
					arg = arguments[0];
					wrapper.push(fQuery._wrapper);

					// Apply node wrappers (if any) to node functions

					new applyWrapper({object: arg, wrapper: wrapper});

					jQuery.extend(true, copy['function'], arg);

					for (var o in arg) {
						copy['object'][o] = arg[o];
					}
				}

				// Reset the _node to an empty array

				fQuery._node = new Array();
			},

			wrap : function() {

				var arr, copy, key;
				var arg = arguments[0];

				// Create wrapper for selected node(s)

				for (i=0; i < fQuery._node.length; i++) {

					arr = fQuery._node[i] ? fQuery._node[i].split(".") : '';
					copy = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;

					for (var k in arr) {
						key = arr[k];

						if (!copy['function'][key]) {

							copy['function'][key] = {};
							copy['object'][key] = {};
						}

						copy['function'] = copy['function'][key];
						copy['object'] = copy['object'][key];
					}

					copy['function']._wrapper = arg;
					copy['object']._wrapper = arg;
				}

				// Create wrapper for top node (and merge with default top node wrapper)

				if (fQuery._node.length === 0) {
					copy = new Array();
					copy['function'] = fQuery._init;
					copy['object'] = fQuery;

					arg = fQuery._internals.mergeFunctions(fQuery._internals.wrapper, arg);

					copy['function']._wrapper = arg;
					copy['object']._wrapper = arg;
				}

				// Reset the _node to an empty array

				fQuery._node = new Array();
			},

			append : function(o) {

				// Faster than jQueries append, but lets you pass through css, bind and attribute objects to jQuery.

				fQuery.$.each(function() {

					var obj = document.createElement(o.element);
					this.appendChild(obj);

					if (o.css) {
						$(obj).css(o.css);
					}

					if (o.attributes) {
						$(obj).attr(o.attributes);
					}

					if (o.bind) {
						for (var k in o.bind) {
							$(obj).bind(k, o.bind[k]);
						}
					}
				});
			},

			log : function() {

				// Check if console is available

				if (typeof(console) != "undefined") {
					console.log(arguments[0]);
				} else {
					alert(arguments[0]);
				}
			}
		};

		// Merge core functions with the fQuery object

		jQuery.extend(fQuery, fQuery._init);
	}

	return fQuery._init;
}

fQuery();
<|endoftext|>


<commit_before>/**
 * Provides 4 features for logging.  log & debug are the same.
 */
export default () => reactotron => {
  return {
    features: {
      log: (message, important = false) => reactotron.send('log', { level: 'debug', message }, !!important),
      debug: (message, important = false) => reactotron.send('log', { level: 'debug', message }, !!important),
      warn: message => reactotron.send('log', { level: 'warn', message }, true),
      error: (message, stack) => reactotron.send('log', { level: 'error', message, stack }, true)
    }
  }
}
<commit_msg>Coerces undefined to null for errors. :( (#374)<commit_after>/**
 * Provides 4 features for logging.  log & debug are the same.
 */
export default () => reactotron => {
  return {
    features: {
      log: (message, important = false) =>
        reactotron.send(
          'log',
          { level: 'debug', message: message || null },
          !!important
        ),
      debug: (message, important = false) =>
        reactotron.send(
          'log',
          { level: 'debug', message: message || null },
          !!important
        ),
      warn: message =>
        reactotron.send(
          'log',
          { level: 'warn', message: message || null },
          true
        ),
      error: (message, stack) =>
        reactotron.send(
          'log',
          { level: 'error', message: message || null, stack: stack || null },
          true
        )
    }
  }
}
<|endoftext|>