<commit_before>const XLSX = require('xlsx');
const _ = require('underscore');
const db = require('../db');
const moment = require('moment');
const fs = require('fs');

module.exports = {
    orderList: function(req, res, next) {
        let no = req.get('CustomerNO');
        db.items.find({
            SK_BCODE: {
                $exists: true
            },
            CreateTime: {
                $gte: moment(0, "HH").toDate(),
                $lte: new Date()
            },
            CustomerNO: no
        }).sort({
            CreateTime: -1
        }).exec(async function(err, data) {
            if (err) {
                res.status(500).send(err);
            } else {
                try {
                    let result = await db.XMLY5000.query(`
                            DROP temporary TABLE IF EXISTS sorddt_tmp;
                            CREATE TEMPORARY TABLE sorddt_tmp (INDEX index_skno (OD_SKNO))
                                SELECT st.OD_ID,st.OD_CTNO,st.OD_SKNO,st.OD_PRICE,OD_NO,OD_QTY
                                            FROM SORDDT st JOIN (
                                                SELECT MAX(OD_ID) OD_ID FROM SORDDT WHERE OD_CTNO = ? AND OD_NO > '2014-06-01' AND OD_QTY > 0
                                                GROUP BY OD_CTNO,OD_SKNO ORDER BY OD_ID
                                            ) stt
                                            ON (st.OD_ID = stt.OD_ID)
                                            ORDER BY st.OD_CTNO,st.OD_SKNO;

                            SELECT DISTINCT OD_NO,OD_CTNO,FirstSale,Price,OD_PRICE,SUM(Amount) Amount,
                                SK_NO,SK_BCODE,SK_NAME,SK_SPEC,SK_UNIT,SK_SUPPNO,SK_SUPPNAME,
                                SK_LOCATE,SK_LPRICE1,SK_LPRICE2,SK_IKIND,SK_NOWQTY,SK_KINDNAME
                                FROM (
                                   SELECT
                                    CASE WHEN (sd.OD_PRICE is null) THEN 0 ELSE 1 END FirstSale
                                    ,CASE WHEN(sd.OD_PRICE is null) THEN SK_LPRICE2 ELSE sd.OD_PRICE END Price
                                    ,CASE WHEN(sd.OD_QTY is null) THEN 0 ELSE sd.OD_QTY END Amount
                                    ,CASE WHEN (b.SK_KINDNAME IS null) THEN '' ELSE b.SK_KINDNAME END SK_KINDNAME
                                    ,a.*
                                    ,OD_PRICE
                                    ,OD_CTNO
                                    ,OD_NO
                                    FROM
                                        (SELECT SK_NO,SK_BCODE,SK_NAME,SK_SPEC,SK_UNIT,SK_SUPPNO,
                                        SK_SUPPNAME,SK_LOCATE,SK_LPRICE1,SK_LPRICE2,SK_IKIND,SK_NOWQTY
                                         from SSTOCK) a
                                        join sorddt_tmp sd ON (a.SK_NO = sd.OD_SKNO )
                                        left join SSTOCKKIND b ON (a.SK_IKIND = b.SK_KINDID)
                                    ) t
                                    GROUP BY OD_NO,OD_CTNO,FirstSale,Price,OD_PRICE,
                                    SK_NO,SK_BCODE,SK_NAME,SK_SPEC,SK_UNIT,
                                    SK_SUPPNO,SK_SUPPNAME,SK_LOCATE,SK_LPRICE1,
                                    SK_LPRICE2,SK_IKIND,SK_NOWQTY,SK_KINDNAME
                                    ORDER BY OD_NO DESC;
                            `, [no]);

                    let indexData = _.indexBy(data, 'SK_NO');
                    let ret = _.reduce(result[result.length - 1], (sum, value, key) => {
                        let v = indexData[value['SK_NO']];
                        if (v) {
                            value = _.extend(value, v, {
                                ordered: 1
                            });
                            //data = _.without(data,v);
                        } else {
                            sum.push(value);
                        }
                        return sum;
                    }, []);
                    res.send(_.union(data, ret));

                } catch (e) {
                    res.status(500).send(e);
                }
            }
        });
    },
    orderUpload: function(req, res, next) {
        let datas = req.body;
        _.each(datas, data => {
            data.CustomerNO = req.get('CustomerNO');
            data.CreateTime = new Date(data.CreateTime);
        })
        db.items.insert(datas, function(err, datas) {
            if (err) {
                res.send(err);
            } else {
                res.send(datas);
            }
        });
    },
    orderCreate: function(req, res, next) {
        let data = req.body;
        data.CustomerNO = req.get('CustomerNO');
        data.CreateTime = new Date();
        db.items.insert(data, function(err, data) {
            if (err) {
                res.status(500).send(err);
            } else {
                res.send(data);
            }
        });
    },
    orderUpdate: function(req, res, next) {
        let id = req.params.id;
        let amount = req.params.amount;
        let price = req.params.price;
        let memo = req.params.memo;
        db.items.update({
                _id: id
            }, {
                $set: {
                    Amount: amount,
                    Price: price,
                    Memo: memo
                }
            }, {},
            function(err, data) {
                if (err) {
                    res.status(500).send(err);
                } else {
                    res.send({
                        numUpdated: data
                    });
                }
            });
    },
    orderDelete: function(req, res, next) {
        db.items.remove({
            _id: req.params.id
        }, {}, function(err, numRemoved) {
            if (err) {
                res.status(500).send(err);
            } else {
                res.send({
                    numRemoved: numRemoved
                });
            }
        });
    },
    orderDaily: function(req, res, next) {
        db.items.find({
            SK_BCODE: {
                $exists: true
            }
        }).sort({
            CreateTime: -1
        }).exec(function(err, result) {
            if (err) {
                res.status(500).send(err);
            } else {
                let v = _.reduce(result, (sum, data) => {
                    let key = moment(data.CreateTime).format("YYYY-MM-DD");
                    if (!sum[key]) {
                        //sum[key] = {key:key,start:moment(key).format("YYYY-MM-DD 00:00:00"),end:moment(key).format("YYYY-MM-DD 23:59:59")};
                        sum[key] = {
                            key: key,
                            start: moment(data.CreateTime),
                            end: moment(data.CreateTime),
                            Date: key,
                            Download: '下載'
                        }
                    } else {
                        let dataDate = moment(data.CreateTime);
                        if (dataDate.isBefore(sum[key].start)) {
                            sum[key].start = dataDate;
                        } else if (dataDate.isAfter(sum[key].end)) {
                            sum[key].end = dataDate;
                        }
                    }
                    return sum;
                }, {});
                res.send(_.values(v));
            }
        });
    },
    orderHistory: async function(req, res, next) {
        try {
            let result = await db.XMLY5000.query(`SELECT * from SORDDT WHERE OD_SKNO = ? AND OD_CTNO = ? ORDER BY OD_NO ASC`, [req.params.no, req.get('CustomerNO')]);
            if (result.length > 0)
                res.send(result);
            else
                res.send([]);
        } catch (e) {
            res.status(500).send(e);
        }
    },
    orderToExcle: function(req, res, next) {
        let start = req.params.start;
        let end = req.params.end;
        res.set("fileName", moment(start).format('YYYYMMDD'));
        db.items.find({
                $and: [{
                    CreateTime: {
                        $gte: moment(start).toDate(),
                        $lte: moment(end).toDate()
                    }
                }, {
                    SK_BCODE: {
                        $exists: true
                    }
                }]
            })
            .sort({
                CreateTime: -1
            }).exec(
                function(err, dataSet) {
                    //console.log(dataSet);
                    if (err) {
                        res.status(500).send(err);
                    } else {
                        let groupData = _.groupBy(dataSet, 'Customer');
                        let wb = {
                            SheetNames: [],
                            Sheets: {}
                        };

                        //案名稱不得使用下列字元: 大於或小於符號 (< >)、星號 ( * )、問號 ( ? )、雙引號 ( " )、分隔號或縱線字元 ( | )、冒號 ( : )、正斜線 ( / ) 或括弧 ( [] )。

                        function fixSheetName(name) {
                            name = name.replace(/[\[\]\:\<\>\*\/\|\?\"\\\：]/g, " ");
                            console.log(name);
                            return name.substring(0, 30);
                        }

                        _.each(groupData, (datas, key) => {
                            key = fixSheetName(key);
                            let _data = _.reduce(datas, function(sum, item) {
                                sum.push({
                                    '貨號': item.SK_NO,
                                    '條碼': item.SK_BCODE,
                                    '品名': item.SK_NAME,
                                    '價格': item.Price,
                                    '數量': item.Amount,
                                    '備註': item.SK_SPEC
                                });
                                return sum;
                            }, []);

                            //console.log(_data);

                            let _headers = [];
                            if (_data.length > 0) {
                                _headers = _.keys(_data[0]) || [];
                            }
                            let headers = _headers
                                .map((v, i) => Object.assign({}, {
                                    v: v,
                                    position: String.fromCharCode(65 + i) + 1
                                }))
                                .reduce((prev, next) => Object.assign({}, prev, {
                                    [next.position]: {
                                        v: next.v
                                    }
                                }), {});
                            let data = _data
                                .map((v, i) => _headers.map((k, j) => Object.assign({}, {
                                    v: v[k],
                                    position: String.fromCharCode(65 + j) + (i + 2)
                                })))
                                .reduce((prev, next) => prev.concat(next))
                                .reduce((prev, next) => Object.assign({}, prev, {
                                    [next.position]: {
                                        v: next.v
                                    }
                                }), {});
                            let output = Object.assign({}, headers, data);
                            let outputPos = Object.keys(output);
                            let ref = outputPos[0] + ':' + outputPos[outputPos.length - 1];

                            wb.SheetNames.push(key);
                            wb.Sheets[key] = Object.assign({}, output, {
                                '!ref': ref,
                                '!cols': [{
                                    wch: 8
                                }, {
                                    wch: 20
                                }, {
                                    wch: 30
                                }, {
                                    wch: 5
                                }, {
                                    wch: 5
                                }, {
                                    wch: 60
                                }, {
                                    wch: 30
                                }],
                                /*'!rows': [{
                                    hpt: 10
                                },{
                                    hpt: 20
                                },{
                                    hpt: 30
                                },{
                                    hpt: 40
                                },{
                                    hpt: 50
                                },{
                                    hpt: 60
                                },{
                                    hpt: 70
                                }],*/
                                '!images': [{
                                    /*name: 'text.png',
                                    fs.readFileSync('text.png');
                                    data: pic.toString('base64'),
                                    opts: {
                                        base64: true
                                    },
                                    position: {
                                        type: 'twoCellAnchor',
                                        attrs: {
                                            editAs: 'oneCell'
                                        },
                                        from: {
                                            col: 6,
                                            row: 1
                                        },
                                        to: {
                                            col: 7,
                                            row: 5
                                        }
                                    }*/
                                }]
                            });

                        });
                        let fileName = "./temp/" + new Date().getTime() + '.xlsx';
                        XLSX.writeFile(wb, fileName);
                        res.download(fileName);
                    }
                });
    }
};
<commit_msg>Update customer.js<commit_after>const XLSX = require('xlsx');
const _ = require('underscore');
const db = require('../db');
const moment = require('moment');
const fs = require('fs');

module.exports = {
    orderList: function(req, res, next) {
        let no = req.get('CustomerNO');
        db.items.find({
            SK_BCODE: {
                $exists: true
            },
            CreateTime: {
                $gte: moment(0, "HH").toDate(),
                $lte: new Date()
            },
            CustomerNO: no
        }).sort({
            CreateTime: -1
        }).exec(async function(err, data) {
            if (err) {
                res.status(500).send(err);
            } else {
                try {
                    let result = await db.XMLY5000.query(`
                            DROP temporary TABLE IF EXISTS sorddt_tmp;
                            CREATE TEMPORARY TABLE sorddt_tmp (INDEX index_skno (OD_SKNO))
                                SELECT st.OD_ID,st.OD_CTNO,st.OD_SKNO,st.OD_PRICE,OD_NO,OD_QTY
                                            FROM SORDDT st JOIN (
                                                SELECT MAX(OD_ID) OD_ID FROM SORDDT WHERE OD_CTNO = ? AND OD_NO > '2014-06-01' AND OD_QTY > 0
                                                GROUP BY OD_CTNO,OD_SKNO ORDER BY OD_ID
                                            ) stt
                                            ON (st.OD_ID = stt.OD_ID)
                                            ORDER BY st.OD_CTNO,st.OD_SKNO;

                            SELECT DISTINCT OD_NO,OD_CTNO,FirstSale,Price,OD_PRICE,SUM(Amount) Amount,
                                SK_NO,SK_BCODE,SK_NAME,SK_SPEC,SK_UNIT,SK_SUPPNO,SK_SUPPNAME,
                                SK_LOCATE,SK_LPRICE1,SK_LPRICE2,SK_IKIND,SK_NOWQTY,SK_KINDNAME
                                FROM (
                                   SELECT
                                    CASE WHEN (sd.OD_PRICE is null) THEN 0 ELSE 1 END FirstSale
                                    ,CASE WHEN(sd.OD_PRICE is null) THEN SK_LPRICE2 ELSE sd.OD_PRICE END Price
                                    ,CASE WHEN(sd.OD_QTY is null) THEN 0 ELSE sd.OD_QTY END Amount
                                    ,CASE WHEN (b.SK_KINDNAME IS null) THEN '' ELSE b.SK_KINDNAME END SK_KINDNAME
                                    ,a.*
                                    ,OD_PRICE
                                    ,OD_CTNO
                                    ,OD_NO
                                    FROM
                                        (SELECT SK_NO,SK_BCODE,SK_NAME,SK_SPEC,SK_UNIT,SK_SUPPNO,
                                        SK_SUPPNAME,SK_LOCATE,SK_LPRICE1,SK_LPRICE2,SK_IKIND,SK_NOWQTY
                                         from SSTOCK) a
                                        join sorddt_tmp sd ON (a.SK_NO = sd.OD_SKNO )
                                        left join SSTOCKKIND b ON (a.SK_IKIND = b.SK_KINDID)
                                    ) t
                                    GROUP BY OD_NO,OD_CTNO,FirstSale,Price,OD_PRICE,
                                    SK_NO,SK_BCODE,SK_NAME,SK_SPEC,SK_UNIT,
                                    SK_SUPPNO,SK_SUPPNAME,SK_LOCATE,SK_LPRICE1,
                                    SK_LPRICE2,SK_IKIND,SK_NOWQTY,SK_KINDNAME
                                    ORDER BY OD_NO DESC;
                            `, [no]);

                    let indexData = _.indexBy(data, 'SK_NO');
                    let ret = _.reduce(result[result.length - 1], (sum, value, key) => {
                        let v = indexData[value['SK_NO']];
                        if (v) {
                            value = _.extend(value, v, {
                                ordered: 1
                            });
                            //data = _.without(data,v);
                        } else {
                            sum.push(value);
                        }
                        return sum;
                    }, []);
                    res.send(_.union(data, ret));

                } catch (e) {
                    res.status(500).send(e);
                }
            }
        });
    },
    orderUpload: function(req, res, next) {
        let datas = req.body;
        _.each(datas, data => {
            data.CustomerNO = req.get('CustomerNO');
            data.CreateTime = new Date(data.CreateTime);
        })
        db.items.insert(datas, function(err, datas) {
            if (err) {
                res.send(err);
            } else {
                res.send(datas);
            }
        });
    },
    orderCreate: function(req, res, next) {
        let data = req.body;
        data.CustomerNO = req.get('CustomerNO');
        data.CreateTime = new Date();
        db.items.insert(data, function(err, data) {
            if (err) {
                res.status(500).send(err);
            } else {
                res.send(data);
            }
        });
    },
    orderUpdate: function(req, res, next) {
        let id = req.params.id;
        let amount = req.params.amount;
        let price = req.params.price;
        let memo = req.params.memo;
        console.log(req.params);
        db.items.update({
                _id: id
            }, {
                $set: {
                    Amount: amount,
                    Price: price,
                    Memo: memo
                }
            }, {},
            function(err, data) {
                if (err) {
                    res.status(500).send(err);
                } else {
                    res.send({
                        numUpdated: data
                    });
                }
            });
    },
    orderDelete: function(req, res, next) {
        db.items.remove({
            _id: req.params.id
        }, {}, function(err, numRemoved) {
            if (err) {
                res.status(500).send(err);
            } else {
                res.send({
                    numRemoved: numRemoved
                });
            }
        });
    },
    orderDaily: function(req, res, next) {
        db.items.find({
            SK_BCODE: {
                $exists: true
            }
        }).sort({
            CreateTime: -1
        }).exec(function(err, result) {
            if (err) {
                res.status(500).send(err);
            } else {
                let v = _.reduce(result, (sum, data) => {
                    let key = moment(data.CreateTime).format("YYYY-MM-DD");
                    if (!sum[key]) {
                        //sum[key] = {key:key,start:moment(key).format("YYYY-MM-DD 00:00:00"),end:moment(key).format("YYYY-MM-DD 23:59:59")};
                        sum[key] = {
                            key: key,
                            start: moment(data.CreateTime),
                            end: moment(data.CreateTime),
                            Date: key,
                            Download: '下載'
                        }
                    } else {
                        let dataDate = moment(data.CreateTime);
                        if (dataDate.isBefore(sum[key].start)) {
                            sum[key].start = dataDate;
                        } else if (dataDate.isAfter(sum[key].end)) {
                            sum[key].end = dataDate;
                        }
                    }
                    return sum;
                }, {});
                res.send(_.values(v));
            }
        });
    },
    orderHistory: async function(req, res, next) {
        try {
            let result = await db.XMLY5000.query(`SELECT * from SORDDT WHERE OD_SKNO = ? AND OD_CTNO = ? ORDER BY OD_NO ASC`, [req.params.no, req.get('CustomerNO')]);
            if (result.length > 0)
                res.send(result);
            else
                res.send([]);
        } catch (e) {
            res.status(500).send(e);
        }
    },
    orderToExcle: function(req, res, next) {
        let start = req.params.start;
        let end = req.params.end;
        res.set("fileName", moment(start).format('YYYYMMDD'));
        db.items.find({
                $and: [{
                    CreateTime: {
                        $gte: moment(start).toDate(),
                        $lte: moment(end).toDate()
                    }
                }, {
                    SK_BCODE: {
                        $exists: true
                    }
                }]
            })
            .sort({
                CreateTime: -1
            }).exec(
                function(err, dataSet) {
                    //console.log(dataSet);
                    if (err) {
                        res.status(500).send(err);
                    } else {
                        let groupData = _.groupBy(dataSet, 'Customer');
                        let wb = {
                            SheetNames: [],
                            Sheets: {}
                        };

                        //案名稱不得使用下列字元: 大於或小於符號 (< >)、星號 ( * )、問號 ( ? )、雙引號 ( " )、分隔號或縱線字元 ( | )、冒號 ( : )、正斜線 ( / ) 或括弧 ( [] )。

                        function fixSheetName(name) {
                            name = name.replace(/[\[\]\:\<\>\*\/\|\?\"\\\：]/g, " ");
                            console.log(name);
                            return name.substring(0, 30);
                        }

                        _.each(groupData, (datas, key) => {
                            key = fixSheetName(key);
                            let _data = _.reduce(datas, function(sum, item) {
                                sum.push({
                                    '貨號': item.SK_NO,
                                    '條碼': item.SK_BCODE,
                                    '品名': item.SK_NAME,
                                    '價格': item.Price,
                                    '數量': item.Amount,
                                    '備註': item.SK_SPEC
                                });
                                return sum;
                            }, []);

                            //console.log(_data);

                            let _headers = [];
                            if (_data.length > 0) {
                                _headers = _.keys(_data[0]) || [];
                            }
                            let headers = _headers
                                .map((v, i) => Object.assign({}, {
                                    v: v,
                                    position: String.fromCharCode(65 + i) + 1
                                }))
                                .reduce((prev, next) => Object.assign({}, prev, {
                                    [next.position]: {
                                        v: next.v
                                    }
                                }), {});
                            let data = _data
                                .map((v, i) => _headers.map((k, j) => Object.assign({}, {
                                    v: v[k],
                                    position: String.fromCharCode(65 + j) + (i + 2)
                                })))
                                .reduce((prev, next) => prev.concat(next))
                                .reduce((prev, next) => Object.assign({}, prev, {
                                    [next.position]: {
                                        v: next.v
                                    }
                                }), {});
                            let output = Object.assign({}, headers, data);
                            let outputPos = Object.keys(output);
                            let ref = outputPos[0] + ':' + outputPos[outputPos.length - 1];

                            wb.SheetNames.push(key);
                            wb.Sheets[key] = Object.assign({}, output, {
                                '!ref': ref,
                                '!cols': [{
                                    wch: 8
                                }, {
                                    wch: 20
                                }, {
                                    wch: 30
                                }, {
                                    wch: 5
                                }, {
                                    wch: 5
                                }, {
                                    wch: 60
                                }, {
                                    wch: 30
                                }],
                                /*'!rows': [{
                                    hpt: 10
                                },{
                                    hpt: 20
                                },{
                                    hpt: 30
                                },{
                                    hpt: 40
                                },{
                                    hpt: 50
                                },{
                                    hpt: 60
                                },{
                                    hpt: 70
                                }],*/
                                '!images': [{
                                    /*name: 'text.png',
                                    fs.readFileSync('text.png');
                                    data: pic.toString('base64'),
                                    opts: {
                                        base64: true
                                    },
                                    position: {
                                        type: 'twoCellAnchor',
                                        attrs: {
                                            editAs: 'oneCell'
                                        },
                                        from: {
                                            col: 6,
                                            row: 1
                                        },
                                        to: {
                                            col: 7,
                                            row: 5
                                        }
                                    }*/
                                }]
                            });

                        });
                        let fileName = "./temp/" + new Date().getTime() + '.xlsx';
                        XLSX.writeFile(wb, fileName);
                        res.download(fileName);
                    }
                });
    }
};
<|endoftext|>


<commit_before>import {modelToEditor} from "../editor/node-convert"
import {downloadFile} from "./download"
import {createSlug} from "./tools"
import {BibliographyDB} from "../bibliography/database"
import {FormatCitations} from "../citations/format"
import {fidusSchema} from "../editor/schema"

import Docxtemplater from "docxtemplater"
import JSZipUtils from "jszip-utils"

/*
Exporter to Microsoft Word.

This exporter is *very* experimental. Do not count on using it unless you
have the time to fix it.

TODO:
* figures
* footnotes
* equations
* links
*/

export class WordExporter {
    constructor(doc, bibDB) {
        let that = this
        this.doc = doc
        // We use the doc in the pm format as this is what we will be using
        // throughout the application in the future.
        this.pmDoc = modelToEditor(this.doc)
        this.template = false
        this.wdoc = false
        this.citInfos = []
        this.citFm = false
        this.pmCits = []
        this.docData = {}
        if (bibDB) {
            this.bibDB = bibDB // the bibliography has already been loaded for some other purpose. We reuse it.
            this.exporter()
        } else {
            this.bibDB = new BibliographyDB(doc.owner.id, false, false, false)
            this.bibDB.getDB(function() {
                that.exporter()
            })
        }
    }

    getTemplate(callback) {
        let that = this
        JSZipUtils.getBinaryContent(
            staticUrl + 'docx/template.docx',
            function(err, template){
                that.template = template
                callback()
            }
        )
    }

    exporter() {
        let that = this
        this.formatCitations()

        this.getTemplate(function(){
            that.wdoc = new Docxtemplater(that.template)
            that.getDocData()
            that.prepareAndDownload()
        })
    }

    // Citations are highly interdependent -- so we need to format them all
    // together before laying out the document.
    formatCitations() {
        let that = this
        this.pmDoc.descendants(
            function(node){
                if (node.type.name==='citation') {
                    that.citInfos.push(node.attrs)
                }
            }
        )
        this.citFm = new FormatCitations(this.citInfos, this.doc.settings.citationstyle, this.bibDB)
        this.citFm.init()
        // There could be some formatting in the citations, so we parse them through the PM schema for final formatting.
        // We need to put the citations each in a paragraph so that it works with
        // the fiduswriter schema and so that the converter doesn't mash them together.
        let citationsHTML = ''
        this.citFm.citationTexts.forEach(function(ct){
            citationsHTML += '
'+ct+'
'
        })

        // We create a standard document DOM node, add the citations
        // into the last child (the body) and parse it back.
        let dom = fidusSchema.parseDOM(document.createTextNode('')).toDOM()
        dom.lastElementChild.innerHTML = citationsHTML
        this.pmCits = fidusSchema.parseDOM(dom).lastChild.toJSON().content

        // Now we do the same for the bibliography.
        dom = fidusSchema.parseDOM(document.createTextNode('')).toDOM()
        dom.lastElementChild.innerHTML = this.citFm.bibliographyHTML
        // Remove empty bibliography header (used in web version)
        dom.lastElementChild.removeChild(dom.lastElementChild.firstElementChild)
        this.pmBib = fidusSchema.parseDOM(dom).lastChild.toJSON()
        // use the References style for the paragraphs in the bibliography
        this.pmBib.type = 'bibliography'
    }

    getDocData() {
        this.docData = {
            title: this.pmDoc.child(0).textContent,
            subtitle: this.pmDoc.child(1).textContent,
            authors: this.pmDoc.child(2).textContent,
            abstract: this.transformRichtext(this.pmDoc.child(3).toJSON()),
            keywords: this.pmDoc.child(4).textContent,
            body: this.transformRichtext(this.pmDoc.child(5).toJSON()),
            bibliography: this.transformRichtext(this.pmBib)
        }
    }

    prepareAndDownload() {
        this.wdoc.setData(this.docData)
        this.wdoc.render()
        let out = this.wdoc.getZip().generate({type:"blob"})
        downloadFile(createSlug(this.docData.title)+'.docx', out)
    }

    escapeText(text) {
		return text
            .replace(/"/g, '"')
            .replace(/&/g, '&')
			.replace(/</g, '<')
			.replace(/>/g, '>')
    }

    transformRichtext(node, options = {}) {
        let start = '', content = '', end = ''

        switch(node.type) {
            case 'body':
                options = _.clone(options)
                options.section = 'Normal'
                break
            case 'abstract':
                options = _.clone(options)
                options.section = 'Abstract'
                break
            case 'bibliography':
                options = _.clone(options)
                options.section = 'References'
                break
            case 'paragraph':
                // This should really be something like
                // '<w:p w:rsidR="A437D321" w:rsidRDefault="2B935ADC">'
                // See: https://blogs.msdn.microsoft.com/brian_jones/2006/12/11/whats-up-with-all-those-rsids/
                // But tests with Word 2016/LibreOffice seem to indicate that it
                // doesn't care if the attributes are missing.
                // We may need to add them later, if it turns out this is a problem
                // for other versions of Word. In that case we should also add
                // it to settings.xml as described in above link.
                start += '<w:p>'
                start += '<w:pPr><w:pStyle w:val="'+options.section+'"/>'
                if (options.list_type) {
                    start += '<w:numPr><w:ilvl w:val="'+options.list_depth+'"/>'
                    start += '<w:numId w:val="'+options.list_type+'"/></w:numPr>'
                } else {
                    start += '<w:rPr></w:rPr>'
                }
                start += '</w:pPr>'
                end += '</w:p>'
                break
            case 'heading':
                start += '<w:p>'
                start += '<w:pPr><w:pStyle w:val="Heading'+node.attrs.level+'"/><w:rPr></w:rPr></w:pPr>'
                end += '</w:p>'
                break
            case 'code':
                start += '<w:p>'
                start += '<w:pPr><w:pStyle w:val="Code"/><w:rPr></w:rPr></w:pPr>'
                end += '</w:p>'
                break
            case 'blockquote':
                // This is imperfect, but Word doesn't seem to provide section/quotation nesting
                options = _.clone(options)
                options.section = 'Quote'
                break
            case 'ordered_list':
                options = _.clone(options)
                options.section = 'ListParagraph'
                options.list_type = '1'
                if (options.list_depth === undefined) {
                    options.list_depth = 0
                } else {
                    options.list_depth = 1
                }
                break
            case 'bullet_list':
                options = _.clone(options)
                options.section = 'ListParagraph'
                options.list_type = '2'
                if (options.list_depth === undefined) {
                    options.list_depth = 0
                } else {
                    options.list_depth = 1
                }
                break
            case 'list_item':
                // Word seems to lack complex nesting options. The styling is applied
                // to child paragraphs. This will deliver correct results in most
                // cases.
                break
            case 'text':
                start += '<w:r>'
                if (node.marks) {
                    start += '<w:rPr>'
                    if (_.findWhere(node.marks, {_:'strong'})) {
                        start += '<w:b/><w:bCs/>'
                    }
                    if (_.findWhere(node.marks, {_:'em'})) {
                        start += '<w:i/><w:iCs/>'
                    }
                    start += '</w:rPr>'
                }
                let textAttr = ''
                if (node.text[0] === ' ' || node.text[node.text.length-1] === ' ') {
                    textAttr += 'xml:space="preserve"'
                }
                start += '<w:t '+textAttr+'>'
                end += '</w:t></w:r>'
                content += this.escapeText(node.text)
                break
            case 'citation':
                // We take the first citation from the stack and remove it.
                let cit = this.pmCits.shift()
                for (let i=0; i < cit.content.length; i++) {
                    content += this.transformRichtext(cit.content[i], options)
                }
                break
            default:
                console.warn('Unhandled node type:' + node.type)
                break
        }

        if (node.content) {
            for (let i=0; i < node.content.length; i++) {
                content += this.transformRichtext(node.content[i], options)
            }
        }

        return start + content + end
    }

}
<commit_msg>make compatible with asyncrhonous citation formatting<commit_after>import {modelToEditor} from "../editor/node-convert"
import {downloadFile} from "./download"
import {createSlug} from "./tools"
import {BibliographyDB} from "../bibliography/database"
import {FormatCitations} from "../citations/format"
import {fidusSchema} from "../editor/schema"

import Docxtemplater from "docxtemplater"
import JSZipUtils from "jszip-utils"

/*
Exporter to Microsoft Word.

This exporter is *very* experimental. Do not count on using it unless you
have the time to fix it.

TODO:
* figures
* footnotes
* equations
* links
*/

export class WordExporter {
    constructor(doc, bibDB) {
        let that = this
        this.doc = doc
        // We use the doc in the pm format as this is what we will be using
        // throughout the application in the future.
        this.pmDoc = modelToEditor(this.doc)
        this.template = false
        this.wdoc = false
        this.citInfos = []
        this.citFm = false
        this.pmCits = []
        this.docData = {}
        if (bibDB) {
            this.bibDB = bibDB // the bibliography has already been loaded for some other purpose. We reuse it.
            this.exporter()
        } else {
            this.bibDB = new BibliographyDB(doc.owner.id, false, false, false)
            this.bibDB.getDB(function() {
                that.exporter()
            })
        }
    }

    getTemplate(callback) {
        let that = this
        JSZipUtils.getBinaryContent(
            staticUrl + 'docx/template.docx',
            function(err, template){
                that.template = template
                callback()
            }
        )
    }

    exporter() {
        let that = this
        this.formatCitations()

        this.getTemplate(function(){
            that.wdoc = new Docxtemplater(that.template)
            that.getDocData()
            that.prepareAndDownload()
        })
    }

    // Citations are highly interdependent -- so we need to format them all
    // together before laying out the document.
    formatCitations() {
        let that = this
        this.pmDoc.descendants(
            function(node){
                if (node.type.name==='citation') {
                    that.citInfos.push(node.attrs)
                }
            }
        )
        this.citFm = new FormatCitations(
            this.citInfos,
            this.doc.settings.citationstyle,
            this.bibDB,
            function() {
                that.formatCitationsTwo()
            }
        )
        this.citFm.init()
    }

    formatCitationsTwo() {
        // There could be some formatting in the citations, so we parse them through the PM schema for final formatting.
        // We need to put the citations each in a paragraph so that it works with
        // the fiduswriter schema and so that the converter doesn't mash them together.
        let citationsHTML = ''
        this.citFm.citationTexts.forEach(function(ct){
            citationsHTML += '
'+ct+'
'
        })

        // We create a standard document DOM node, add the citations
        // into the last child (the body) and parse it back.
        let dom = fidusSchema.parseDOM(document.createTextNode('')).toDOM()
        dom.lastElementChild.innerHTML = citationsHTML
        this.pmCits = fidusSchema.parseDOM(dom).lastChild.toJSON().content

        // Now we do the same for the bibliography.
        dom = fidusSchema.parseDOM(document.createTextNode('')).toDOM()
        dom.lastElementChild.innerHTML = this.citFm.bibliographyHTML
        // Remove empty bibliography header (used in web version)
        dom.lastElementChild.removeChild(dom.lastElementChild.firstElementChild)
        this.pmBib = fidusSchema.parseDOM(dom).lastChild.toJSON()
        // use the References style for the paragraphs in the bibliography
        this.pmBib.type = 'bibliography'
    }

    getDocData() {
        this.docData = {
            title: this.pmDoc.child(0).textContent,
            subtitle: this.pmDoc.child(1).textContent,
            authors: this.pmDoc.child(2).textContent,
            abstract: this.transformRichtext(this.pmDoc.child(3).toJSON()),
            keywords: this.pmDoc.child(4).textContent,
            body: this.transformRichtext(this.pmDoc.child(5).toJSON()),
            bibliography: this.transformRichtext(this.pmBib)
        }
    }

    prepareAndDownload() {
        this.wdoc.setData(this.docData)
        this.wdoc.render()
        let out = this.wdoc.getZip().generate({type:"blob"})
        downloadFile(createSlug(this.docData.title)+'.docx', out)
    }

    escapeText(text) {
		return text
            .replace(/"/g, '"')
            .replace(/&/g, '&')
			.replace(/</g, '<')
			.replace(/>/g, '>')
    }

    transformRichtext(node, options = {}) {
        let start = '', content = '', end = ''

        switch(node.type) {
            case 'body':
                options = _.clone(options)
                options.section = 'Normal'
                break
            case 'abstract':
                options = _.clone(options)
                options.section = 'Abstract'
                break
            case 'bibliography':
                options = _.clone(options)
                options.section = 'References'
                break
            case 'paragraph':
                // This should really be something like
                // '<w:p w:rsidR="A437D321" w:rsidRDefault="2B935ADC">'
                // See: https://blogs.msdn.microsoft.com/brian_jones/2006/12/11/whats-up-with-all-those-rsids/
                // But tests with Word 2016/LibreOffice seem to indicate that it
                // doesn't care if the attributes are missing.
                // We may need to add them later, if it turns out this is a problem
                // for other versions of Word. In that case we should also add
                // it to settings.xml as described in above link.
                start += '<w:p>'
                start += '<w:pPr><w:pStyle w:val="'+options.section+'"/>'
                if (options.list_type) {
                    start += '<w:numPr><w:ilvl w:val="'+options.list_depth+'"/>'
                    start += '<w:numId w:val="'+options.list_type+'"/></w:numPr>'
                } else {
                    start += '<w:rPr></w:rPr>'
                }
                start += '</w:pPr>'
                end += '</w:p>'
                break
            case 'heading':
                start += '<w:p>'
                start += '<w:pPr><w:pStyle w:val="Heading'+node.attrs.level+'"/><w:rPr></w:rPr></w:pPr>'
                end += '</w:p>'
                break
            case 'code':
                start += '<w:p>'
                start += '<w:pPr><w:pStyle w:val="Code"/><w:rPr></w:rPr></w:pPr>'
                end += '</w:p>'
                break
            case 'blockquote':
                // This is imperfect, but Word doesn't seem to provide section/quotation nesting
                options = _.clone(options)
                options.section = 'Quote'
                break
            case 'ordered_list':
                options = _.clone(options)
                options.section = 'ListParagraph'
                options.list_type = '1'
                if (options.list_depth === undefined) {
                    options.list_depth = 0
                } else {
                    options.list_depth = 1
                }
                break
            case 'bullet_list':
                options = _.clone(options)
                options.section = 'ListParagraph'
                options.list_type = '2'
                if (options.list_depth === undefined) {
                    options.list_depth = 0
                } else {
                    options.list_depth = 1
                }
                break
            case 'list_item':
                // Word seems to lack complex nesting options. The styling is applied
                // to child paragraphs. This will deliver correct results in most
                // cases.
                break
            case 'text':
                start += '<w:r>'
                if (node.marks) {
                    start += '<w:rPr>'
                    if (_.findWhere(node.marks, {_:'strong'})) {
                        start += '<w:b/><w:bCs/>'
                    }
                    if (_.findWhere(node.marks, {_:'em'})) {
                        start += '<w:i/><w:iCs/>'
                    }
                    start += '</w:rPr>'
                }
                let textAttr = ''
                if (node.text[0] === ' ' || node.text[node.text.length-1] === ' ') {
                    textAttr += 'xml:space="preserve"'
                }
                start += '<w:t '+textAttr+'>'
                end += '</w:t></w:r>'
                content += this.escapeText(node.text)
                break
            case 'citation':
                // We take the first citation from the stack and remove it.
                let cit = this.pmCits.shift()
                for (let i=0; i < cit.content.length; i++) {
                    content += this.transformRichtext(cit.content[i], options)
                }
                break
            default:
                console.warn('Unhandled node type:' + node.type)
                break
        }

        if (node.content) {
            for (let i=0; i < node.content.length; i++) {
                content += this.transformRichtext(node.content[i], options)
            }
        }

        return start + content + end
    }

}
<|endoftext|>


<commit_before>const fs = require('fs');
const p = require('path');

const defaultSettings = {
  title: 'My project',
  authors: ['Your demoscene handle'],
  description: 'This is my project',
  previewImage: 'https://raw.githubusercontent.com/ninjadev/nin/master/nin/frontend/app/images/nin-dark.png',
  music: {
    path: 'res/music.mp3',
    bpm: 125,
    subdivision: 4
  },
  googleAnalyticsID: 'Your GA ID'
};

function init(projectPath) {
  fs.writeFileSync(
    p.join(projectPath, 'nin.json'),
    new Buffer(JSON.stringify(defaultSettings, null, '  '))
  );
}

function load(projectPath) {
  let rawProjectSettings = fs.readFileSync(p.join(projectPath, 'nin.json'), 'utf8');
  let projectSettings = JSON.parse(rawProjectSettings);
  return traverse(projectSettings, defaultSettings);
}

function write(projectPath, parsedProjectSettings) {
  let projectSettingsFile = 'var PROJECT = ' + JSON.stringify(parsedProjectSettings) + ';';
  fs.writeFileSync(
    p.join(projectPath, 'gen/projectSettings.js'),
    new Buffer(projectSettingsFile)
  );
}

function generate(projectPath) {
  write(projectPath, load(projectPath));
}

function traverse(input, defaults) {
  let output = {};
  for (let key in defaults) {
    if (key in input) {
      if (input[key].constructor === Object) {
        output[key] = traverse(input[key], defaults[key]);
      } else {
        output[key] = input[key];
      }
    } else {
      output[key] = defaults[key];
    }
  }
  return output;
}

module.exports = {init: init, load: load, generate: generate};
<commit_msg>Add newline to end of nin.json in init<commit_after>const fs = require('fs');
const p = require('path');

const defaultSettings = {
  title: 'My project',
  authors: ['Your demoscene handle'],
  description: 'This is my project',
  previewImage: 'https://raw.githubusercontent.com/ninjadev/nin/master/nin/frontend/app/images/nin-dark.png',
  music: {
    path: 'res/music.mp3',
    bpm: 125,
    subdivision: 4
  },
  googleAnalyticsID: 'Your GA ID'
};

function init(projectPath) {
  fs.writeFileSync(
    p.join(projectPath, 'nin.json'),
    new Buffer(JSON.stringify(defaultSettings, null, '  ') + '\n')
  );
}

function load(projectPath) {
  let rawProjectSettings = fs.readFileSync(p.join(projectPath, 'nin.json'), 'utf8');
  let projectSettings = JSON.parse(rawProjectSettings);
  return traverse(projectSettings, defaultSettings);
}

function write(projectPath, parsedProjectSettings) {
  let projectSettingsFile = 'var PROJECT = ' + JSON.stringify(parsedProjectSettings) + ';';
  fs.writeFileSync(
    p.join(projectPath, 'gen/projectSettings.js'),
    new Buffer(projectSettingsFile)
  );
}

function generate(projectPath) {
  write(projectPath, load(projectPath));
}

function traverse(input, defaults) {
  let output = {};
  for (let key in defaults) {
    if (key in input) {
      if (input[key].constructor === Object) {
        output[key] = traverse(input[key], defaults[key]);
      } else {
        output[key] = input[key];
      }
    } else {
      output[key] = defaults[key];
    }
  }
  return output;
}

module.exports = {init: init, load: load, generate: generate};
<|endoftext|>


<commit_before>var count = 0;

addWatcher('pony', function(ack, err) {
    count += 1;
    if (count % 4 == 2) {
        err('out for the count');
    } else {
        ack();
    }
});

addWatcher('py', watchHTTP('http://localhost:8080/irc_handlers.py'));

addWatcher('Google DNS', watchPing('8.8.8.8'));

<commit_msg>Use a more sensible default service set<commit_after>addWatcher('Internet uplink', watchPing('8.8.8.8'));

<|endoftext|>


<commit_before>/*jshint esversion:6, node:true*/
'use strict';
const COLORS = require('colors');
const _ansiStyle = require('ansi-color').set;
const enforceColumnWidth = require('./line-formatter').enforceColumnWidth;

/*
 * const ansiRegex = require('ansi-regex')();
 * let LN = (before + from).replace(ansiRegex, '').length;
 */
const LN = 37;

const DEFAULTS = {
    arrows: {
        smal: '▸',
        black: '▶',
        empty: '▷'
    },
    symbols:{
        highVoltage: '⚡',
        arrow:'➞',
        dot:'•',
        rarrow: '⟶'
    },
    columnWidth: 190
};

/**
 *
 * @memberof core/Logger
*/
class Message {
    constructor() {
        this._colorizer = null;
        this._message = 'No message';
        this._timestamp = null;
        this._level = 'info';
        this._label = null;
        this._from = null;
        // this._template = '[{{timestamp}} {{level}}] {{message}}';
    }

    /**
    *
    * @param {Colorizer} colorizer
    */
    setColorizer (colorizer) {
        this._colorizer = colorizer;
        return this;
    }

    setColors(colors) {
        this._colors = colors;
        return this;
    }

    setColor(key, style) {
        this._colors[key] = style;
        return this;
    }

    setTextStyle(...style) {
        /*
         * We can use an array as argument:
         * ['red', 'bold', 'white_bg']
         */
        if(Array.isArray(style[0])) {
            style = style[0];
        }

        if(style.length === 1 && typeof style[0] === 'string') {
            style = style[0];
        } else {
            style = style.join('+');
        }

        // [
        //     'bold', 'underline', 'blink',
        //     'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
        //     'black_bg', 'red_bg', 'green_bg', 'yellow_bg', 'blue_bg', 'magenta_bg', 'cyan_bg', 'white_bg'
        // ]

        this._textStyle = style;

        return this;
    }

    stylize(message, style) {
        return _ansiStyle(message, style);
    }

    colorify (level, message, createColor) {
        if(createColor) {
            if(!this._colors[level]) {
                this.setColor(level, ['bold']);
            }
        }

        try {
            return this._colorizer(level, message);
        } catch (e) {
            return message;
        }
    }

    randomColor() {
        // let colors = [
        // 'bgBlack',
        // 'bgRed',
        // 'bgGreen',
        // 'bgYellow',
        // 'bgBlue',
        // 'bgMagenta',
        // 'bgCyan',
        // 'bgWhite'];

        let colors = [
        'black',
        'red',
        'green',
        'yellow',
        'blue',
        'magenta',
        'cyan',
        'white'];
        let c = colors[Math.floor(Math.random() * colors.length)];
        return c;
    }

    /**
    * @param {string|undefined} message
    * @return {Message}
    */
    setMessage (message) {
        if (message) {
            this._message = message;
        }
        return this;
    }

    setLoggerName(name) {
        if(name) {
            this._loggerName = name;
        }
        return this;
    }

    /**
    * @param {boolean|function} timestamp
    * @return {Message}
    */
    setTime (timestamp) {
        if (typeof timestamp === 'function') {
            this._timestamp = timestamp();
        } else if (timestamp) {
            var format = typeof timestamp === 'string' ? timestamp : 'hh:mm:ss';
            this._timestamp = this.dateFormat(format);
        }

        return this;
    }

    /**
    * @param {string|undefined} label
    * @return {Message}
    */
    setLabel (label) {
        if (label) {
            this._label = label;
        }
        return this;
    }

    /**
    * @param {string|undefined} level
    * @return {Message}
    */
    setLevel (level) {
        if (level) {
            this._level = level.toLowerCase();
        }

        return this;
    }

    /**
    * @param {string|undefined} from
    * @return {Message}
    */
    setFrom (from) {
        if (from) {
            this._from = from;
        }
        return this;
    }
    /*
     * eg: format="YYYY-MM-DD hh:mm:ss";
     */
    dateFormat(format) {
        var date = new Date();

        var o = {
            'M+' : date.getMonth()+1,                //month
            'D+' : date.getDate(),                   //day
            'h+' : date.getHours(),                  //hour
            'm+' : date.getMinutes(),                //minute
            's+' : date.getSeconds(),                //second
            'q+' : Math.floor((date.getMonth()+3)/3),//quarter
            'S' : date.getMilliseconds()             //millisecond
        };

        if(/(Y+)/.test(format)) {
            format = format.replace(RegExp.$1, (date.getFullYear()+'').substr(4 - RegExp.$1.length));
        }

        for(var k in o) {
            if(new RegExp('('+ k +')').test(format)) {
                format = format.replace(RegExp.$1, RegExp.$1.length==1 ? o[k] : ('00'+ o[k]).substr((''+ o[k]).length));
            }
        }
        return format;
    }

    padRight(str='', len=5, char=' ') {
        if (str.length >= len) return str;
        return str + Array(len - str.length + 1).join(char);
    }

    padLeft(str='', len=5, char=' ') {
        if (str.length >= len) return str;
        return Array(len - str.length + 1).join(char) + str;
    }

    pad(str='', len=10, char='') {
        if (str.length >= len) return str;
        len = len - str.length;
        let left = Array(Math.ceil(len / 2) + 1).join(char);
        let right = Array(Math.floor(len / 2) + 1).join(char);
        return left + str + right;
    }

    toString() {
        let from = '';
        let after = '';
        let before = '';
        let message = this._message;

        if (this._label) {
            before += `[${this._label}] `;
        }

        let level = this.pad(this._level.toUpperCase() , 8, ' ');
        before += `${level}`;

        before = this.colorify(this._level, before);

        if (this._timestamp) {
            before += `[${this._timestamp}] `;
        }

        if(this._loggerName) {
            let loggername = this.padRight(this._loggerName, 12);
            loggername = this.colorify(loggername, loggername, true);
            before += `├── ${loggername}`;
        }

        before += ' : ';

        if (this._from) {
            from += `${this._from} `;
            after += '- ';
        }
        // let message = this._message;
        if(['error', 'warn'].indexOf(this._level) !== -1) {
            message = this.colorify(this._level + '-msg', message);
        }

        if(this._textStyle) {
            message = this.stylize(message, this._textStyle);
        }

        message = enforceColumnWidth(message, this.columnWidth);

        message = message.join(this.padRight('\n', LN)+' ');

        after += `${message}`;

        return before + from + after;
    }
}

///////
module.exports = Message;
<commit_msg>udpate docs<commit_after>'use strict';
const COLORS = require('colors');
const _ansiStyle = require('ansi-color').set;
const enforceColumnWidth = require('./line-formatter').enforceColumnWidth;

/*
 * const ansiRegex = require('ansi-regex')();
 * let LN = (before + from).replace(ansiRegex, '').length;
 */
const LN = 37;

const DEFAULTS = {
    arrows: {
        smal: '▸',
        black: '▶',
        empty: '▷'
    },
    symbols:{
        highVoltage: '⚡',
        arrow:'➞',
        dot:'•',
        rarrow: '⟶'
    },
    columnWidth: 190
};

/**
 * Message is the formatter for messages
 * being written to the console transport.
 *
 * See [winston.transports.Console]() fore
 * more information.
 *
 * @class Message
 * @memberof core/logger
*/
class Message {
    constructor() {
        this._colorizer = null;
        this._message = 'No message';
        this._timestamp = null;
        this._level = 'info';
        this._label = null;
        this._from = null;
        // this._template = '[{{timestamp}} {{level}}] {{message}}';
    }

    /**
    *
    * @param {Colorizer} colorizer
    * @return {Message} Return instance
    */
    setColorizer (colorizer) {
        this._colorizer = colorizer;
        return this;
    }

    /**
     * This takes a configuration
     * object like Winston's colors object.
     *
     * @param {Object} colors
     */
    setColors(colors) {
        this._colors = colors;
        return this;
    }

    setColor(key, style) {
        this._colors[key] = style;
        return this;
    }

    setTextStyle(...style) {
        /*
         * We can use an array as argument:
         * ['red', 'bold', 'white_bg']
         */
        if(Array.isArray(style[0])) {
            style = style[0];
        }

        if(style.length === 1 && typeof style[0] === 'string') {
            style = style[0];
        } else {
            style = style.join('+');
        }

        // [
        //     'bold', 'underline', 'blink',
        //     'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
        //     'black_bg', 'red_bg', 'green_bg', 'yellow_bg', 'blue_bg', 'magenta_bg', 'cyan_bg', 'white_bg'
        // ]

        this._textStyle = style;

        return this;
    }

    stylize(message, style) {
        return _ansiStyle(message, style);
    }

    colorify (level, message, createColor) {
        if(createColor) {
            if(!this._colors[level]) {
                this.setColor(level, ['bold']);
            }
        }

        try {
            return this._colorizer(level, message);
        } catch (e) {
            return message;
        }
    }

    randomColor() {
        // let colors = [
        // 'bgBlack',
        // 'bgRed',
        // 'bgGreen',
        // 'bgYellow',
        // 'bgBlue',
        // 'bgMagenta',
        // 'bgCyan',
        // 'bgWhite'];

        let colors = [
        'black',
        'red',
        'green',
        'yellow',
        'blue',
        'magenta',
        'cyan',
        'white'];
        let c = colors[Math.floor(Math.random() * colors.length)];
        return c;
    }

    /**
     * Set the message of this instance.
     *
     * @param {String} message String to output
     * @memberof Message
     * @return {this}
     */
    setMessage (message) {
        if (message) {
            this._message = message;
        }
        return this;
    }

    setLoggerName(name) {
        if(name) {
            this._loggerName = name;
        }
        return this;
    }

    /**
    * @param {boolean|function} timestamp
    * @return {Message}
    */
    setTime (timestamp) {
        if (typeof timestamp === 'function') {
            this._timestamp = timestamp();
        } else if (timestamp) {
            var format = typeof timestamp === 'string' ? timestamp : 'hh:mm:ss';
            this._timestamp = this.dateFormat(format);
        }

        return this;
    }

    /**
    * @param {string|undefined} label
    * @return {Message}
    */
    setLabel (label) {
        if (label) {
            this._label = label;
        }
        return this;
    }

    /**
    * @param {string|undefined} level
    * @return {Message}
    */
    setLevel (level) {
        if (level) {
            this._level = level.toLowerCase();
        }

        return this;
    }

    /**
    * @param {string|undefined} from
    * @return {Message}
    */
    setFrom (from) {
        if (from) {
            this._from = from;
        }
        return this;
    }
    /*
     * eg: format="YYYY-MM-DD hh:mm:ss";
     */
    dateFormat(format) {
        var date = new Date();

        var o = {
            'M+' : date.getMonth()+1,                //month
            'D+' : date.getDate(),                   //day
            'h+' : date.getHours(),                  //hour
            'm+' : date.getMinutes(),                //minute
            's+' : date.getSeconds(),                //second
            'q+' : Math.floor((date.getMonth()+3)/3),//quarter
            'S' : date.getMilliseconds()             //millisecond
        };

        if(/(Y+)/.test(format)) {
            format = format.replace(RegExp.$1, (date.getFullYear()+'').substr(4 - RegExp.$1.length));
        }

        for(var k in o) {
            if(new RegExp('('+ k +')').test(format)) {
                format = format.replace(RegExp.$1, RegExp.$1.length==1 ? o[k] : ('00'+ o[k]).substr((''+ o[k]).length));
            }
        }
        return format;
    }

    padRight(str='', len=5, char=' ') {
        if (str.length >= len) return str;
        return str + Array(len - str.length + 1).join(char);
    }

    padLeft(str='', len=5, char=' ') {
        if (str.length >= len) return str;
        return Array(len - str.length + 1).join(char) + str;
    }

    pad(str='', len=10, char='') {
        if (str.length >= len) return str;
        len = len - str.length;
        let left = Array(Math.ceil(len / 2) + 1).join(char);
        let right = Array(Math.floor(len / 2) + 1).join(char);
        return left + str + right;
    }

    toString() {
        let from = '';
        let after = '';
        let before = '';
        let message = this._message;

        if (this._label) {
            before += `[${this._label}] `;
        }

        let level = this.pad(this._level.toUpperCase() , 8, ' ');
        before += `${level}`;

        before = this.colorify(this._level, before);

        if (this._timestamp) {
            before += `[${this._timestamp}] `;
        }

        if(this._loggerName) {
            let loggername = this.padRight(this._loggerName, 12);
            loggername = this.colorify(loggername, loggername, true);
            before += `├── ${loggername}`;
        }

        before += ' : ';

        if (this._from) {
            from += `${this._from} `;
            after += '- ';
        }
        // let message = this._message;
        if(['error', 'warn'].indexOf(this._level) !== -1) {
            message = this.colorify(this._level + '-msg', message);
        }

        if(this._textStyle) {
            message = this.stylize(message, this._textStyle);
        }

        message = enforceColumnWidth(message, this.columnWidth);

        message = message.join(this.padRight('\n', LN)+' ');

        after += `${message}`;

        return before + from + after;
    }
}

///////
module.exports = Message;
<|endoftext|>


<commit_before>/**
 * In order to test warnings, record console output.
 */

const originals = {}
const messages = {
  log: [],
  warn: [],
  error: []
}

export default {

  record() {
    for (let key in messages) {
      originals[key] = console[key]
      console[key] = (...args) => messages[key].push([args.join(' ')])
    }
  },

  last(key) {
    return messages[key][messages[key].length - 1]
  },

  count(key) {
    if (key in messages === false) {
      throw new Error(`console.${key} is not tracked. Please add it to "${ __filename }."`)
    }

    return messages[key].length
  },

  restore() {
    for (let key in messages) {
      console[key] = originals[key]
      messages[key].length = 0
    }
  }

}
<commit_msg>Remove extraneous test helper<commit_after><|endoftext|>


<commit_before>var SDM = (size = 10000) => {

  }
<commit_msg>Added docs<commit_after>/* Main object type.
 * Parameters:
 *   size: # of "neurons" defaults to 10,000 as that is the commonly accepted place to start in order for the math to work
 */
var SDM = (size = 10000) => {
  this.size = size;
  }
<|endoftext|>


<commit_before>'use strict';

var cluster = require('cluster'),
	async = require('async'),
	os = require('os'),
	swintHelper = require('swint-helper'),
	print = swintHelper.print,
	EventEmitter = require('events').EventEmitter,
	defaultize = swintHelper.defaultize;

module.exports = function(options) {
	defaultize({
		preProcess: function(fork, cb) {
			cb({});
		},
		postProcess: function(fork, sharedData, cb) {
			cb({});
		},
		onExit: function( /* fork */ ) {
		},
		numFork: os.cpus().length,
		operator: null
	}, options);

	return new Fork(options);
};

var Fork = function(options) {
	this.options = options;
	this.sharedData = null;
	this.evt = new EventEmitter();
	this.start();
};

var _ = Fork.prototype;

_.start = function() {
	var that = this;

	if (cluster.isMaster) {
		if (this.options.operator !== null) {
			this.options.operator.start(function() {
				that.startPreProcess();
			});
		} else {
			this.startPreProcess();
		}
	} else if (cluster.isWorker) {
		process.send({
			type: 'ready'
		});
	}

	process.on('message', function(msg) {
		switch (msg.type) {
			case 'control':
				switch (msg.data) {
					case 'healthCheck':
						that.monitor(function(err, res) {
							if (err) {
								print(4, err);
								process.exit(-1);
								return;
							}
							process.emit('controlEnd', null, res);
						});
						break;
					case 'softReset':
						that.resetPost(function(err) {
							if (err) {
								print(4, err);
								process.exit(-1);
								return;
							}
							process.emit('controlEnd');
						});
						break;
					case 'hardReset':
						that.resetAll(function(err) {
							if (err) {
								print(4, err);
								process.exit(-1);
								return;
							}
							process.emit('controlEnd');
						});
						break;
				}
				break;
			case 'data':
				that.options.postProcess(that, msg.data, function() {
					process.send({
						type: 'complete'
					});
				});
				break;
		}
	});
};

_.startPreProcess = function() {
	var that = this,
		numFork = this.options.numFork;

	this.options.preProcess(this, function(sharedData) {
		that.sharedData = sharedData;
		for (var i = 0; i < numFork; i++) {
			that.createWorker(sharedData);
		}
	});

	cluster.on('exit', function(worker) {
		print(2, 'Worker ' + worker.process.pid + ' died');
		that.options.onExit(that);
		that.createWorker(that.sharedData);
	});

	cluster.on('error', function(worker) {
		worker.kill();
	});

	cluster.on('disconnect', function(worker) {
		worker.kill();
	});
};

_.createWorker = function(sharedData) {
	var that = this,
		worker = cluster.fork();

	worker.on('message', function(msg) {
		if (msg.type === 'complete') {
			that.evt.emit('complete');
		} else if (msg.type === 'ready') {
			worker.send({
				type: 'data',
				data: sharedData
			});
		}
	});

	return worker;
};

_.monitor = function(callback) {
	var processes = [];

	for (var id in cluster.workers) {
		var worker = cluster.workers[id];

		processes.push({
			id: id,
			pid: worker.process.pid
		});
	}

	callback(null, processes);
};

_.resetAll = function(callback) {
	var that = this;

	that.options.preProcess(that, function() {
		var workers = [];

		for (var id in cluster.workers) {
			var worker = cluster.workers[id];

			workers.push(worker);
		}

		async.series(
			workers.map(function(v) {
				return function(cb) {
					that.evt.once('complete', function() {
						cb(null, true);
					});
					v.kill();
				};
			}),
			function(err) {
				callback(err, true);
			}
		);
	});
};

_.resetPost = function(callback) {
	var that = this,
		workers = [];

	for (var id in cluster.workers) {
		var worker = cluster.workers[id];

		workers.push(worker);
	}

	async.series(
		workers.map(function(v) {
			return function(cb) {
				that.evt.once('complete', function() {
					cb(null, true);
				});
				v.kill();
			};
		}),
		function(err) {
			callback(err, true);
		}
	);
};

<commit_msg>New: onCreateWorker() option / event added<commit_after>'use strict';

var cluster = require('cluster'),
	async = require('async'),
	os = require('os'),
	swintHelper = require('swint-helper'),
	print = swintHelper.print,
	EventEmitter = require('events').EventEmitter,
	defaultize = swintHelper.defaultize;

module.exports = function(options) {
	defaultize({
		preProcess: function(fork, cb) {
			cb({});
		},
		postProcess: function(fork, sharedData, cb) {
			cb({});
		},
		onCreateWorker: function(fork, worker) {
		},
		onExit: function( /* fork */ ) {
		},
		numFork: os.cpus().length,
		operator: null
	}, options);

	return new Fork(options);
};

var Fork = function(options) {
	this.options = options;
	this.sharedData = null;
	this.evt = new EventEmitter();
	this.start();
};

var _ = Fork.prototype;

_.start = function() {
	var that = this;

	if (cluster.isMaster) {
		if (this.options.operator !== null) {
			this.options.operator.start(function() {
				that.startPreProcess();
			});
		} else {
			this.startPreProcess();
		}
	} else if (cluster.isWorker) {
		process.send({
			type: 'ready'
		});
	}

	process.on('message', function(msg) {
		switch (msg.type) {
			case 'control':
				switch (msg.data) {
					case 'healthCheck':
						that.monitor(function(err, res) {
							if (err) {
								print(4, err);
								process.exit(-1);
								return;
							}
							process.emit('controlEnd', null, res);
						});
						break;
					case 'softReset':
						that.resetPost(function(err) {
							if (err) {
								print(4, err);
								process.exit(-1);
								return;
							}
							process.emit('controlEnd');
						});
						break;
					case 'hardReset':
						that.resetAll(function(err) {
							if (err) {
								print(4, err);
								process.exit(-1);
								return;
							}
							process.emit('controlEnd');
						});
						break;
				}
				break;
			case 'data':
				that.options.postProcess(that, msg.data, function() {
					process.send({
						type: 'complete'
					});
				});
				break;
		}
	});
};

_.startPreProcess = function() {
	var that = this,
		numFork = this.options.numFork;

	this.options.preProcess(this, function(sharedData) {
		that.sharedData = sharedData;
		for (var i = 0; i < numFork; i++) {
			that.createWorker(sharedData);
		}
	});

	cluster.on('exit', function(worker) {
		print(2, 'Worker ' + worker.process.pid + ' died');
		that.options.onExit(that);
		that.createWorker(that.sharedData);
	});

	cluster.on('error', function(worker) {
		worker.kill();
	});

	cluster.on('disconnect', function(worker) {
		worker.kill();
	});
};

_.createWorker = function(sharedData) {
	var that = this,
		worker = cluster.fork();

	worker.on('message', function(msg) {
		if (msg.type === 'complete') {
			that.evt.emit('complete');
		} else if (msg.type === 'ready') {
			worker.send({
				type: 'data',
				data: sharedData
			});
		}
	});

	this.options.onCreateWorker(this, worker);

	return worker;
};

_.monitor = function(callback) {
	var processes = [];

	for (var id in cluster.workers) {
		var worker = cluster.workers[id];

		processes.push({
			id: id,
			pid: worker.process.pid
		});
	}

	callback(null, processes);
};

_.resetAll = function(callback) {
	var that = this;

	that.options.preProcess(that, function() {
		var workers = [];

		for (var id in cluster.workers) {
			var worker = cluster.workers[id];

			workers.push(worker);
		}

		async.series(
			workers.map(function(v) {
				return function(cb) {
					that.evt.once('complete', function() {
						cb(null, true);
					});
					v.kill();
				};
			}),
			function(err) {
				callback(err, true);
			}
		);
	});
};

_.resetPost = function(callback) {
	var that = this,
		workers = [];

	for (var id in cluster.workers) {
		var worker = cluster.workers[id];

		workers.push(worker);
	}

	async.series(
		workers.map(function(v) {
			return function(cb) {
				that.evt.once('complete', function() {
					cb(null, true);
				});
				v.kill();
			};
		}),
		function(err) {
			callback(err, true);
		}
	);
};

<|endoftext|>


<commit_before>(function(){var a={version:"0.2.2"};this.__cache={};this.__escapehtml={__escapehash:{"<":"<",">":">",'"':""","&":"&"},__escapereplace:function(b){return __escapehtml.__escapehash[b];},__escape:function(b){return typeof(b)!=="string"?b:b.replace(/[&<>"]/igm,__escapehtml.__escapereplace);}};a.settings={forstart:/{@each\s*([\w\.]*?)\s*as\s*(\w*?)(,\w*?)?}/igm,forend:/{@\/each}/igm,ifstart:/{@if\s*([^}]*?)}/igm,ifend:/{@\/if}/igm,elsestart:/{@else}/igm,interpolate:/\${([\s\S]+?)}/igm,noneencode:/\$\${([\s\S]+?)}/igm,inlinecomment:/{#[^}]*?}/igm};a.template=function(){var b=this;this.__interpolate=function(d,f){var c=d.split("|"),e="";if(c.length>1){d=c.shift();e=c.shift();}return"<%= "+(f?"__escapehtml.__escape":"")+"("+e+"("+d+")) %>";};this.__shell=function(d,c){var e=0;d=d.replace(a.settings.forstart,function(j,g,i,h){var i=i||"value",h=h&&h.substr(1);var f="i"+e++;return"<% for(var "+f+"=0,l="+g+".length;"+f+"<l;"+f+"++) {var "+i+"="+g+"["+f+"];"+(h?("var "+h+"="+f+";"):"")+" %>";}).replace(a.settings.forend,"<% } %>").replace(a.settings.ifstart,function(f,g){return"<% if("+g+") { %>";}).replace(a.settings.ifend,"<% } %>").replace(a.settings.elsestart,function(f){return"<% } else { %>";}).replace(a.settings.noneencode,function(g,f){return b.__interpolate(f,false);}).replace(a.settings.interpolate,function(g,f){return b.__interpolate(f,true);}).replace(a.settings.inlinecomment,"");if(!c||c.errorhandling!==false){d="<% try { %>"+d+'<% } catch(e) {console.warn("Juicer Render Exception: "+e.message);} %>';}return d;};this.__pure=function(d,c){if(c&&c.loose===true){buf=this.__looseconvert(d);}else{buf=this.__convert(d);}return buf;};this.__convert=function(d){var c=[].join("");c+="var data=data||{};";c+="var out='';out+='";c+=d.replace(/\\/g,"\\\\").replace(/[\r\t\n]/g," ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"';out+=$1;out+='").split("<%").join("';").split("%>").join("out+='")+"';return out;";return c;};this.__looseconvert=function(d){var c=[].join("");c+="var data=data||{};";c+="var p=[];";c+="with(data) {p.push('"+d.replace(/\\/g,"\\\\").replace(/[\r\t\n]/g," ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');};return p.join('');";return c;};this.parse=function(d,c){d=this.__shell(d,c);d=this.__pure(d,c);this.render=new Function("data",d);return this;};};a.compile=function(c,b){try{var d=__cache[c]?__cache[c]:new this.template().parse(c,b);if(!b||b.cache!==false){__cache[c]=d;}return d;}catch(f){console.warn("Juicer Compile Exception: "+f.message);return{render:function(){}};}};a.to_html=function(c,d,b){return this.compile(c,b).render(d);};typeof(module)!=="undefined"&&module.exports?module.exports=a:this.juicer=a;})();<commit_msg>re-minified juicer.js after added detection of undefined.<commit_after>(function(){var a={version:"0.2.2"};this.__cache={};this.__escapehtml={__escapehash:{"<":"<",">":">",'"':""","&":"&"},__escapereplace:function(b){return __escapehtml.__escapehash[b];},__escape:function(b){return typeof(b)!=="string"?__escapehtml.__detection(b):b.replace(/[&<>"]/igm,__escapehtml.__escapereplace);},__detection:function(b){return typeof(b)==="undefined"?"":b;}};a.settings={forstart:/{@each\s*([\w\.]*?)\s*as\s*(\w*?)(,\w*?)?}/igm,forend:/{@\/each}/igm,ifstart:/{@if\s*([^}]*?)}/igm,ifend:/{@\/if}/igm,elsestart:/{@else}/igm,interpolate:/\${([\s\S]+?)}/igm,noneencode:/\$\${([\s\S]+?)}/igm,inlinecomment:/{#[^}]*?}/igm};a.template=function(){var b=this;this.__interpolate=function(d,f){var c=d.split("|"),e="";if(c.length>1){d=c.shift();e=c.shift();}return"<%= "+(f?"__escapehtml.__escape":"__escapehtml.__detection")+"("+e+"("+d+")) %>";};this.__shell=function(d,c){var e=0;d=d.replace(a.settings.forstart,function(j,g,i,h){var i=i||"value",h=h&&h.substr(1);var f="i"+e++;return"<% for(var "+f+"=0,l="+g+".length;"+f+"<l;"+f+"++) {var "+i+"="+g+"["+f+"];"+(h?("var "+h+"="+f+";"):"")+" %>";}).replace(a.settings.forend,"<% } %>").replace(a.settings.ifstart,function(f,g){return"<% if("+g+") { %>";}).replace(a.settings.ifend,"<% } %>").replace(a.settings.elsestart,function(f){return"<% } else { %>";}).replace(a.settings.noneencode,function(g,f){return b.__interpolate(f,false);}).replace(a.settings.interpolate,function(g,f){return b.__interpolate(f,true);}).replace(a.settings.inlinecomment,"");if(!c||c.errorhandling!==false){d="<% try { %>"+d+'<% } catch(e) {console.warn("Juicer Render Exception: "+e.message);} %>';}return d;};this.__pure=function(d,c){if(c&&c.loose===true){buf=this.__looseconvert(d);}else{buf=this.__convert(d);}return buf;};this.__convert=function(d){var c=[].join("");c+="var data=data||{};";c+="var out='';out+='";c+=d.replace(/\\/g,"\\\\").replace(/[\r\t\n]/g," ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"';out+=$1;out+='").split("<%").join("';").split("%>").join("out+='")+"';return out;";return c;};this.__looseconvert=function(d){var c=[].join("");c+="var data=data||{};";c+="var p=[];";c+="with(data) {p.push('"+d.replace(/\\/g,"\\\\").replace(/[\r\t\n]/g," ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');};return p.join('');";return c;};this.parse=function(d,c){d=this.__shell(d,c);d=this.__pure(d,c);this.render=new Function("data",d);return this;};};a.compile=function(c,b){try{var d=__cache[c]?__cache[c]:new this.template().parse(c,b);if(!b||b.cache!==false){__cache[c]=d;}return d;}catch(f){console.warn("Juicer Compile Exception: "+f.message);return{render:function(){}};}};a.to_html=function(c,d,b){return this.compile(c,b).render(d);};typeof(module)!=="undefined"&&module.exports?module.exports=a:this.juicer=a;})();<|endoftext|>