<commit_before>const Canvas = require('canvas');

class CanvasConstructor {

    constructor(width, height) {
        this.canvas = new Canvas(width, height);
        this.context = this.canvas.getContext('2d');

        this.width = width;
        this.height = height;
    }

    /**
     * Restore the context changes.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore
     */
    restore() {
        this.context.restore();
        return this;
    }

    /**
     * Add a rectangle.
     * @param {number} x      The position x to start drawing the element.
     * @param {number} y      The position y to start drawing the element.
     * @param {number} width  The width of the element.
     * @param {number} height The heigth of the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect
     */
    fillRect(x, y, width, height) {
        this.context.fillRect(x, y, width, height);
        return this;
    }

    /**
     * Add a text.
     * @param {string} text The text to write.
     * @param {number} x    The position x to start drawing the element.
     * @param {number} y    The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillText
     */
    addText(text, x, y) {
        this.context.fillText(text, x, y);
        return this;
    }

    /**
     * Add stroked text.
     * @param {string} text The text to write.
     * @param {number} x    The position x to start drawing the element.
     * @param {number} y    The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeText
     */
    addStrokeText(text, x, y) {
        this.context.strokeText(text, x, y);
        return this;
    }

    /**
     * Set a colour for the canvas' context.
     * @param {string} color A canvas' colour resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle
     */
    setStroke(color) {
        this.context.strokeStyle = color;
        return this;
    }

    /**
     * Add an image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {Object} options Options.
     * @param {number} options.radius The radius for the new image.
     * @param {'round'|'bevel'} options.type   The type for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addImage(buffer, x, y, width, height, options = {}) {
        if (options.type) {
            if (options.type === 'round') return this.addRoundImage(buffer, x, y, width, height, options.radius);
            if (options.type === 'bevel') return this.addBevelImage(buffer, x, y, width, height, options.radius);
        }
        const image = new Canvas.Image();
        image.onload = () => this.context.drawImage(image, x, y, width, height);
        image.src = buffer;
        return this;
    }

    /**
     * Add a round image.
     * @param {Buffer} buffer The image's buffer.
     * @param {number} x      The position x to start drawing the element.
     * @param {number} y      The position y to start drawing the element.
     * @param {number} width  The width of the element.
     * @param {number} height The heigth of the element.
     * @param {number} radius The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addRoundImage(buffer, x, y, width, height, radius) {
        this.createRoundClip(x + radius, y + radius, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Add a beveled image.
     * @param {Buffer} buffer The image's buffer.
     * @param {number} x      The position x to start drawing the element.
     * @param {number} y      The position y to start drawing the element.
     * @param {number} width  The width of the element.
     * @param {number} height The heigth of the element.
     * @param {number} radius The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addBevelImage(buffer, x, y, width, height, radius) {
        this.createBeveledClip(x, y, width, height, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Create a round clip.
     * @param {number} x                   The position x in the center of the clip's circle.
     * @param {number} y                   The position y in the center of the clip's circle.
     * @param {number} radius              The radius for the clip.
     * @param {number} [start=0]           The degree in radians to start drawing the circle.
     * @param {number} [angle=Math.PI * 2] The degree in radians to finish drawing the circle, defaults to a full circle.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createRoundClip(x, y, radius, start = 0, angle = Math.PI * 2) {
        this.context.save();
        this.context.beginPath();
        this.context.arc(x, y, radius, start, angle, false);
        this.context.clip();
        return this;
    }

    /**
     * Create a round clip.
     * @param {number} x      The position x to start drawing clip.
     * @param {number} y      The position y to start drawing clip.
     * @param {number} width  The width of clip.
     * @param {number} height The heigth of clip.
     * @param {number} radius The radius for clip's rounded borders.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createBeveledClip(x, y, width, height, radius) {
        if (width > 0 && height > 0) {
            radius = Math.min(radius, width / 2, height / 2);
            this.context.beginPath();
            this.context.moveTo(x + radius, y);
            this.context.lineTo(x + width - radius, y);
            this.context.quadraticCurveTo(x + width, y, x + width, y + radius);
            this.context.lineTo(x + width, y + height - radius);
            this.context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
            this.context.lineTo(x + radius, y + height);
            this.context.quadraticCurveTo(x, y + height, x, y + height - radius);
            this.context.lineTo(x, y + radius);
            this.context.quadraticCurveTo(x, y, x + radius, y);
            this.context.closePath();
            this.context.clip();
        }
        return this;
    }

    /**
     * Register a new font.
     * @param {string} path   The path for the font.
     * @param {string} family The font's family name.
     * @returns {CanvasConstructor}
     * @chainable
     */
    registerTextFont(path, family) {
        Canvas.registerFont(path, { family });
        return this;
    }

    /**
     * Register a new font.
     * @param {string} path   The path for the font.
     * @param {string} family The font's family name.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addTextFont(path, family) {
        this.context.addFont(new Canvas.Font(family, path));
        return this;
    }

    /**
     * Set a colour for the canvas' context.
     * @param {string} color A canvas' colour resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle
     */
    setColor(color) {
        this.context.fillStyle = color;
        return this;
    }

    /**
     * Change the font.
     * @param {string} font The font's name to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font
     */
    setTextFont(font) {
        this.context.font = font;
        return this;
    }

    /**
     * Change the font alignment.
     * @param {('left'|'center'|'right'|'start'|'end')} align The font's alignment to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
     */
    setTextAlign(align) {
        this.context.textAlign = align;
        return this;
    }

    /**
     * Change the font's baseline.
     * @param {('top'|'hanging'|'middle'|'alphabetic'|'ideographic'|'bottom')} baseline The font's baseline to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline
     */
    setTextBaseline(baseline) {
        this.context.textBaseline = baseline;
        return this;
    }

    /**
     * Set the shadow's blur.
     * @param {number} radius The shadow's blur radius to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowBlur
     */
    setShadowBlur(radius) {
        this.context.shadowBlur = radius;
        return this;
    }

    /**
     * Set the shadow's colour.
     * @param {string} colour A canvas' colour resolvable to set as shadow's colour.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor
     */
    setShadowColour(colour) {
        this.context.shadowColor = colour;
        return this;
    }

    /**
     * Set the property that specifies the distance that the shadow will be offset in horizontal distance.
     * @param {number} value The value in pixels for the distance.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetX
     */
    setShadowOffsetX(value) {
        this.context.shadowOffsetX = value;
        return this;
    }

    /**
     * Set the property that specifies the distance that the shadow will be offset in vertical distance.
     * @param {number} value The value in pixels for the distance.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetY
     */
    setShadowOffsetY(value) {
        this.context.shadowOffsetY = value;
        return this;
    }

    /**
     * Modify the alpha value that is applied to shapes and images before they are drawn into the canvas.
     * @param {number} value The alpha value, from 0.0 (fully transparent) to 1.0 (fully opaque)
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha
     */
    setGlobalAlpha(value) {
        this.context.globalAlpha(value);
        return this;
    }

    /**
     * Reset the canvas' shadows.
     * @returns {CanvasConstructor}
     * @chainable
     */
    resetShadows() {
        return this
            .setShadowBlur(0)
            .setShadowColour('#000000');
    }

    /**
     * Clear a circle.
     * @param {number} x                   The position x in the center of the clip's circle.
     * @param {number} y                   The position y in the center of the clip's circle.
     * @param {number} radius              The radius for the clip.
     * @param {number} [start=0]           The degree in radians to start drawing the circle.
     * @param {number} [angle=Math.PI * 2] The degree in radians to finish drawing the circle, defaults to a full circle.
     * @returns {CanvasConstructor}
     * @chainable
     */
    clearCircle(x, y, radius, start = 0, angle = Math.PI * 2) {
        return this
            .createRoundClip(x, y, radius, start, angle)
            .clearPixels(x - radius, y - radius, radius * 2, radius * 2);
    }

    /**
     * Clear an area.
     * @param {number} [x=0]                The position x to start drawing the element.
     * @param {number} [y=0]                The position y to start drawing the element.
     * @param {number} [width=this.width]   The width of the element.
     * @param {number} [height=this.heigth] The heigth of the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clearRect
     */
    clearPixels(x = 0, y = 0, width = this.width, height = this.height) {
        this.context.clearRect(x, y, width, height);
        return this;
    }

    /**
     * Render the canvas into a buffer.
     * @param {Object} options The render's options.
     * @returns {Buffer}
     */
    toBuffer(options) {
        return this.canvas.toBuffer(options);
    }

}

module.exports = CanvasConstructor;<commit_msg>Change all colour to color<commit_after>const Canvas = require('canvas');

class CanvasConstructor {

    constructor(width, height) {
        this.canvas = new Canvas(width, height);
        this.context = this.canvas.getContext('2d');

        this.width = width;
        this.height = height;
    }

    /**
     * Restore the context changes.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore
     */
    restore() {
        this.context.restore();
        return this;
    }

    /**
     * Add a rectangle.
     * @param {number} x      The position x to start drawing the element.
     * @param {number} y      The position y to start drawing the element.
     * @param {number} width  The width of the element.
     * @param {number} height The heigth of the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect
     */
    fillRect(x, y, width, height) {
        this.context.fillRect(x, y, width, height);
        return this;
    }

    /**
     * Add a text.
     * @param {string} text The text to write.
     * @param {number} x    The position x to start drawing the element.
     * @param {number} y    The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillText
     */
    addText(text, x, y) {
        this.context.fillText(text, x, y);
        return this;
    }

    /**
     * Add stroked text.
     * @param {string} text The text to write.
     * @param {number} x    The position x to start drawing the element.
     * @param {number} y    The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeText
     */
    addStrokeText(text, x, y) {
        this.context.strokeText(text, x, y);
        return this;
    }

    /**
     * Set a color for the canvas' context.
     * @param {string} color A canvas' color resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle
     */
    setStroke(color) {
        this.context.strokeStyle = color;
        return this;
    }

    /**
     * Add an image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {Object} options Options.
     * @param {number} options.radius The radius for the new image.
     * @param {'round'|'bevel'} options.type   The type for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addImage(buffer, x, y, width, height, options = {}) {
        if (options.type) {
            if (options.type === 'round') return this.addRoundImage(buffer, x, y, width, height, options.radius);
            if (options.type === 'bevel') return this.addBevelImage(buffer, x, y, width, height, options.radius);
        }
        const image = new Canvas.Image();
        image.onload = () => this.context.drawImage(image, x, y, width, height);
        image.src = buffer;
        return this;
    }

    /**
     * Add a round image.
     * @param {Buffer} buffer The image's buffer.
     * @param {number} x      The position x to start drawing the element.
     * @param {number} y      The position y to start drawing the element.
     * @param {number} width  The width of the element.
     * @param {number} height The heigth of the element.
     * @param {number} radius The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addRoundImage(buffer, x, y, width, height, radius) {
        this.createRoundClip(x + radius, y + radius, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Add a beveled image.
     * @param {Buffer} buffer The image's buffer.
     * @param {number} x      The position x to start drawing the element.
     * @param {number} y      The position y to start drawing the element.
     * @param {number} width  The width of the element.
     * @param {number} height The heigth of the element.
     * @param {number} radius The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addBevelImage(buffer, x, y, width, height, radius) {
        this.createBeveledClip(x, y, width, height, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Create a round clip.
     * @param {number} x                   The position x in the center of the clip's circle.
     * @param {number} y                   The position y in the center of the clip's circle.
     * @param {number} radius              The radius for the clip.
     * @param {number} [start=0]           The degree in radians to start drawing the circle.
     * @param {number} [angle=Math.PI * 2] The degree in radians to finish drawing the circle, defaults to a full circle.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createRoundClip(x, y, radius, start = 0, angle = Math.PI * 2) {
        this.context.save();
        this.context.beginPath();
        this.context.arc(x, y, radius, start, angle, false);
        this.context.clip();
        return this;
    }

    /**
     * Create a round clip.
     * @param {number} x      The position x to start drawing clip.
     * @param {number} y      The position y to start drawing clip.
     * @param {number} width  The width of clip.
     * @param {number} height The heigth of clip.
     * @param {number} radius The radius for clip's rounded borders.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createBeveledClip(x, y, width, height, radius) {
        if (width > 0 && height > 0) {
            radius = Math.min(radius, width / 2, height / 2);
            this.context.beginPath();
            this.context.moveTo(x + radius, y);
            this.context.lineTo(x + width - radius, y);
            this.context.quadraticCurveTo(x + width, y, x + width, y + radius);
            this.context.lineTo(x + width, y + height - radius);
            this.context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
            this.context.lineTo(x + radius, y + height);
            this.context.quadraticCurveTo(x, y + height, x, y + height - radius);
            this.context.lineTo(x, y + radius);
            this.context.quadraticCurveTo(x, y, x + radius, y);
            this.context.closePath();
            this.context.clip();
        }
        return this;
    }

    /**
     * Register a new font.
     * @param {string} path   The path for the font.
     * @param {string} family The font's family name.
     * @returns {CanvasConstructor}
     * @chainable
     */
    registerTextFont(path, family) {
        Canvas.registerFont(path, { family });
        return this;
    }

    /**
     * Register a new font.
     * @param {string} path   The path for the font.
     * @param {string} family The font's family name.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addTextFont(path, family) {
        this.context.addFont(new Canvas.Font(family, path));
        return this;
    }

    /**
     * Set a color for the canvas' context.
     * @param {string} color A canvas' color resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle
     */
    setColor(color) {
        this.context.fillStyle = color;
        return this;
    }

    /**
     * Change the font.
     * @param {string} font The font's name to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font
     */
    setTextFont(font) {
        this.context.font = font;
        return this;
    }

    /**
     * Change the font alignment.
     * @param {('left'|'center'|'right'|'start'|'end')} align The font's alignment to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign
     */
    setTextAlign(align) {
        this.context.textAlign = align;
        return this;
    }

    /**
     * Change the font's baseline.
     * @param {('top'|'hanging'|'middle'|'alphabetic'|'ideographic'|'bottom')} baseline The font's baseline to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textBaseline
     */
    setTextBaseline(baseline) {
        this.context.textBaseline = baseline;
        return this;
    }

    /**
     * Set the shadow's blur.
     * @param {number} radius The shadow's blur radius to set.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowBlur
     */
    setShadowBlur(radius) {
        this.context.shadowBlur = radius;
        return this;
    }

    /**
     * Set the shadow's color.
     * @param {string} color A canvas' color resolvable to set as shadow's color.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor
     */
    setShadowColor(color) {
        this.context.shadowColor = color;
        return this;
    }

    /**
     * Set the property that specifies the distance that the shadow will be offset in horizontal distance.
     * @param {number} value The value in pixels for the distance.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetX
     */
    setShadowOffsetX(value) {
        this.context.shadowOffsetX = value;
        return this;
    }

    /**
     * Set the property that specifies the distance that the shadow will be offset in vertical distance.
     * @param {number} value The value in pixels for the distance.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetY
     */
    setShadowOffsetY(value) {
        this.context.shadowOffsetY = value;
        return this;
    }

    /**
     * Modify the alpha value that is applied to shapes and images before they are drawn into the canvas.
     * @param {number} value The alpha value, from 0.0 (fully transparent) to 1.0 (fully opaque)
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha
     */
    setGlobalAlpha(value) {
        this.context.globalAlpha(value);
        return this;
    }

    /**
     * Reset the canvas' shadows.
     * @returns {CanvasConstructor}
     * @chainable
     */
    resetShadows() {
        return this
            .setShadowBlur(0)
            .setShadowColor('#000000');
    }

    /**
     * Clear a circle.
     * @param {number} x                   The position x in the center of the clip's circle.
     * @param {number} y                   The position y in the center of the clip's circle.
     * @param {number} radius              The radius for the clip.
     * @param {number} [start=0]           The degree in radians to start drawing the circle.
     * @param {number} [angle=Math.PI * 2] The degree in radians to finish drawing the circle, defaults to a full circle.
     * @returns {CanvasConstructor}
     * @chainable
     */
    clearCircle(x, y, radius, start = 0, angle = Math.PI * 2) {
        return this
            .createRoundClip(x, y, radius, start, angle)
            .clearPixels(x - radius, y - radius, radius * 2, radius * 2);
    }

    /**
     * Clear an area.
     * @param {number} [x=0]                The position x to start drawing the element.
     * @param {number} [y=0]                The position y to start drawing the element.
     * @param {number} [width=this.width]   The width of the element.
     * @param {number} [height=this.heigth] The heigth of the element.
     * @returns {CanvasConstructor}
     * @chainable
     * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clearRect
     */
    clearPixels(x = 0, y = 0, width = this.width, height = this.height) {
        this.context.clearRect(x, y, width, height);
        return this;
    }

    /**
     * Render the canvas into a buffer.
     * @param {Object} options The render's options.
     * @returns {Buffer}
     */
    toBuffer(options) {
        return this.canvas.toBuffer(options);
    }

}

module.exports = CanvasConstructor;<|endoftext|>


<commit_before>const Canvas = require('canvas');

class CanvasConstructor {

    constructor(width, height) {
        this.canvas = new Canvas(width, height);
        this.context = this.canvas.getContext('2d');
    }

    /**
     * Restore the context changes.
     * @returns {CanvasConstructor}
     * @chainable
     */
    restore() {
        this.context.restore();
        return this;
    }

    /**
     * Add a rectangle.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @returns {CanvasConstructor}
     * @chainable
     */
    fillRect(x, y, width, height) {
        this.context.fillRect(x, y, width, height);
        return this;
    }

    /**
     * Add a text.
     * @param {string} text    The text to write.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addText(text, x, y) {
        this.context.fillText(text, x, y);
        return this;
    }

    /**
     * Add stroked text.
     * @param {string} text    The text to write.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addStrokeText(text, x, y) {
        this.context.strokeText(text, x, y);
        return this;
    }

    /**
     * Set a colour for the canvas' context.
     * @param {string} color A canvas' colour resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setStroke(color) {
        this.context.strokeStyle = color;
        return this;
    }

    /**
     * Add an image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {Object} options Options.
     * @param {number} options.radius The radius for the new image.
     * @param {'round'|'bevel'} options.type   The type for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addImage(buffer, x, y, width, height, options = {}) {
        if (options.type !== null) {
            if (options.type === 'round') return this.addRoundImage(buffer, x, y, width, height, options.radius);
            if (options.type === 'bevel') return this.addBevelImage(buffer, x, y, width, height, options.radius);
        }
        const image = new Canvas.Image();
        image.onload = () => this.context.drawImage(image, x, y, width, height);
        image.src = buffer;
        return this;
    }

    /**
     * Add a round image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {number} radius  The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addRoundImage(buffer, x, y, width, height, radius) {
        this.createRoundClip(x + radius, y + radius, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Add a beveled image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {number} radius  The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addBevelImage(buffer, x, y, width, height, radius) {
        this.createBeveledClip(x, y, width, height, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Create a round clip.
     * @param {number} x       The position x in the center of the clip's circle.
     * @param {number} y       The position y in the center of the clip's circle.
     * @param {number} radius  The radius for the clip.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createRoundClip(x, y, radius) {
        this.context.save();
        this.context.beginPath();
        this.context.arc(x, y, radius, 0, Math.PI * 2, false);
        this.context.clip();
        return this;
    }

    /**
     * Create a round clip.
     * @param {number} x       The position x to start drawing clip.
     * @param {number} y       The position y to start drawing clip.
     * @param {number} width   The width of clip.
     * @param {number} height  The heigth of clip.
     * @param {number} radius  The radius for clip's rounded borders.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createBeveledClip(x, y, width, height, radius) {
        if (width > 0 && height > 0) {
            radius = Math.min(radius, width / 2, height / 2);
            this.context.beginPath();
            this.context.moveTo(x + radius, y);
            this.context.lineTo(x + width - radius, y);
            this.context.quadraticCurveTo(x + width, y, x + width, y + radius);
            this.context.lineTo(x + width, y + height - radius);
            this.context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
            this.context.lineTo(x + radius, y + height);
            this.context.quadraticCurveTo(x, y + height, x, y + height - radius);
            this.context.lineTo(x, y + radius);
            this.context.quadraticCurveTo(x, y, x + radius, y);
            this.context.closePath();
            this.context.clip();
        }
        return this;
    }

    /**
     * Register a new font.
     * @param {string} path The path for the font.
     * @param {string} family The font's family name.
     * @returns {CanvasConstructor}
     * @chainable
     */
    registerTextFont(path, family) {
        Canvas.registerFont(path, { family });
        return this;
    }

    /**
     * Set a colour for the canvas' context.
     * @param {string} color A canvas' colour resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setColor(color) {
        this.context.fillStyle = color;
        return this;
    }

    /**
     * Change the font.
     * @param {string} font The font's name to set.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setTextFont(font) {
        this.context.font = font;
        return this;
    }

    /**
     * Change the font alignment.
     * @param {('left'|'center'|'right'|'justified')} align The font's alignment to set.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setTextAlign(align) {
        this.context.textAlign = align;
        return this;
    }

    /**
     * Set the shadow's blur.
     * @param {number} radius The shadow's blur radius to set.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setShadowBlur(radius) {
        this.context.shadowBlur = radius;
        return this;
    }

    /**
     * Set the shadow's colour.
     * @param {string} colour A canvas' colour resolvable to set as shadow's colour.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setShadowColour(colour) {
        this.context.shadowColor = colour;
        return this;
    }

    /**
     * Reset the canvas' shadows.
     * @returns {CanvasConstructor}
     * @chainable
     */
    resetShadows() {
        return this.setShadowBlur(0).setShadowColour('#000000');
    }

    /**
     * Render the canvas into a buffer.
     * @param {Object} options The render's options.
     * @returns {Buffer}
     */
    toBuffer(options) {
        return this.canvas.toBuffer(options);
    }

}

module.exports = CanvasConstructor;
<commit_msg>Added addFont method<commit_after>const Canvas = require('canvas');

class CanvasConstructor {

    constructor(width, height) {
        this.canvas = new Canvas(width, height);
        this.context = this.canvas.getContext('2d');
    }

    /**
     * Restore the context changes.
     * @returns {CanvasConstructor}
     * @chainable
     */
    restore() {
        this.context.restore();
        return this;
    }

    /**
     * Add a rectangle.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @returns {CanvasConstructor}
     * @chainable
     */
    fillRect(x, y, width, height) {
        this.context.fillRect(x, y, width, height);
        return this;
    }

    /**
     * Add a text.
     * @param {string} text    The text to write.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addText(text, x, y) {
        this.context.fillText(text, x, y);
        return this;
    }

    /**
     * Add stroked text.
     * @param {string} text    The text to write.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addStrokeText(text, x, y) {
        this.context.strokeText(text, x, y);
        return this;
    }

    /**
     * Set a colour for the canvas' context.
     * @param {string} color A canvas' colour resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setStroke(color) {
        this.context.strokeStyle = color;
        return this;
    }

    /**
     * Add an image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {Object} options Options.
     * @param {number} options.radius The radius for the new image.
     * @param {'round'|'bevel'} options.type   The type for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addImage(buffer, x, y, width, height, options = {}) {
        if (options.type !== null) {
            if (options.type === 'round') return this.addRoundImage(buffer, x, y, width, height, options.radius);
            if (options.type === 'bevel') return this.addBevelImage(buffer, x, y, width, height, options.radius);
        }
        const image = new Canvas.Image();
        image.onload = () => this.context.drawImage(image, x, y, width, height);
        image.src = buffer;
        return this;
    }

    /**
     * Add a round image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {number} radius  The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addRoundImage(buffer, x, y, width, height, radius) {
        this.createRoundClip(x + radius, y + radius, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Add a beveled image.
     * @param {Buffer} buffer  The image's buffer.
     * @param {number} x       The position x to start drawing the element.
     * @param {number} y       The position y to start drawing the element.
     * @param {number} width   The width of the element.
     * @param {number} height  The heigth of the element.
     * @param {number} radius  The radius for the new image.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addBevelImage(buffer, x, y, width, height, radius) {
        this.createBeveledClip(x, y, width, height, radius);
        return this.addImage(buffer, x, y, width, height, radius, { type: null });
    }

    /**
     * Create a round clip.
     * @param {number} x       The position x in the center of the clip's circle.
     * @param {number} y       The position y in the center of the clip's circle.
     * @param {number} radius  The radius for the clip.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createRoundClip(x, y, radius) {
        this.context.save();
        this.context.beginPath();
        this.context.arc(x, y, radius, 0, Math.PI * 2, false);
        this.context.clip();
        return this;
    }

    /**
     * Create a round clip.
     * @param {number} x       The position x to start drawing clip.
     * @param {number} y       The position y to start drawing clip.
     * @param {number} width   The width of clip.
     * @param {number} height  The heigth of clip.
     * @param {number} radius  The radius for clip's rounded borders.
     * @returns {CanvasConstructor}
     * @chainable
     */
    createBeveledClip(x, y, width, height, radius) {
        if (width > 0 && height > 0) {
            radius = Math.min(radius, width / 2, height / 2);
            this.context.beginPath();
            this.context.moveTo(x + radius, y);
            this.context.lineTo(x + width - radius, y);
            this.context.quadraticCurveTo(x + width, y, x + width, y + radius);
            this.context.lineTo(x + width, y + height - radius);
            this.context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
            this.context.lineTo(x + radius, y + height);
            this.context.quadraticCurveTo(x, y + height, x, y + height - radius);
            this.context.lineTo(x, y + radius);
            this.context.quadraticCurveTo(x, y, x + radius, y);
            this.context.closePath();
            this.context.clip();
        }
        return this;
    }

    /**
     * Register a new font.
     * @param {string} path The path for the font.
     * @param {string} family The font's family name.
     * @returns {CanvasConstructor}
     * @chainable
     */
    registerTextFont(path, family) {
        Canvas.registerFont(path, { family });
        return this;
    }

    /**
     * Register a new font.
     * @param {string} path The path for the font.
     * @param {string} family The font's family name.
     * @returns {CanvasConstructor}
     * @chainable
     */
    addTextFont(path, family) {
        this.context.addFont(new Canvas.Font(family, path));
        return this;
    }

    /**
     * Set a colour for the canvas' context.
     * @param {string} color A canvas' colour resolvable.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setColor(color) {
        this.context.fillStyle = color;
        return this;
    }

    /**
     * Change the font.
     * @param {string} font The font's name to set.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setTextFont(font) {
        this.context.font = font;
        return this;
    }

    /**
     * Change the font alignment.
     * @param {('left'|'center'|'right'|'justified')} align The font's alignment to set.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setTextAlign(align) {
        this.context.textAlign = align;
        return this;
    }

    /**
     * Set the shadow's blur.
     * @param {number} radius The shadow's blur radius to set.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setShadowBlur(radius) {
        this.context.shadowBlur = radius;
        return this;
    }

    /**
     * Set the shadow's colour.
     * @param {string} colour A canvas' colour resolvable to set as shadow's colour.
     * @returns {CanvasConstructor}
     * @chainable
     */
    setShadowColour(colour) {
        this.context.shadowColor = colour;
        return this;
    }

    /**
     * Reset the canvas' shadows.
     * @returns {CanvasConstructor}
     * @chainable
     */
    resetShadows() {
        return this.setShadowBlur(0).setShadowColour('#000000');
    }

    /**
     * Render the canvas into a buffer.
     * @param {Object} options The render's options.
     * @returns {Buffer}
     */
    toBuffer(options) {
        return this.canvas.toBuffer(options);
    }

}

module.exports = CanvasConstructor;
<|endoftext|>


<commit_before>/******************************************************************************
 *                                  ~cassie~                                  *
 *                                ‾‾‾‾‾‾‾‾‾‾‾‾                                *
 * Simple future library for JS. Ready to be violently raped by Ajax!         *
 *     _________________________________________________________________      *
 *        Copyright (c) 2011 Quildreen Motta // Licenced under MIT/X11        *
 ******************************************************************************/

//// Module Cassie /////////////////////////////////////////////////////////////
//
// Cassie (short for lil' Cassandra) is a deliciously short future
// library for JavaScript. It provides a simple Promise object that can
// be used as the return value of any asynchronous call.
//
// The idea behind promises is that you can manipulate the return value
// of an asynchronous function before the function has been
// resolved. This allows you to write in a clear chaining DSL rather
// than using a clusterfuck of callbacks.
//
// Take an Ajax request, for example. The usual way::
//
//     var req = ajax.get('data.json'
//               , function (resp) { /* success */
//                   req.update('#data', JSON.parse(resp.responseText))
//               }
//               , function (resp) { /* fail */
//                   req.show_error()
//               })
//     setTimeout(req.fail, 10000)
//
// With promises, you could get this::
//
//     var req = ajax.get('data.json')
//                   .ok().update('#data')
//                   .failed().show_error()
//                   .timeout(10)
//
// You can pass this ``req`` object around, and other functions can add
// their own manipulations to the object as well::
//
//     function log_it(req) {
//         return req.ok(log('success'))
//                   .failed(log('failed'))
//                   .clear_timer() /* disables the timeout */
//     }
//     var req = log_it(ajax.get('data.json').timeout(10))
//

'@cassie',
function (root) {
    if (typeof exports == 'undefined') {
        old    = root.cassie
        cassie = root.cassie = root.cassie || {}
        cassie.clean = function() {
            root.cassie = old
            return cassie
        }}
    else
        cassie = exports

    var cassie, old
      , slice = Array.prototype.slice

      // Constants with values for errors
      , forgotten = {}
      , timeouted = {}

    ///// Object Promise ///////////////////////////////////////////////////////
    //
    // Creates a deferred object, that can be manipulated before the
    // value is actually resolved. As soon as it is fulfilled, this
    // promise will apply the pending actions.
    //
    // You can either return the promise directly, or take full
    // advantage of it by inheriting the ``Promise``'s prototoype and
    // adding your own custom methods.
    //
    function Promise () {
        this.callbacks   = {}
        this.flush_queue = []
        this.value       = null
        this.timer       = null
        this.defaultev   = 'done'
    }
    Promise.prototype = function() {
        return { add:         add
               , flush:       flush
               , done:        done
               , bind:        bind
               , fail:        fail
               , timeout:     timeout
               , clear_timer: clear_timer
               , forget:      forget

               // Shortcuts for add(event[, callback])
               , ok:          ok
               , failed:      failed
               , timeouted:   _timeouted
               , forgotten:   _forgotten }

        ////// Function add_callback ///////////////////////////////////////////
        // ::
        //     add_callback(Obj promise, Str event, Fn callback) → Fn
        //
        // Adds a callback to a ``Promise``.
        //
        // The callback will be called whenever the given event happens
        // within the given promise, in the context of the promise (ie.:
        // ``this`` inside the callback will refer to the given promise)
        // and the arguments provided when the promise was fulfilled.
        //
        // Returns the given callback function.
        //
        function add_callback(promise, event, callback) {
            get_queue(promise, event).push(callback)
            return callback
        }

        function get_queue(promise, event) {
            return promise.callbacks[event]
                || (promise.callbacks[event] = [])
        }

        ////// Method add //////////////////////////////////////////////////////
        // ::
        //     add(Str event[, Fn callback]) → Promise
        //
        // Adds a callback to the ``Promise``.
        //
        // Passing a callback directly to the add method is optional, to
        // leverage more specialized promises, Cassie supports defining
        // a default event to which callbacks are bound.
        //
        // For example, instead of writting the following::
        //
        //     promise.add('ok', foo).add('ok', bar)
        //
        // You could go with::
        //
        //     promise.add('ok').foo().bar()
        //
        // Of course, given you have a specialized promise implementing
        // `foo` and `bar`.
        //
        // The default event persists until another `add` call with an
        // explicit event is issued.
        //
        // See :fn:`add_callback` for more information.
        //
        function add(event, callback) {
            if (typeof event == 'function') {
                callback = event
                event    = this.defaultev }

            _add(this, event, callback)
            return this
        }

        function _add(promise, event, callback) {
            promise.defaultev = event
            if (promise.value)
                fire(promise, event, callback)
            else
                callback && add_callback(promise, event, callback)
        }

        function fire(promise, event, callback) {
            var queue = get_queue(promise, event)
            if (callback && queue.flushed)
                return callback.apply(promise, promise.value)
        }

        ////// Method flush ////////////////////////////////////////////////////
        // ::
        //     flush(Str event) → Promise
        //
        // Calls all callbacks associated with the given event.
        //
        // The callbacks are called in the context of this ``Promise``
        // (ie.: ``this`` inside such callback will refer to this
        // ``Promise``), and with any arguments that have been passed to
        // the promise when it was fulfilled.
        //
        function flush(event) {
            if (!this.value)
                event && this.flush_queue.push(event)
            else while (event = this.flush_queue.shift())
                flush_ev(this, event)

            return this
        }

        function flush_ev(promise, event) {
            var callbacks = promise.callbacks[event] || []
              , current

            while (current = callbacks.shift())
                current.apply(promise, promise.value)

            callbacks.flushed = true
        }

        ////// Method done /////////////////////////////////////////////////////
        // ::
        //     done(ArrayLike values) → Promise
        //
        // Resolves the promise to the given values and call the
        // callbacks defined for ``done``.
        //
        // The given value array is cloned, then assigned to the
        // promise. This makes it easier for caller functions to just
        // pass the ``arguments`` object straight up to this function.
        //
        // If the promise has already been resolved, this method is a
        // noop.
        //
        function done(values) {
            if (!this.value) {
                this.clear_timer().flush('done')
                this.value = slice.call(values)
                this.flush() }
            return this
        }

        ////// Method fail /////////////////////////////////////////////////////
        // ::
        //     fail(Obj error) → Promise
        //
        // Fails to fulfill the promise, and calls all the ``fail``
        // callbacks passing the error as parameter.
        //
        // See :fn:`done` for more information.
        //
        function fail() {
            return this.flush('fail').done(arguments)
        }

        ////// Method bind /////////////////////////////////////////////////////
        // ::
        //     bind(values...) → Promise
        //
        // Successfully fulfills the promise, and calls the ``bind``
        // callbacks passing the values as parameter.
        //
        // See :fn:`resolve` for more information.
        //
        function bind() {
            return this.flush('ok').done(arguments)
        }

        ////// Method timeout //////////////////////////////////////////////////
        // ::
        //     timeout(Num delay) → Promise
        //
        // Fails to fulfill the promise after the given number of
        // seconds.
        //
        // The promise fails with the value of ``timeouted``.
        //
        function timeout(delay) {
            var promise = this
            this.timer = setTimeout(function(){
                promise.flush('timeouted')
                       .fail(timeouted)
            }, delay * 1000)
            return this
        }

        ////// Method clear_timer //////////////////////////////////////////////
        // ::
        //     clear_timer() → Promise
        //
        // Clears any timer that may exist for this promise.
        //
        function clear_timer() {
            clearTimeout(this.timer)
            return this
        }

        ////// Method forget ///////////////////////////////////////////////////
        // ::
        //     forget() → Promise
        //
        // Cancels the promise, and fails with the value of ``forgotten``.
        //
        function forget() {
            return this.flush('forgotten').fail(forgotten)
        }

        ////// -Shortcuts for add(event[, callback]) //////////////////////////
        function ok(fn)         { return this.add('ok',        fn) }
        function failed(fn)     { return this.add('fail',      fn) }
        function _timeouted(fn) { return this.add('timeouted', fn) }
        function _forgotten(fn) { return this.add('forgotten', fn) }
    }()

    ///// Exṕorts //////////////////////////////////////////////////////////////
    cassie.Promise      = Promise
    cassie.forgotten    = forgotten
    cassie.timeouted    = timeouted
}(this)<commit_msg>Always overwrites the old global cassie (when CommonJS is not available).<commit_after>/******************************************************************************
 *                                  ~cassie~                                  *
 *                                ‾‾‾‾‾‾‾‾‾‾‾‾                                *
 * Simple future library for JS. Ready to be violently raped by Ajax!         *
 *     _________________________________________________________________      *
 *        Copyright (c) 2011 Quildreen Motta // Licenced under MIT/X11        *
 ******************************************************************************/

//// Module Cassie /////////////////////////////////////////////////////////////
//
// Cassie (short for lil' Cassandra) is a deliciously short future
// library for JavaScript. It provides a simple Promise object that can
// be used as the return value of any asynchronous call.
//
// The idea behind promises is that you can manipulate the return value
// of an asynchronous function before the function has been
// resolved. This allows you to write in a clear chaining DSL rather
// than using a clusterfuck of callbacks.
//
// Take an Ajax request, for example. The usual way::
//
//     var req = ajax.get('data.json'
//               , function (resp) { /* success */
//                   req.update('#data', JSON.parse(resp.responseText))
//               }
//               , function (resp) { /* fail */
//                   req.show_error()
//               })
//     setTimeout(req.fail, 10000)
//
// With promises, you could get this::
//
//     var req = ajax.get('data.json')
//                   .ok().update('#data')
//                   .failed().show_error()
//                   .timeout(10)
//
// You can pass this ``req`` object around, and other functions can add
// their own manipulations to the object as well::
//
//     function log_it(req) {
//         return req.ok(log('success'))
//                   .failed(log('failed'))
//                   .clear_timer() /* disables the timeout */
//     }
//     var req = log_it(ajax.get('data.json').timeout(10))
//

'@cassie',
function (root) {
    if (typeof exports == 'undefined') {
        old    = root.cassie
        cassie = root.cassie = {}
        cassie.clean = function() {
            root.cassie = old
            return cassie
        }}
    else
        cassie = exports

    var cassie, old
      , slice = Array.prototype.slice

      // Constants with values for errors
      , forgotten = {}
      , timeouted = {}

    ///// Object Promise ///////////////////////////////////////////////////////
    //
    // Creates a deferred object, that can be manipulated before the
    // value is actually resolved. As soon as it is fulfilled, this
    // promise will apply the pending actions.
    //
    // You can either return the promise directly, or take full
    // advantage of it by inheriting the ``Promise``'s prototoype and
    // adding your own custom methods.
    //
    function Promise () {
        this.callbacks   = {}
        this.flush_queue = []
        this.value       = null
        this.timer       = null
        this.defaultev   = 'done'
    }
    Promise.prototype = function() {
        return { add:         add
               , flush:       flush
               , done:        done
               , bind:        bind
               , fail:        fail
               , timeout:     timeout
               , clear_timer: clear_timer
               , forget:      forget

               // Shortcuts for add(event[, callback])
               , ok:          ok
               , failed:      failed
               , timeouted:   _timeouted
               , forgotten:   _forgotten }

        ////// Function add_callback ///////////////////////////////////////////
        // ::
        //     add_callback(Obj promise, Str event, Fn callback) → Fn
        //
        // Adds a callback to a ``Promise``.
        //
        // The callback will be called whenever the given event happens
        // within the given promise, in the context of the promise (ie.:
        // ``this`` inside the callback will refer to the given promise)
        // and the arguments provided when the promise was fulfilled.
        //
        // Returns the given callback function.
        //
        function add_callback(promise, event, callback) {
            get_queue(promise, event).push(callback)
            return callback
        }

        function get_queue(promise, event) {
            return promise.callbacks[event]
                || (promise.callbacks[event] = [])
        }

        ////// Method add //////////////////////////////////////////////////////
        // ::
        //     add(Str event[, Fn callback]) → Promise
        //
        // Adds a callback to the ``Promise``.
        //
        // Passing a callback directly to the add method is optional, to
        // leverage more specialized promises, Cassie supports defining
        // a default event to which callbacks are bound.
        //
        // For example, instead of writting the following::
        //
        //     promise.add('ok', foo).add('ok', bar)
        //
        // You could go with::
        //
        //     promise.add('ok').foo().bar()
        //
        // Of course, given you have a specialized promise implementing
        // `foo` and `bar`.
        //
        // The default event persists until another `add` call with an
        // explicit event is issued.
        //
        // See :fn:`add_callback` for more information.
        //
        function add(event, callback) {
            if (typeof event == 'function') {
                callback = event
                event    = this.defaultev }

            _add(this, event, callback)
            return this
        }

        function _add(promise, event, callback) {
            promise.defaultev = event
            if (promise.value)
                fire(promise, event, callback)
            else
                callback && add_callback(promise, event, callback)
        }

        function fire(promise, event, callback) {
            var queue = get_queue(promise, event)
            if (callback && queue.flushed)
                return callback.apply(promise, promise.value)
        }

        ////// Method flush ////////////////////////////////////////////////////
        // ::
        //     flush(Str event) → Promise
        //
        // Calls all callbacks associated with the given event.
        //
        // The callbacks are called in the context of this ``Promise``
        // (ie.: ``this`` inside such callback will refer to this
        // ``Promise``), and with any arguments that have been passed to
        // the promise when it was fulfilled.
        //
        function flush(event) {
            if (!this.value)
                event && this.flush_queue.push(event)
            else while (event = this.flush_queue.shift())
                flush_ev(this, event)

            return this
        }

        function flush_ev(promise, event) {
            var callbacks = promise.callbacks[event] || []
              , current

            while (current = callbacks.shift())
                current.apply(promise, promise.value)

            callbacks.flushed = true
        }

        ////// Method done /////////////////////////////////////////////////////
        // ::
        //     done(ArrayLike values) → Promise
        //
        // Resolves the promise to the given values and call the
        // callbacks defined for ``done``.
        //
        // The given value array is cloned, then assigned to the
        // promise. This makes it easier for caller functions to just
        // pass the ``arguments`` object straight up to this function.
        //
        // If the promise has already been resolved, this method is a
        // noop.
        //
        function done(values) {
            if (!this.value) {
                this.clear_timer().flush('done')
                this.value = slice.call(values)
                this.flush() }
            return this
        }

        ////// Method fail /////////////////////////////////////////////////////
        // ::
        //     fail(Obj error) → Promise
        //
        // Fails to fulfill the promise, and calls all the ``fail``
        // callbacks passing the error as parameter.
        //
        // See :fn:`done` for more information.
        //
        function fail() {
            return this.flush('fail').done(arguments)
        }

        ////// Method bind /////////////////////////////////////////////////////
        // ::
        //     bind(values...) → Promise
        //
        // Successfully fulfills the promise, and calls the ``bind``
        // callbacks passing the values as parameter.
        //
        // See :fn:`resolve` for more information.
        //
        function bind() {
            return this.flush('ok').done(arguments)
        }

        ////// Method timeout //////////////////////////////////////////////////
        // ::
        //     timeout(Num delay) → Promise
        //
        // Fails to fulfill the promise after the given number of
        // seconds.
        //
        // The promise fails with the value of ``timeouted``.
        //
        function timeout(delay) {
            var promise = this
            this.timer = setTimeout(function(){
                promise.flush('timeouted')
                       .fail(timeouted)
            }, delay * 1000)
            return this
        }

        ////// Method clear_timer //////////////////////////////////////////////
        // ::
        //     clear_timer() → Promise
        //
        // Clears any timer that may exist for this promise.
        //
        function clear_timer() {
            clearTimeout(this.timer)
            return this
        }

        ////// Method forget ///////////////////////////////////////////////////
        // ::
        //     forget() → Promise
        //
        // Cancels the promise, and fails with the value of ``forgotten``.
        //
        function forget() {
            return this.flush('forgotten').fail(forgotten)
        }

        ////// -Shortcuts for add(event[, callback]) //////////////////////////
        function ok(fn)         { return this.add('ok',        fn) }
        function failed(fn)     { return this.add('fail',      fn) }
        function _timeouted(fn) { return this.add('timeouted', fn) }
        function _forgotten(fn) { return this.add('forgotten', fn) }
    }()

    ///// Exṕorts //////////////////////////////////////////////////////////////
    cassie.Promise      = Promise
    cassie.forgotten    = forgotten
    cassie.timeouted    = timeouted
}(this)<|endoftext|>


<commit_before>import App from './app';

var state;

// load state from the server sent state
// needed for isomorphic state sharing
try {
  state = JSON.parse(window.state);
} catch (err) {
  console.error(err);
}

new App(state, document.getElementById('app'));

// Try to add more
//

 have to be presented in the DOM
// new App(document.getElementById('app2'));
// new App(document.getElementById('app3'));
<commit_msg>Check for window.state<commit_after>import App from './app';

var state;

// load state from the server sent state
// needed for isomorphic state sharing
if(window.state) {
  try {
    state = JSON.parse(window.state);
  } catch (err) {
    console.error(err);
  }
}

new App(state, document.getElementById('app'));

// Try to add more
//

 have to be presented in the DOM
// new App(document.getElementById('app2'));
// new App(document.getElementById('app3'));
<|endoftext|>


<commit_before>
exports.commands = {
	/*stafflist: 'authlist',
	authlist: function (target, room, user, connection) {
		var rankLists = {};
		for (var u in Users.usergroups) {
			var rank = Users.usergroups[u][0];
			var name = Users.usergroups[u].slice(1);
			if (!rankLists[rank]) rankLists[rank] = [];
			if (name) name = name.replace("\n", "").replace("\r", "");
			rankLists[rank].push(name);
		}
		var buffer = [];
		Object.keys(rankLists).sort(function (a, b) {
			return Config.groups[b].rank - Config.groups[a].rank;
		}).forEach(function (r) {
			buffer.push(Config.groups[r].name + "s (" + r + "):\n" + rankLists[r].sort().join(", "));
		});

		if (!buffer.length) {
			buffer = "This server has no auth.";
			return connection.popup("This server has no auth.");
		}
		connection.popup(buffer.join("\n\n"));
	},*/

	plugdj: function () {
		if (!this.canBroadcast()) return;
		this.sendReplyBox('

Plug-DJ del Servidor Dropp');

	},

	jugando: 'afk',
	ocupado: 'afk',
	comiendo: 'afk',
	durmiendo: 'afk',
	grabando: 'afk',
	programando: 'afk',
	ausente: 'afk',
	away: 'afk',
	afk: function(target, room, user, connection, cmd) {
		if (!this.canTalk) return false;
		var t = 'Away';
		switch (cmd) {
			case 'jugando':
			t = 'ⒿⓊⒼⒶⓃⒹⓄ';
			s = 'Jugando'
			break;
                        case 'comiendo':
			t = 'ⒸⓄⓂⒾⒺⓃⒹⓄ';
			s = 'Comiendo'
			break;
                        case 'grabando':
			t = 'ⒼⓇⒶⒷⒶⓃⒹⓄ';
			s = 'Grabando'
			break;
			case 'durmiendo':
			t = 'ⒹⓊⓇⓂⒾⒺⓃⒹⓄ';
			s = 'Durmiendo'
			break;
			case 'programando':
			t = 'ⓅⓇⓄⒼⓇⒶⓂⒶⓃⒹⓄ';
			s = 'Programando'
			break;
			case 'ocupado':
			t = 'ⓄⒸⓊⓅⒶⒹⓄ';
			s = 'Ocupado'
			break;
			default:
			t = 'ⒶⓊⓈⒺⓃⓉⒺ'
			s = 'Ausente'
			break;
		},

	ayudaestado: 'afkhelvp,
	afkhelp: function () {
		if (!this.canBroadcast()) return;
		this.sendReplyBox(" Comandos de Afk :
" +
			  "/ausente
" +
                          "/ocupado
" +
			  "/comiendo
" +
			  "/aburrido
" +
                          "/durmiendo
" +
                          "/grabando (Especialmente para los youtubers)
" +
                          "/programando (Especialmente para los programadores del servidor).
" +
                          "
" );
	},

	postimage: 'image',
	image: function (target, room, user) {
		if (!target) return this.sendReply('Usage: /image link, size');
		if (!this.can('ban', room)) return false;
		if (!this.canBroadcast()) return;

		var targets = target.split(',');
		if (targets.length !== 2) {
			return this.sendReply('|raw|');
		}
		if (parseInt(targets[1]) <= 0 || parseInt(targets[1]) > 100) return this.parse('Usage: /image link, size (1-100)');
		this.sendReply('|raw|');
	},

	cssedit: function (target, room, user, connection) {
		if (!user.hasConsoleAccess(connection)) {return this.sendReply("/cssedit - Access denied.");}
		var fsscript = require('fs');
		if (!target) {
			if (!fsscript.existsSync(DATA_DIR + "custom.css")) return this.sendReply("custom.css no existe.");
			return this.sendReplyBox(fsscript.readFileSync(DATA_DIR + "custom.css").toString());
		}
		fsscript.writeFileSync(DATA_DIR + "custom.css", target.toString());
		this.sendReply("custom.css editado correctamente.");
	},

	destroymodlog: function (target, room, user, connection) {
		if (!user.hasConsoleAccess(connection)) {return this.sendReply("/destroymodlog - Access denied.");}
		var fsscript = require('fs');
		var logPath = LOGS_DIR + 'modlog/';
		if (CommandParser.modlog && CommandParser.modlog[room.id])  {
			CommandParser.modlog[room.id].close();
			delete CommandParser.modlog[room.id];
		}
		try {
			fsscript.unlinkSync(logPath + "modlog_" + room.id + ".txt");
			this.addModCommand(user.name + " ha destruido el modlog de esta sala." + (target ? ('(' + target + ')') : ''));
		} catch (e) {
			this.sendReply("No se puede destruir el modlog de esta sala.");
		}
	},

	clearall: function (target, room, user, connection) {
		if (!this.can('clearall')) return;
		var len = room.log.length,
			users = [];
		while (len--) {
			room.log[len] = '';
		}
		for (var user in room.users) {
			users.push(user);
			Users.get(user).leaveRoom(room, Users.get(user).connections[0]);
		}
		len = users.length;
		setTimeout(function() {
			while (len--) {
				Users.get(users[len]).joinRoom(room, Users.get(users[len]).connections[0]);
			}
		}, 1000);
	},

	roomlist: function (target, room, user) {
		if (!this.can('roomlist')) return;
		var rooms = Object.keys(Rooms.rooms);
		var len = rooms.length;
		var official = ['Salas oficiales:

'];
		var nonOfficial = ['
Salas no-oficiales:

'];
		var privateRoom = ['
Salas privadas:

'];
		while (len--) {
			var _room = Rooms.rooms[rooms[(rooms.length - len) - 1]];
			if (_room.type === 'chat') {
				if (_room.isOfficial) {
					official.push(('' + _room.title + ' |'));
				} else if (_room.isPrivate) {
					privateRoom.push(('' + _room.title + ' |'));
				} else {
					nonOfficial.push(('' + _room.title + ' |'));
				}
			}
		}
		this.sendReplyBox(official.join(' ') + nonOfficial.join(' ') + privateRoom.join(' '));
	}
};
<commit_msg>Update custom.js<commit_after>
exports.commands = {
	/*stafflist: 'authlist',
	authlist: function (target, room, user, connection) {
		var rankLists = {};
		for (var u in Users.usergroups) {
			var rank = Users.usergroups[u][0];
			var name = Users.usergroups[u].slice(1);
			if (!rankLists[rank]) rankLists[rank] = [];
			if (name) name = name.replace("\n", "").replace("\r", "");
			rankLists[rank].push(name);
		}
		var buffer = [];
		Object.keys(rankLists).sort(function (a, b) {
			return Config.groups[b].rank - Config.groups[a].rank;
		}).forEach(function (r) {
			buffer.push(Config.groups[r].name + "s (" + r + "):\n" + rankLists[r].sort().join(", "));
		});

		if (!buffer.length) {
			buffer = "This server has no auth.";
			return connection.popup("This server has no auth.");
		}
		connection.popup(buffer.join("\n\n"));
	},*/

	plugdj: function () {
		if (!this.canBroadcast()) return;
		this.sendReplyBox('

Plug-DJ del Servidor Dropp');

	},

	jugando: 'afk',
	ocupado: 'afk',
	comiendo: 'afk',
	durmiendo: 'afk',
	grabando: 'afk',
	programando: 'afk',
	ausente: 'afk',
	away: 'afk',
	afk: function(target, room, user, connection, cmd) {
		if (!this.canTalk) return false;
		var t = 'Away';
		switch (cmd) {
			case 'jugando':
			t = 'ⒿⓊⒼⒶⓃⒹⓄ';
			s = 'Jugando'
			break;
                        case 'comiendo':
			t = 'ⒸⓄⓂⒾⒺⓃⒹⓄ';
			s = 'Comiendo'
			break;
                        case 'grabando':
			t = 'ⒼⓇⒶⒷⒶⓃⒹⓄ';
			s = 'Grabando'
			break;
			case 'durmiendo':
			t = 'ⒹⓊⓇⓂⒾⒺⓃⒹⓄ';
			s = 'Durmiendo'
			break;
			case 'programando':
			t = 'ⓅⓇⓄⒼⓇⒶⓂⒶⓃⒹⓄ';
			s = 'Programando'
			break;
			case 'ocupado':
			t = 'ⓄⒸⓊⓅⒶⒹⓄ';
			s = 'Ocupado'
			break;
			default:
			t = 'ⒶⓊⓈⒺⓃⓉⒺ'
			s = 'Ausente'
			break;
		},

	ayudaestado: 'afkhelp,
	afkhelp: function () {
		if (!this.canBroadcast()) return;
		this.sendReplyBox(" Comandos de Afk :
" +
			  "/ausente
" +
                          "/ocupado
" +
			  "/comiendo
" +
			  "/aburrido
" +
                          "/durmiendo
" +
                          "/grabando (Especialmente para los youtubers)
" +
                          "/programando (Especialmente para los programadores del servidor).
" +
                          "
" );
	},

	postimage: 'image',
	image: function (target, room, user) {
		if (!target) return this.sendReply('Usage: /image link, size');
		if (!this.can('ban', room)) return false;
		if (!this.canBroadcast()) return;

		var targets = target.split(',');
		if (targets.length !== 2) {
			return this.sendReply('|raw|');
		}
		if (parseInt(targets[1]) <= 0 || parseInt(targets[1]) > 100) return this.parse('Usage: /image link, size (1-100)');
		this.sendReply('|raw|');
	},

	cssedit: function (target, room, user, connection) {
		if (!user.hasConsoleAccess(connection)) {return this.sendReply("/cssedit - Access denied.");}
		var fsscript = require('fs');
		if (!target) {
			if (!fsscript.existsSync(DATA_DIR + "custom.css")) return this.sendReply("custom.css no existe.");
			return this.sendReplyBox(fsscript.readFileSync(DATA_DIR + "custom.css").toString());
		}
		fsscript.writeFileSync(DATA_DIR + "custom.css", target.toString());
		this.sendReply("custom.css editado correctamente.");
	},

	destroymodlog: function (target, room, user, connection) {
		if (!user.hasConsoleAccess(connection)) {return this.sendReply("/destroymodlog - Access denied.");}
		var fsscript = require('fs');
		var logPath = LOGS_DIR + 'modlog/';
		if (CommandParser.modlog && CommandParser.modlog[room.id])  {
			CommandParser.modlog[room.id].close();
			delete CommandParser.modlog[room.id];
		}
		try {
			fsscript.unlinkSync(logPath + "modlog_" + room.id + ".txt");
			this.addModCommand(user.name + " ha destruido el modlog de esta sala." + (target ? ('(' + target + ')') : ''));
		} catch (e) {
			this.sendReply("No se puede destruir el modlog de esta sala.");
		}
	},

	clearall: function (target, room, user, connection) {
		if (!this.can('clearall')) return;
		var len = room.log.length,
			users = [];
		while (len--) {
			room.log[len] = '';
		}
		for (var user in room.users) {
			users.push(user);
			Users.get(user).leaveRoom(room, Users.get(user).connections[0]);
		}
		len = users.length;
		setTimeout(function() {
			while (len--) {
				Users.get(users[len]).joinRoom(room, Users.get(users[len]).connections[0]);
			}
		}, 1000);
	},

	roomlist: function (target, room, user) {
		if (!this.can('roomlist')) return;
		var rooms = Object.keys(Rooms.rooms);
		var len = rooms.length;
		var official = ['Salas oficiales:

'];
		var nonOfficial = ['
Salas no-oficiales:

'];
		var privateRoom = ['
Salas privadas:

'];
		while (len--) {
			var _room = Rooms.rooms[rooms[(rooms.length - len) - 1]];
			if (_room.type === 'chat') {
				if (_room.isOfficial) {
					official.push(('' + _room.title + ' |'));
				} else if (_room.isPrivate) {
					privateRoom.push(('' + _room.title + ' |'));
				} else {
					nonOfficial.push(('' + _room.title + ' |'));
				}
			}
		}
		this.sendReplyBox(official.join(' ') + nonOfficial.join(' ') + privateRoom.join(' '));
	}
};
<|endoftext|>


<commit_before>/*****************
* Reports Plugin *
* Credits: jd    *
*****************/
var fs = require('fs');
var moment = require('moment');

var Reports = {};
function loadReports() {
	try {
		Reports = JSON.parse(fs.readFileSync('config/reports.json'));
	} catch (e) {
		Reports = {};
	}
}
loadReports();

function saveReports() {
	fs.writeFile('config/reports.json', JSON.stringify(Reports));
}

function pmUpperStaff(message) {
    Gold.pmUpperStaff(message, '~Server');
}

exports.commands = {
    complain: 'requesthelp',
    bitch: 'requesthelp',
	report: 'requesthelp',
	requesthelp: function (target, room, user) {
		if (user.can('pban')) return this.parse('/reports ' + (target || ''));
		if (!this.canTalk()) return this.errorReply("You can't use this command while unable to speak.");
		if (!target) return this.errorReply("Usage: /requesthelp [message] - Requests help from Senior Staff. Please remember to include as much detail as possible with your request.");
		if (target.length < 1) return this.errorReply("Usage: /requesthelp [message] - Requests help from Senior Staff. Please remember to include as much detail as possible with your request.");

		var reportId = (Object.size(Reports) + 1);
		while (Reports[reportId]) reportId--;
		Reports[reportId] = new Object();
		Reports[reportId].reporter = user.name;
		Reports[reportId].message = target.trim();
		Reports[reportId].id = reportId;
		Reports[reportId].status = 'Pending Staff';
		Reports[reportId].reportTime = moment().format('MMMM Do YYYY, h:mm A') + " EST";
		saveReports();
		pmUpperStaff('A new report has been submitted by ' + user.name + '. ID: ' + reportId + ' Message: ' + target.trim());
		Rooms('upperstaff').add('A new report has been submitted by ' + user.name + '. ID: ' + reportId + ' Message: ' + target.trim());
		Rooms('upperstaff').update();
		return this.sendReply("Your report has been sent to Senior Staff.");
	},

	reports: function (target, room, user, connection, cmd) {
		if (!user.can('pban')) return this.errorReply('/reports - Access denied.');
		if (!target) var target = '';
		target = target.trim();

		var cmdParts = target.split(' ');
		var cmd = cmdParts.shift().trim().toLowerCase();
		var params = cmdParts.join(' ').split(',').map(function (param) { return param.trim(); });
		switch (cmd) {
			case '':
			case 'view':
				if (!this.runBroadcast()) return;
				var output = '|raw|

ID	Reporter	Message	Report Time	Status
';
				for (var u in Object.keys(Reports)) {
					var currentReport = Reports[Object.keys(Reports)[u]];
					var date = currentReport.reportTime;
					output += '
' + currentReport.id + '	' + Tools.escapeHTML(currentReport.reporter) + '	' +
						Tools.escapeHTML(currentReport.message) + '	' + date + ' 	' + (currentReport.status === 'Pending Staff' ? 'Pending Staff' : (~currentReport.status.indexOf('Accepted by') ? '' + Tools.escapeHTML(currentReport.status) + '' : Tools.escapeHTML(currentReport.status))) + '
';
				}
				this.sendReply(output);
				break;
			case 'accept':
				if (params.length < 1) return this.errorReply("Usage: /reports accept [id]");
				var id = params.shift();
				if (!Reports[id]) return this.errorReply("There's no report with that id.");
				if (Reports[id].status !== 'Pending Staff') return this.errorReply("That report isn't pending staff.");
				Reports[id].status = "Accepted by " + user.name;
				saveReports();
				if (Users(Reports[id].reporter) && Users(Reports[id].reporter).connected) {
					Users(Reports[id].reporter).popup("Your report has been accepted by " + user.name);
				}
				this.sendReply("You've accepted the report by "+ Reports[id].reporter);
				pmUpperStaff(user.name + " accepted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').add(user.name + " accepted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').update();
				break;
			case 'decline':
			case 'deny':
				if (params.length < 1) return this.errorReply("Usage: /reports deny [id]");
				var id = params.shift();
				if (!Reports[id]) return this.errorReply("There's no report with that id.");
				if (Reports[id].status !== 'Pending Staff') return this.errorReply("That report isn't pending staff.");
				if (Users(Reports[id].reporter) && Users(Reports[id].reporter).connected) {
					Users(Reports[id].reporter).popup("|modal|" + "Your report has been denied by " + user.name);
				}
				this.sendReply("You've denied the report by "+Reports[id].reporter);
				pmUpperStaff(user.name + " denied the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').add(user.name + " denied the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').update();
				delete Reports[id];
				saveReports();
				break;
			case 'del':
			case 'delete':
				if (params.length < 1) return this.errorReply("Usage: /reports delete [id]");
				var id = params.shift();
				if (!Reports[id]) return this.errorReply("There's no report with that id.");
				pmUpperStaff(user.name + " deleted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').add(user.name + " deleted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').update();
				delete Reports[id];
				saveReports();
				this.sendReply("That report has been deleted.");
				break;
			case 'help':
				if (!this.runBroadcast()) return;
				this.sendReplyBox("Report commands:
" +
					"/report [message] - Adds a report to the system
" +
					"/reports view - Views all current reports
" +
					"/reports accept [id] - Accepts a report
" +
					"/reports delete [id] - Deletes a report
" +
					"/reports deny [id] - Denies a report"
				);
				break;
			default:
				this.sendReply("/reports " + target + " - Command not found.");
		}
	}
};
<commit_msg>Update report.js<commit_after>/*****************
* Reports Plugin *
* Credits: jd    *
*****************/
var fs = require('fs');
var moment = require('moment');

var Reports = {};
function loadReports() {
	try {
		Reports = JSON.parse(fs.readFileSync('config/reports.json'));
	} catch (e) {
		Reports = {};
	}
}
loadReports();

function saveReports() {
	fs.writeFile('config/reports.json', JSON.stringify(Reports));
}

function pmUpperStaff(message) {
    Gold.pmUpperStaff(message, '~Server');
}

exports.commands = {
    complain: 'requesthelp',
    bitch: 'requesthelp',
	report: 'requesthelp',
	requesthelp: function (target, room, user) {
		if (user.can('pban')) return this.parse('/reports ' + (target || ''));
		if (!this.canTalk()) return this.errorReply("You can't use this command while unable to speak.");
		if (!target) return this.errorReply("Usage: /requesthelp [message] - Requests help from Senior Staff. Please remember to include as much detail as possible with your request.");
		if (target.length < 1) return this.errorReply("Usage: /requesthelp [message] - Requests help from Senior Staff. Please remember to include as much detail as possible with your request.");

		var reportId = (Object.keys(Reports) + 1);
		while (Reports[reportId]) reportId--;
		Reports[reportId] = new Object();
		Reports[reportId].reporter = user.name;
		Reports[reportId].message = target.trim();
		Reports[reportId].id = reportId;
		Reports[reportId].status = 'Pending Staff';
		Reports[reportId].reportTime = moment().format('MMMM Do YYYY, h:mm A') + " EST";
		saveReports();
		pmUpperStaff('A new report has been submitted by ' + user.name + '. ID: ' + reportId + ' Message: ' + target.trim());
		Rooms('upperstaff').add('A new report has been submitted by ' + user.name + '. ID: ' + reportId + ' Message: ' + target.trim());
		Rooms('upperstaff').update();
		return this.sendReply("Your report has been sent to Senior Staff.");
	},

	reports: function (target, room, user, connection, cmd) {
		if (!user.can('pban')) return this.errorReply('/reports - Access denied.');
		if (!target) var target = '';
		target = target.trim();

		var cmdParts = target.split(' ');
		var cmd = cmdParts.shift().trim().toLowerCase();
		var params = cmdParts.join(' ').split(',').map(function (param) { return param.trim(); });
		switch (cmd) {
			case '':
			case 'view':
				if (!this.runBroadcast()) return;
				var output = '|raw|

ID	Reporter	Message	Report Time	Status
';
				for (var u in Object.keys(Reports)) {
					var currentReport = Reports[Object.keys(Reports)[u]];
					var date = currentReport.reportTime;
					output += '
' + currentReport.id + '	' + Tools.escapeHTML(currentReport.reporter) + '	' +
						Tools.escapeHTML(currentReport.message) + '	' + date + ' 	' + (currentReport.status === 'Pending Staff' ? 'Pending Staff' : (~currentReport.status.indexOf('Accepted by') ? '' + Tools.escapeHTML(currentReport.status) + '' : Tools.escapeHTML(currentReport.status))) + '
';
				}
				this.sendReply(output);
				break;
			case 'accept':
				if (params.length < 1) return this.errorReply("Usage: /reports accept [id]");
				var id = params.shift();
				if (!Reports[id]) return this.errorReply("There's no report with that id.");
				if (Reports[id].status !== 'Pending Staff') return this.errorReply("That report isn't pending staff.");
				Reports[id].status = "Accepted by " + user.name;
				saveReports();
				if (Users(Reports[id].reporter) && Users(Reports[id].reporter).connected) {
					Users(Reports[id].reporter).popup("Your report has been accepted by " + user.name);
				}
				this.sendReply("You've accepted the report by "+ Reports[id].reporter);
				pmUpperStaff(user.name + " accepted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').add(user.name + " accepted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').update();
				break;
			case 'decline':
			case 'deny':
				if (params.length < 1) return this.errorReply("Usage: /reports deny [id]");
				var id = params.shift();
				if (!Reports[id]) return this.errorReply("There's no report with that id.");
				if (Reports[id].status !== 'Pending Staff') return this.errorReply("That report isn't pending staff.");
				if (Users(Reports[id].reporter) && Users(Reports[id].reporter).connected) {
					Users(Reports[id].reporter).popup("|modal|" + "Your report has been denied by " + user.name);
				}
				this.sendReply("You've denied the report by "+Reports[id].reporter);
				pmUpperStaff(user.name + " denied the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').add(user.name + " denied the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').update();
				delete Reports[id];
				saveReports();
				break;
			case 'del':
			case 'delete':
				if (params.length < 1) return this.errorReply("Usage: /reports delete [id]");
				var id = params.shift();
				if (!Reports[id]) return this.errorReply("There's no report with that id.");
				pmUpperStaff(user.name + " deleted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').add(user.name + " deleted the report by " + Reports[id].reporter + ". (ID: " + id + ")");
				Rooms('upperstaff').update();
				delete Reports[id];
				saveReports();
				this.sendReply("That report has been deleted.");
				break;
			case 'help':
				if (!this.runBroadcast()) return;
				this.sendReplyBox("Report commands:
" +
					"/report [message] - Adds a report to the system
" +
					"/reports view - Views all current reports
" +
					"/reports accept [id] - Accepts a report
" +
					"/reports delete [id] - Deletes a report
" +
					"/reports deny [id] - Denies a report"
				);
				break;
			default:
				this.sendReply("/reports " + target + " - Command not found.");
		}
	}
};
<|endoftext|>


<commit_before>const BundleTracker = require('webpack-bundle-tracker');
const path = require('path');
const webpack = require('webpack');

/*** helpers ***/

const devMode = process.env.NODE_ENV !== 'production';

// BundleTracker includes absolute paths, which causes webpack-stats.json to change when it shouldn't.
// We use this RelativeBundleTracker workaround via https://github.com/owais/webpack-bundle-tracker/issues/25
const RelativeBundleTracker = function(options) {
  BundleTracker.call(this, options);
};
RelativeBundleTracker.prototype = Object.create(BundleTracker.prototype);
RelativeBundleTracker.prototype.writeOutput = function(compiler, contents) {
  if(contents.chunks){
    const relativePathRoot = path.join(__dirname) + path.sep;
    for(const bundle of Object.values(contents.chunks)){
      for(const chunk of bundle){
        if (chunk.path.startsWith(relativePathRoot)) {
          chunk.path = chunk.path.substr(relativePathRoot.length);
        }
      }
    }
  }
  BundleTracker.prototype.writeOutput.call(this, compiler, contents);
};

/*** Vue config ***/
let devServerHost = process.env.DOCKERIZED ? '0.0.0.0' : '127.0.0.1';

let vueConfig = {
  outputDir: 'static/dist',

  // When running `npm run serve`, paths in webpack-stats.json will point to the live dev server.
  // Otherwise they will point to the compiled assets URL.
  publicPath: devMode ? 'http://localhost:8080/static/dist' : '/static/dist',

  pages: {
    application: 'frontend/pages/application.js',
    rich_text_editor: 'frontend/pages/rich_text_editor.js',
    main: 'frontend/pages/main.scss',
    test: 'frontend/pages/test.js',
    vue_app: 'frontend/pages/vue_app.js',
  },

  configureWebpack: {
    plugins: process.env.NODE_ENV === 'test' ? [new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
      }),] : [
      new RelativeBundleTracker({   // output location of bundles so they can be found by django
        filename: './webpack-stats.json'}),
      new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
      }),
    ],
    resolve: {
      alias: {
        '@': path.resolve("frontend"),
        vue: "vue/dist/vue.esm.js",
        'vue$': 'vue/dist/vue.esm.js',
        // alias assets dir to ~assets for SASS url() styles
        static: path.resolve("static"),
      },
      modules: [
        path.resolve('frontend'),
        path.resolve('frontend', 'styles'),
        'node_modules'
      ],
    }
  },

  devServer: {
    public: devServerHost + ':8080',
    host: devServerHost,
    headers: { 'Access-Control-Allow-Origin': '*' },
    allowedHosts: [
      '.h2o-dev.local'
    ],
    // hopefully we don't need active polling ...
    // watchOptions: {
    //   poll: true,
    //   ignored: ['node_modules'],
    // }

  },

  chainWebpack: config => {
    // delete HTML related webpack plugins
    // via https://github.com/vuejs/vue-cli/issues/1478
    Object.keys(vueConfig.pages).forEach(function (key) {
      config.plugins.delete('html-' + key);
      config.plugins.delete('preload-' + key);
      config.plugins.delete('prefetch-' + key);
    });

    // use same chunks config for dev as prod so {% render_bundle %} works on both
    // copied from node_modules/@vue/cli-service/lib/config/app.js
    config.optimization.splitChunks({
      cacheGroups: {
        // vendors: {
        //   name: `chunk-vendors`,
        //   test: /[\\/]node_modules[\\/]/,
        //   priority: -10,
        //   chunks: 'initial'
        // },
        common: {
          name: `chunk-common`,
          minChunks: 2,
          priority: -20,
          chunks: 'initial',
          reuseExistingChunk: true
        }
      }
    });

    // workaround for "SASS files from NPM modules referencing relative imports won't build [in mocha]"
    // https://github.com/vuejs/vue-cli/issues/4053#issuecomment-544641072
    if (process.env.NODE_ENV === 'test') {
      const scssRule = config.module.rule('scss');
      scssRule.uses.clear();
      scssRule
        .use('null-loader')
        .loader('null-loader');
    }
  },

};

module.exports = vueConfig;
<commit_msg>Try concat<commit_after>const BundleTracker = require('webpack-bundle-tracker');
const path = require('path');
const webpack = require('webpack');

/*** helpers ***/

const devMode = process.env.NODE_ENV !== 'production';
const testMode = process.env.NODE_ENV === 'test'

// BundleTracker includes absolute paths, which causes webpack-stats.json to change when it shouldn't.
// We use this RelativeBundleTracker workaround via https://github.com/owais/webpack-bundle-tracker/issues/25
const RelativeBundleTracker = function(options) {
  BundleTracker.call(this, options);
};
RelativeBundleTracker.prototype = Object.create(BundleTracker.prototype);
RelativeBundleTracker.prototype.writeOutput = function(compiler, contents) {
  if(contents.chunks){
    const relativePathRoot = path.join(__dirname) + path.sep;
    for(const bundle of Object.values(contents.chunks)){
      for(const chunk of bundle){
        if (chunk.path.startsWith(relativePathRoot)) {
          chunk.path = chunk.path.substr(relativePathRoot.length);
        }
      }
    }
  }
  BundleTracker.prototype.writeOutput.call(this, compiler, contents);
};

/*** Vue config ***/
let devServerHost = process.env.DOCKERIZED ? '0.0.0.0' : '127.0.0.1';

let vueConfig = {
  outputDir: 'static/dist',

  // When running `npm run serve`, paths in webpack-stats.json will point to the live dev server.
  // Otherwise they will point to the compiled assets URL.
  publicPath: devMode ? 'http://localhost:8080/static/dist' : '/static/dist',

  pages: {
    application: 'frontend/pages/application.js',
    rich_text_editor: 'frontend/pages/rich_text_editor.js',
    main: 'frontend/pages/main.scss',
    test: 'frontend/pages/test.js',
    vue_app: 'frontend/pages/vue_app.js',
  },

  configureWebpack: {
    plugins: [
      new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
      }),].concat(testMode ? [] : [
        new RelativeBundleTracker({
          // output location of bundles so they can be found by django
          filename: './webpack-stats.json'}),
      ]),
    resolve: {
      alias: {
        '@': path.resolve("frontend"),
        vue: "vue/dist/vue.esm.js",
        'vue$': 'vue/dist/vue.esm.js',
        // alias assets dir to ~assets for SASS url() styles
        static: path.resolve("static"),
      },
      modules: [
        path.resolve('frontend'),
        path.resolve('frontend', 'styles'),
        'node_modules'
      ],
    }
  },

  devServer: {
    public: devServerHost + ':8080',
    host: devServerHost,
    headers: { 'Access-Control-Allow-Origin': '*' },
    allowedHosts: [
      '.h2o-dev.local'
    ],
    // hopefully we don't need active polling ...
    // watchOptions: {
    //   poll: true,
    //   ignored: ['node_modules'],
    // }

  },

  chainWebpack: config => {
    // delete HTML related webpack plugins
    // via https://github.com/vuejs/vue-cli/issues/1478
    Object.keys(vueConfig.pages).forEach(function (key) {
      config.plugins.delete('html-' + key);
      config.plugins.delete('preload-' + key);
      config.plugins.delete('prefetch-' + key);
    });

    // use same chunks config for dev as prod so {% render_bundle %} works on both
    // copied from node_modules/@vue/cli-service/lib/config/app.js
    config.optimization.splitChunks({
      cacheGroups: {
        // vendors: {
        //   name: `chunk-vendors`,
        //   test: /[\\/]node_modules[\\/]/,
        //   priority: -10,
        //   chunks: 'initial'
        // },
        common: {
          name: `chunk-common`,
          minChunks: 2,
          priority: -20,
          chunks: 'initial',
          reuseExistingChunk: true
        }
      }
    });

    // workaround for "SASS files from NPM modules referencing relative imports won't build [in mocha]"
    // https://github.com/vuejs/vue-cli/issues/4053#issuecomment-544641072
    if (testMode) {
      const scssRule = config.module.rule('scss');
      scssRule.uses.clear();
      scssRule
        .use('null-loader')
        .loader('null-loader');
    }
  },

};

module.exports = vueConfig;
<|endoftext|>