<commit_before>import Mapper from "./mapper";
import date from "../date";
import config from "../../config";
import router from "../../router";
import {value} from "../../utils";

export default function () {
    const mapper = new Mapper;

    mapper.registerResolver("App.Meta", "Vue.MetaInfo", function (meta) {
        return {
            title: value(() => meta.title),
            titleTemplate: value(() => meta.title) ? `%s | ${value(() => meta.name)}` : value(() => meta.name),
            meta: [
                {vmid: "description", name: "description", content: value(() => meta.description)},
                {vmid: "keywords", name: "keywords", content: value(() => meta.keywords)},
                // Open Graph protocol properties.
                {vmid: "og:type", property: "og:type", content: "article"},
                {vmid: "og:url", property: "og:url", content: config.url.app + router.currentRoute.fullPath},
                {vmid: "og:site_name", property: "og:site_name", content: value(() => meta.name)},
                {vmid: "og:description", property: "og:description", content: value(() => meta.description)},
                {vmid: "og:image", property: "og:image", content: value(() => meta.image)},
                {vmid: "og:title", property: "og:title", content: value(() => meta.title)},
                // Twitter Cards properties.
                {vmid: "twitter:card", name: "twitter:card", property: "twitter:card", content: "summary_large_image"},
                {vmid: "twitter:title", name: "twitter:title", property: "twitter:title", content: value(() => meta.title)},
                {vmid: "twitter:image", name: "twitter:image", property: "twitter:image", content: value(() => meta.image)},
            ],
        };
    });

    mapper.registerResolver("Api.V1.User", "App.User", function (user) {
        return {
            id: value(() => user.id),
            name: value(() => user.name),
        };
    });

    mapper.registerResolver("Api.V1.Post", "App.Photo", function (post) {
        const route = router.history.current;
        return {
            id: post.id,
            route: {
                name: "photo",
                params: {id: post.id},
                query: {
                    tag: route.params.tag || route.query.tag,
                    search_phrase: route.params.search_phrase || route.query.search_phrase,
                    page: route.params.page || route.query.page,
                },
            },
            description: value(() => post.description),
            exif: mapper.map(value(() => post.photo.exif), "Api.V1.Exif", "App.Exif"),
            averageColor: value(() => post.photo.avg_color),
            thumbnail: mapper.map(value(() => post.photo.thumbnails.medium), "Api.V1.Thumbnail", "App.Thumbnail"),
            original: mapper.map(value(() => post.photo.thumbnails.large), "Api.V1.Thumbnail", "App.Thumbnail"),
            tags: post.tags.map((tag) => value(() => tag.value)),
            toString: () => value(() => post.photo.thumbnails.large.url),
            is: (image) => value(() => image.id) === value(() => post.id),
        };
    });

    mapper.registerResolver("*", "Api.V1.Post", function (any) {
        return {
            id: undefined,
            created_by_user_id: undefined,
            is_published: undefined,
            description: undefined,
            published_at: undefined,
            created_at: undefined,
            updated_at: undefined,
            photo: {
                id: undefined,
                created_by_user_id: undefined,
                avg_color: undefined,
                created_at: undefined,
                exif: {
                    manufacturer: undefined,
                    model: undefined,
                    exposure_time: undefined,
                    aperture: undefined,
                    iso: undefined,
                    taken_at: undefined
                },
                thumbnails: {
                    medium: {
                        url: undefined,
                        width: undefined,
                        height: undefined
                    },
                    large: {
                        url: undefined,
                        width: undefined,
                        height: undefined
                    }
                }
            },
            tags: [],
        };
    });

    mapper.registerResolver("Api.V1.Thumbnail", "App.Thumbnail", function (thumbnail) {
        return {
            url: value(() => thumbnail.url),
            width: value(() => thumbnail.width),
            height: value(() => thumbnail.height),
        };
    });

    mapper.registerResolver("Api.V1.Exif", "App.Exif", function (exif) {
        return {
            manufacturer: value(() => exif.manufacturer),
            model: value(() => exif.model),
            exposureTime: value(() => exif.exposure_time),
            aperture: value(() => exif.aperture),
            iso: value(() => exif.iso),
            takenAt: value(() => exif.taken_at) ? date.format(exif.taken_at) : value(() => exif.taken_at),
        };
    });

    mapper.registerResolver("Api.V1.Tag", "App.Tag", function (tag) {
        return value(() => tag.value);
    });

    mapper.registerResolver("App.Tag", "Api.V1.Tag", function (tag) {
        return {
            value: tag,
        };
    });

    return mapper;
}
<commit_msg>Improved meta tags<commit_after>import Mapper from "./mapper";
import date from "../date";
import config from "../../config";
import router from "../../router";
import {value} from "../../utils";

export default function () {
    const mapper = new Mapper;

    mapper.registerResolver("App.Meta", "Vue.MetaInfo", function (meta) {
        return {
            title: value(() => meta.title),
            titleTemplate: value(() => meta.title) ? `%s | ${value(() => meta.name)}` : value(() => meta.name),
            meta: [
                {vmid: "description", name: "description", content: value(() => meta.description)},
                {vmid: "keywords", name: "keywords", content: value(() => meta.keywords)},
                // Open Graph protocol properties.
                {vmid: "og:type", property: "og:type", content: "article"},
                {vmid: "og:url", property: "og:url", content: config.url.app + router.currentRoute.fullPath},
                {vmid: "og:site_name", property: "og:site_name", content: value(() => meta.name)},
                {vmid: "og:description", property: "og:description", content: value(() => meta.description)},
                {vmid: "og:image", property: "og:image", content: value(() => meta.image)},
                {vmid: "og:title", property: "og:title", content: value(() => meta.title)},
                // Twitter Cards properties.
                {vmid: "twitter:card", name: "twitter:card", content: "summary_large_image"},
                {vmid: "twitter:title", name: "twitter:title", content: value(() => meta.title)},
                {vmid: "twitter:image", name: "twitter:image", content: value(() => meta.image)},
            ],
        };
    });

    mapper.registerResolver("Api.V1.User", "App.User", function (user) {
        return {
            id: value(() => user.id),
            name: value(() => user.name),
        };
    });

    mapper.registerResolver("Api.V1.Post", "App.Photo", function (post) {
        const route = router.history.current;
        return {
            id: post.id,
            route: {
                name: "photo",
                params: {id: post.id},
                query: {
                    tag: route.params.tag || route.query.tag,
                    search_phrase: route.params.search_phrase || route.query.search_phrase,
                    page: route.params.page || route.query.page,
                },
            },
            description: value(() => post.description),
            exif: mapper.map(value(() => post.photo.exif), "Api.V1.Exif", "App.Exif"),
            averageColor: value(() => post.photo.avg_color),
            thumbnail: mapper.map(value(() => post.photo.thumbnails.medium), "Api.V1.Thumbnail", "App.Thumbnail"),
            original: mapper.map(value(() => post.photo.thumbnails.large), "Api.V1.Thumbnail", "App.Thumbnail"),
            tags: post.tags.map((tag) => value(() => tag.value)),
            toString: () => value(() => post.photo.thumbnails.large.url),
            is: (image) => value(() => image.id) === value(() => post.id),
        };
    });

    mapper.registerResolver("*", "Api.V1.Post", function (any) {
        return {
            id: undefined,
            created_by_user_id: undefined,
            is_published: undefined,
            description: undefined,
            published_at: undefined,
            created_at: undefined,
            updated_at: undefined,
            photo: {
                id: undefined,
                created_by_user_id: undefined,
                avg_color: undefined,
                created_at: undefined,
                exif: {
                    manufacturer: undefined,
                    model: undefined,
                    exposure_time: undefined,
                    aperture: undefined,
                    iso: undefined,
                    taken_at: undefined
                },
                thumbnails: {
                    medium: {
                        url: undefined,
                        width: undefined,
                        height: undefined
                    },
                    large: {
                        url: undefined,
                        width: undefined,
                        height: undefined
                    }
                }
            },
            tags: [],
        };
    });

    mapper.registerResolver("Api.V1.Thumbnail", "App.Thumbnail", function (thumbnail) {
        return {
            url: value(() => thumbnail.url),
            width: value(() => thumbnail.width),
            height: value(() => thumbnail.height),
        };
    });

    mapper.registerResolver("Api.V1.Exif", "App.Exif", function (exif) {
        return {
            manufacturer: value(() => exif.manufacturer),
            model: value(() => exif.model),
            exposureTime: value(() => exif.exposure_time),
            aperture: value(() => exif.aperture),
            iso: value(() => exif.iso),
            takenAt: value(() => exif.taken_at) ? date.format(exif.taken_at) : value(() => exif.taken_at),
        };
    });

    mapper.registerResolver("Api.V1.Tag", "App.Tag", function (tag) {
        return value(() => tag.value);
    });

    mapper.registerResolver("App.Tag", "Api.V1.Tag", function (tag) {
        return {
            value: tag,
        };
    });

    return mapper;
}
<|endoftext|>


<commit_before>import { createFilter } from '@rollup/pluginutils';
import prettier from 'prettier';

import { compile, compileTranslation } from '../i18n/compile-translation.js';

export default function langImport(options) {
    const filter = createFilter(options.include, options.exclude);
    const { filterChunk = () => true } = options;
    const { outputTranslationsAsFn = false } = options;

    return {
        name: 'langImport',
        enforce: 'post',
        transform(code, id) {
            if (
                !filter(id) ||
                !(id.endsWith('.lang.js') && id.includes('/strings/'))
            ) {
                return;
            }
            id = id.slice(id.lastIndexOf('/') + 1).replace('.lang.js', '');

            return compile(id, code, null, outputTranslationsAsFn);
        },
        renderChunk(code, chunk) {
            if (!filterChunk(chunk)) {
                return;
            }

            const id = code.match(/['"]?code['"]?:\s*['"]([a-z-]+)['"]/)[1];
            if (!id) {
                throw new Error("Could not find ID.")
            }
            const fallbackRules = {
                needsFallbackPluralisationFunction: true,
            };
            if (
                [
                    'bg',
                    'da',
                    'de',
                    'en',
                    'en-gb',
                    'es',
                    'es-la',
                    'fi',
                    'hu',
                    'it',
                    'nb',
                    'nl',
                    'nn',
                    'pt',
                    'sv',
                    'tr',
                ].includes(id)
            ) {
                fallbackRules.needsFallbackPluralisationFunction = false;
            }

            code = code.replace(
                /['"]?translations['"]?:\s*\{(.*)\}\s*\};/gs,
                (match, strings) => {
                    let data;
                    try {
                        // eslint-disable-next-line no-eval
                        const evalGlobal = eval;
                        data = evalGlobal(
                            '(function () { return {' + strings + '}})();',
                        );
                    } catch {
                        return match;
                    }
                    const translations = options.idsInUse.map((id) => {
                        return compileTranslation(
                            JSON.parse(data[id]),
                            fallbackRules,
                        );
                    });
                    return (
                        'translations: ' +
                        prettier
                            .format('[' + translations + ']', {
                                singleQuote: false,
                                tabWidth: 4,
                                quoteProps: 'as-needed',
                                trailingComma: 'all',
                                parser: 'babel',
                            })
                            .replace('];', ']}')
                    );
                },
            );

            return {
                code,
                map: { mappings: '' },
            };
        },
    };
}
<commit_msg>rollup-plugin-lang-import: improve error message<commit_after>import { createFilter } from '@rollup/pluginutils';
import prettier from 'prettier';

import { compile, compileTranslation } from '../i18n/compile-translation.js';

export default function langImport(options) {
    const filter = createFilter(options.include, options.exclude);
    const { filterChunk = () => true } = options;
    const { outputTranslationsAsFn = false } = options;

    return {
        name: 'langImport',
        enforce: 'post',
        transform(code, id) {
            if (
                !filter(id) ||
                !(id.endsWith('.lang.js') && id.includes('/strings/'))
            ) {
                return;
            }
            id = id.slice(id.lastIndexOf('/') + 1).replace('.lang.js', '');

            return compile(id, code, null, outputTranslationsAsFn);
        },
        renderChunk(code, chunk) {
            if (!filterChunk(chunk)) {
                return;
            }

            const id = code.match(/['"]?code['"]?:\s*['"]([a-z-]+)['"]/)[1];
            if (!id) {
                throw new Error("Could not find ID.")
            }
            const fallbackRules = {
                needsFallbackPluralisationFunction: true,
            };
            if (
                [
                    'bg',
                    'da',
                    'de',
                    'en',
                    'en-gb',
                    'es',
                    'es-la',
                    'fi',
                    'hu',
                    'it',
                    'nb',
                    'nl',
                    'nn',
                    'pt',
                    'sv',
                    'tr',
                ].includes(id)
            ) {
                fallbackRules.needsFallbackPluralisationFunction = false;
            }

            code = code.replace(
                /['"]?translations['"]?:\s*\{(.*)\}\s*\};/gs,
                (match, strings) => {
                    let data;
                    try {
                        // eslint-disable-next-line no-eval
                        const evalGlobal = eval;
                        data = evalGlobal(
                            '(function () { return {' + strings + '}})();',
                        );
                    } catch {
                        return match;
                    }
                    const translations = options.idsInUse.map((id) => {
                        const target = data[id];
                        if (!target) {
                            throw new Error(
                                `Couldn't find a string for: ${id}`
                            );
                        }
                        return compileTranslation(
                            JSON.parse(target),
                            fallbackRules,
                        );
                    });
                    return (
                        'translations: ' +
                        prettier
                            .format('[' + translations + ']', {
                                singleQuote: false,
                                tabWidth: 4,
                                quoteProps: 'as-needed',
                                trailingComma: 'all',
                                parser: 'babel',
                            })
                            .replace('];', ']}')
                    );
                },
            );

            return {
                code,
                map: { mappings: '' },
            };
        },
    };
}
<|endoftext|>


<commit_before>elation.require([], function() {
  elation.extend("physics.rigidbody", function(args) {
    this.position = new THREE.Vector3();
    this.positionWorld = new THREE.Vector3();
    this.orientation = new THREE.Quaternion();
    this.orientationWorld = new THREE.Quaternion();
    this.velocity = new THREE.Vector3();
    this.acceleration = new THREE.Vector3();
    this.angular = new THREE.Vector3();
    this.angularacceleration = new THREE.Vector3();
    this.forces = [];
    this.constraints = [];
    this.mass = 0;
    this.state = {sleeping: true, accelerating: false, moving: false, rotating: false};
    this.momentInverse = new THREE.Matrix4().identity();
    this.linearDamping = 1;
    this.angularDamping = 1;
    this.restitution = 1;
    this.paused = false;

    this.parent = false;
    this.children = [];

    // Accumulation buffers for linear and rotational acceleration
    this.force_accumulator = new THREE.Vector3();
    this.torque_accumulator = new THREE.Vector3();
    this._tmpvec = new THREE.Vector3();
    this._tmpvec2 = new THREE.Vector3();
    this.lastacceleration = new THREE.Vector3();

    this.init = function() {
      for (var k in args) {
        if (!elation.utils.isNull(args[k])) {
          this[k] = args[k];
        }
      }
      this.updateState();
    }
    this.updateState = function() {
      var lambda = 0.00001;
      this.processConstraints();

      if (this.parent) {
        this.orientationWorld.multiplyQuaternions(this.parent.orientationWorld, this.orientation);
        this.positionWorld.copy(this.position).applyQuaternion(this.parent.orientation.clone().inverse()).add(this.parent.positionWorld);
      } else {
        this.orientationWorld.copy(this.orientation).inverse();
        this.positionWorld.copy(this.position);
      }

      this.state.forces = false;
      for (var i = 0, l = this.forces.length; i < l; i++) {
        this.state.forces = this.state.forces || (typeof this.forces[i].sleepstate == 'function' ? !this.forces[i].sleepstate() : true);
      }
      this.state.accelerating = (this.acceleration && this.acceleration.lengthSq() > lambda);
      this.state.moving = (this.velocity && this.velocity.lengthSq() > lambda);
      this.state.rotating = ((this.angular && this.angular.lengthSq() > lambda) || (this.angularacceleration && this.angularacceleration.lengthSq() > lambda));

      this.state.sleeping = this.paused || !(this.state.forces || this.state.accelerating || this.state.moving || this.state.rotating);
      return this.state.sleeping;
    }

    this.clearAccumulators = function() {
      this.force_accumulator.set(0,0,0);
      this.torque_accumulator.set(0,0,0);
    }
    this.updateAcceleration = function() {
      this.lastacceleration.copy(this.acceleration);
      if (this.forces.length > 0) {
        this.clearAccumulators();
        for (var k in this.forces) {
          this.forces[k].apply();
        }
        this.acceleration.copy(this.force_accumulator.divideScalar(this.mass));
        if (this.collider && this.collider.momentInverse) {
          this.angularacceleration.copy(this.torque_accumulator.applyMatrix4(this.collider.momentInverse));
        }
      }
      this.updateState();
      //console.log([this.acceleration.x, this.acceleration.y, this.acceleration.z], [this.angularacceleration.x, this.angularacceleration.y, this.angularacceleration.z]);
    }
    this.applyForce = function(force, relative) {
      this._tmpvec.copy(force);
      if (relative) {
        this.localToWorldDir(this._tmpvec);
      }
      this.force_accumulator.add(this._tmpvec);
    }
    this.applyForceAtPoint = function(force, point, relative) {
      this.applyForce(force, relative);
      this.applyTorque(point.clone().cross(force));
    }
    this.applyTorque = function(torque) {
      this.torque_accumulator.add(torque);
    }
    this.setVelocity = function(vel) {
      this.velocity.copy(vel);
      this.updateState();
    }
    this.addVelocity = function(vel) {
      this.velocity.add(vel);
      this.updateState();
    }
    this.setAngularVelocity = function(vel) {
      this.angular.copy(vel);
      this.updateState();
    }
    this.addAngularVelocity = function(vel) {
      this.angular.add(vel);
      this.updateState();
    }
    this.addForce = function(type, args) {
      var force = false;
      if (typeof elation.physics.forces[type] == 'function') {
        force = new elation.physics.forces[type](this, args);
        this.forces.push(force);
        this.updateAcceleration();
        this.updateState();
        //console.log('added new force', force);
      } else {
        console.log('Unknown force type: ' + type);
      }
      return force;
    }
    this.removeForce = function(force) {
      var removes = [];
      if (typeof force == 'string') {
        for (var i = 0; i < this.forces.length; i++) {
          if (this.forces[i] instanceof elation.physics.forces[force]) {
            removes.unshift(i);
          }
        }
      } else {
        var idx = this.forces.indexOf(force);
        if (idx > -1) {
          removes.push(idx);
        }
      }
      if (removes.length > 0) {
        removes.sort();
        for (var i = removes.length; i > 0; --i) {
          this.forces.splice(i, 1);
        }
      }
    }
    this.getForces = function(type) {
      var forces = [];
      for (var i = 0; i < this.forces.length; i++) {
        if (this.forces[i] instanceof elation.physics.forces[type]) {
          forces.push(this.forces[i]);
        }
      }
      return (forces.length > 0 ? forces : false);
    }
    this.updateForce = function(name, args) {
      /*
      if (this.forces[name]) {
        this.forces[name].update(args);
      }
      */
    }
    this.addConstraint = function(type, args) {
      var constraint = false;
      if (typeof elation.physics.constraints[type] == 'function') {
        constraint = new elation.physics.constraints[type](this, args);
        this.constraints.push(constraint);
        //this.updateConstraints();
        this.updateState();
        //console.log('added new constraint', constraint);
      } else {
        console.log('Unknown constraint type: ' + type);
      }
      return constraint;
    }
    this.removeConstraint = function(constraint) {
      var removes = [];
      if (typeof constraint == 'string') {
        for (var i = 0; i < this.constraints.length; i++) {
          if (this.constraints[i] instanceof elation.physics.constraints[constraint]) {
            removes.unshift(i);
          }
        }
      } else {
        var idx = this.constraints.indexOf(constraint);
        if (idx > -1) {
          removes.push(idx);
        }
      }
      if (removes.length > 0) {
        removes.sort();
        for (var i = removes.length; i > 0; --i) {
          this.constraints.splice(i, 1);
        }
      }
    }
    /*
    this.updateMoment = function(shape, shapeargs) {
      switch (shape) {
        case 'box':
          var diff = shapeargs.max.clone().sub(shapeargs.min);
          var xsq = diff.x*diff.x,
              ysq = diff.y*diff.y,
              zsq = diff.z*diff.z,
              m = 1/12 * this.mass;
          this.momentInverse.set(
            1 / (m * (ysq + zsq)), 0, 0, 0,
            0, 1 / (m * (xsq + zsq)), 0, 0,
            0, 0, 1 / (m * (xsq + ysq)), 0,
            0, 0, 0, 1);
          break;
        case 'sphere':
          var c = 5 / (2 * this.mass * shapeargs.radius * shapeargs.radius);
          this.momentInverse.set(
            c, 0, 0, 0,
            0, c, 0, 0,
            0, 0, c, 0,
            0, 0, 0, 1);
          break;
        case 'cylinder':
          // FIXME - axes are probably wrong
          var rsq = shapeargs.x * shapeargs.x,
              hsq = shapeargs.y * shapeargs.y,
              xy = 1/(1/12 * m * hsq + 1/4 * m * rsq),
              z = 1/(1/2 * m * rsq);
          this.momentInverse.set(
            xy, 0, 0, 0,
            0, xy, 0, 0,
            0, 0, z, 0,
            0, 0, 0, 1);
          break;
        case 'matrix':
          this.momentInverse.copy(shapeargs);
          break;
        default:
          console.log('Unimplemented inertia moment tensor: ' + shape);
      }
    }
    */

    // Coordinate space transforms

    // world space to local space
    this.worldToLocalPos = function() {
      // closure for scratch variables
      var tmpquat = new THREE.Quaternion();
      return function(point) {
        if (!point) point = new THREE.Vector3();
        if (this.parent) {
          point = this.parent.worldToLocalPos(point);
        }
        return this.parentToLocalPos(point);
      }
    }();
    // local space to world space
    this.localToWorldPos = function(point) {
      point = this.localToParentPos(point);
      if (this.parent) {
        point = this.parent.localToWorldPos(point);
      }
      return point;
    }
    // local space to parent space
    this.localToParentPos = function(point) {
      if (!point) point = new THREE.Vector3();
      return point.applyQuaternion(this.orientation).add(this.position);
    }
    // parent space to local space
    this.parentToLocalPos = function() {
      // closure for scratch variables
      var tmpquat = new THREE.Quaternion();
      return function(point) {
        if (!point) point = new THREE.Vector3();
        return point.sub(this.position).applyQuaternion(tmpquat.copy(this.orientation).inverse());
      }
    }();
    // world direction to local direction
    this.worldToLocalDir = function() {
      // temp variable closure
      var tmpquat = new THREE.Quaternion();
      return function(dir) {
        return dir.applyQuaternion(tmpquat.copy(this.orientationWorld).inverse());
      }
    }();
    // local direction to world direction
    this.localToWorldDir = function(dir) {
      return dir.applyQuaternion(this.orientationWorld);
    }

    this.isPotentiallyColliding = function() {
      // closure scratch vars
      var thispos = new THREE.Vector3(),
          otherpos = new THREE.Vector3(),
          diff = new THREE.Vector3();

      return function(other) {
        other.localToWorldPos(otherpos.set(0,0,0));
        this.localToWorldPos(thispos.set(0,0,0));
        diff.subVectors(otherpos, thispos);
        var radius = this.collider.radius + other.collider.radius;
        return (
          //other.object != this.object.parent &&
          //this.object != other.object.parent &&
          diff.lengthSq() <= radius * radius
         );
      }
    }();
    this.getContacts = function(other, collisions) {
      var hasContacts = false;
      if (this.collider && other.collider) {
        hasContacts = this.collider.getContacts(other.collider, collisions);
      }
      return hasContacts;
    }
    this.setCollider = function(type, colliderargs) {
      if (typeof type == 'object') {
        this.collider = type;
        this.collider.body = this;
      } else {
        if (typeof elation.physics.colliders[type] == 'function') {
          this.collider = new elation.physics.colliders[type](this, colliderargs);
        } else {
          console.log('Unknown collider type ' + type);
        }
      }
      this.collider.getInertialMoment();
    }
    this.setDamping = function(linear, angular) {
      if (typeof angular == 'undefined') angular = linear;
      this.setLinearDamping(linear);
      this.setAngularDamping(angular);
    }
    this.setLinearDamping = function(linear) {
      this.linearDamping = linear;
    }
    this.setAngularDamping = function(angular) {
      this.angularDamping = angular;
    }
    this.add = function(body) {
      var idx = this.children.indexOf(body);
      if (idx == -1) this.children.push(body);
      body.parent = this;
    }
    this.remove = function(body) {
      var idx = this.children.indexOf(body);
      if (idx != -1) {
        this.children.splice(idx,1);
        body.parent = undefined;
      }
    }
    this.processConstraints = function(contactlist) {
      var wasConstrained = false;
      for (var i = 0; i < this.constraints.length; i++) {
        wasConstrained = wasConstrained || this.constraints[i].apply(contactlist);
      }
      return wasConstrained;
    }
    this.init();
  });
});
<commit_msg>Added framedata support<commit_after>elation.require([], function() {
  elation.extend("physics.rigidbody", function(args) {
    this.position = new THREE.Vector3();
    this.positionWorld = new THREE.Vector3();
    this.orientation = new THREE.Quaternion();
    this.orientationWorld = new THREE.Quaternion();
    this.velocity = new THREE.Vector3();
    this.acceleration = new THREE.Vector3();
    this.angular = new THREE.Vector3();
    this.angularacceleration = new THREE.Vector3();
    this.forces = [];
    this.constraints = [];
    this.mass = 0;
    this.state = {sleeping: true, accelerating: false, moving: false, rotating: false};
    this.momentInverse = new THREE.Matrix4().identity();
    this.linearDamping = 1;
    this.angularDamping = 1;
    this.restitution = 1;
    this.paused = false;

    this.parent = false;
    this.children = [];

    // Accumulation buffers for linear and rotational acceleration
    this.force_accumulator = new THREE.Vector3();
    this.torque_accumulator = new THREE.Vector3();
    this._tmpvec = new THREE.Vector3();
    this._tmpvec2 = new THREE.Vector3();
    this.lastacceleration = new THREE.Vector3();

    this.init = function() {
      for (var k in args) {
        if (!elation.utils.isNull(args[k])) {
          this[k] = args[k];
        }
      }
      this.updateState();
    }
    this.updateState = function() {
      var lambda = 0.00001;
      this.processConstraints();

      if (this.parent) {
        this.orientationWorld.multiplyQuaternions(this.parent.orientationWorld, this.orientation);
        this.positionWorld.copy(this.position).applyQuaternion(this.parent.orientation.clone().inverse()).add(this.parent.positionWorld);
      } else {
        this.orientationWorld.copy(this.orientation).inverse();
        this.positionWorld.copy(this.position);
      }

      this.state.forces = false;
      for (var i = 0, l = this.forces.length; i < l; i++) {
        this.state.forces = this.state.forces || (typeof this.forces[i].sleepstate == 'function' ? !this.forces[i].sleepstate() : true);
      }
      this.state.accelerating = (this.acceleration && this.acceleration.lengthSq() > lambda);
      this.state.moving = (this.velocity && this.velocity.lengthSq() > lambda);
      this.state.rotating = ((this.angular && this.angular.lengthSq() > lambda) || (this.angularacceleration && this.angularacceleration.lengthSq() > lambda));

      this.state.sleeping = this.paused || !(this.state.forces || this.state.accelerating || this.state.moving || this.state.rotating);
      return this.state.sleeping;
    }

    this.clearAccumulators = function() {
      this.force_accumulator.set(0,0,0);
      this.torque_accumulator.set(0,0,0);
    }
    this.updateAcceleration = function(framedata) {
      this.lastacceleration.copy(this.acceleration);
      if (this.forces.length > 0) {
        this.clearAccumulators();
        for (var k in this.forces) {
          this.forces[k].apply(framedata);
        }
        this.acceleration.copy(this.force_accumulator.divideScalar(this.mass));
        if (this.collider && this.collider.momentInverse) {
          this.angularacceleration.copy(this.torque_accumulator.applyMatrix4(this.collider.momentInverse));
        }
      }
      this.updateState();
      //console.log([this.acceleration.x, this.acceleration.y, this.acceleration.z], [this.angularacceleration.x, this.angularacceleration.y, this.angularacceleration.z]);
    }
    this.applyForce = function(force, relative) {
      this._tmpvec.copy(force);
      if (relative) {
        this.localToWorldDir(this._tmpvec);
      }
      this.force_accumulator.add(this._tmpvec);
    }
    this.applyForceAtPoint = function(force, point, relative) {
      this.applyForce(force, relative);
      this.applyTorque(point.clone().cross(force));
    }
    this.applyTorque = function(torque) {
      this.torque_accumulator.add(torque);
    }
    this.setVelocity = function(vel) {
      this.velocity.copy(vel);
      this.updateState();
    }
    this.addVelocity = function(vel) {
      this.velocity.add(vel);
      this.updateState();
    }
    this.setAngularVelocity = function(vel) {
      this.angular.copy(vel);
      this.updateState();
    }
    this.addAngularVelocity = function(vel) {
      this.angular.add(vel);
      this.updateState();
    }
    this.addForce = function(type, args) {
      var force = false;
      if (typeof elation.physics.forces[type] == 'function') {
        force = new elation.physics.forces[type](this, args);
        this.forces.push(force);
        this.updateAcceleration({});
        this.updateState();
        //console.log('added new force', force);
      } else {
        console.log('Unknown force type: ' + type);
      }
      return force;
    }
    this.removeForce = function(force) {
      var removes = [];
      if (typeof force == 'string') {
        for (var i = 0; i < this.forces.length; i++) {
          if (this.forces[i] instanceof elation.physics.forces[force]) {
            removes.unshift(i);
          }
        }
      } else {
        var idx = this.forces.indexOf(force);
        if (idx > -1) {
          removes.push(idx);
        }
      }
      if (removes.length > 0) {
        removes.sort();
        for (var i = removes.length; i > 0; --i) {
          this.forces.splice(i, 1);
        }
      }
    }
    this.getForces = function(type) {
      var forces = [];
      for (var i = 0; i < this.forces.length; i++) {
        if (this.forces[i] instanceof elation.physics.forces[type]) {
          forces.push(this.forces[i]);
        }
      }
      return (forces.length > 0 ? forces : false);
    }
    this.updateForce = function(name, args) {
      /*
      if (this.forces[name]) {
        this.forces[name].update(args);
      }
      */
    }
    this.addConstraint = function(type, args) {
      var constraint = false;
      if (typeof elation.physics.constraints[type] == 'function') {
        constraint = new elation.physics.constraints[type](this, args);
        this.constraints.push(constraint);
        //this.updateConstraints();
        this.updateState();
        //console.log('added new constraint', constraint);
      } else {
        console.log('Unknown constraint type: ' + type);
      }
      return constraint;
    }
    this.removeConstraint = function(constraint) {
      var removes = [];
      if (typeof constraint == 'string') {
        for (var i = 0; i < this.constraints.length; i++) {
          if (this.constraints[i] instanceof elation.physics.constraints[constraint]) {
            removes.unshift(i);
          }
        }
      } else {
        var idx = this.constraints.indexOf(constraint);
        if (idx > -1) {
          removes.push(idx);
        }
      }
      if (removes.length > 0) {
        removes.sort();
        for (var i = removes.length; i > 0; --i) {
          this.constraints.splice(i, 1);
        }
      }
    }
    /*
    this.updateMoment = function(shape, shapeargs) {
      switch (shape) {
        case 'box':
          var diff = shapeargs.max.clone().sub(shapeargs.min);
          var xsq = diff.x*diff.x,
              ysq = diff.y*diff.y,
              zsq = diff.z*diff.z,
              m = 1/12 * this.mass;
          this.momentInverse.set(
            1 / (m * (ysq + zsq)), 0, 0, 0,
            0, 1 / (m * (xsq + zsq)), 0, 0,
            0, 0, 1 / (m * (xsq + ysq)), 0,
            0, 0, 0, 1);
          break;
        case 'sphere':
          var c = 5 / (2 * this.mass * shapeargs.radius * shapeargs.radius);
          this.momentInverse.set(
            c, 0, 0, 0,
            0, c, 0, 0,
            0, 0, c, 0,
            0, 0, 0, 1);
          break;
        case 'cylinder':
          // FIXME - axes are probably wrong
          var rsq = shapeargs.x * shapeargs.x,
              hsq = shapeargs.y * shapeargs.y,
              xy = 1/(1/12 * m * hsq + 1/4 * m * rsq),
              z = 1/(1/2 * m * rsq);
          this.momentInverse.set(
            xy, 0, 0, 0,
            0, xy, 0, 0,
            0, 0, z, 0,
            0, 0, 0, 1);
          break;
        case 'matrix':
          this.momentInverse.copy(shapeargs);
          break;
        default:
          console.log('Unimplemented inertia moment tensor: ' + shape);
      }
    }
    */

    // Coordinate space transforms

    // world space to local space
    this.worldToLocalPos = function() {
      // closure for scratch variables
      var tmpquat = new THREE.Quaternion();
      return function(point) {
        if (!point) point = new THREE.Vector3();
        if (this.parent) {
          point = this.parent.worldToLocalPos(point);
        }
        return this.parentToLocalPos(point);
      }
    }();
    // local space to world space
    this.localToWorldPos = function(point) {
      point = this.localToParentPos(point);
      if (this.parent) {
        point = this.parent.localToWorldPos(point);
      }
      return point;
    }
    // local space to parent space
    this.localToParentPos = function(point) {
      if (!point) point = new THREE.Vector3();
      return point.applyQuaternion(this.orientation).add(this.position);
    }
    // parent space to local space
    this.parentToLocalPos = function() {
      // closure for scratch variables
      var tmpquat = new THREE.Quaternion();
      return function(point) {
        if (!point) point = new THREE.Vector3();
        return point.sub(this.position).applyQuaternion(tmpquat.copy(this.orientation).inverse());
      }
    }();
    // world direction to local direction
    this.worldToLocalDir = function() {
      // temp variable closure
      var tmpquat = new THREE.Quaternion();
      return function(dir) {
        return dir.applyQuaternion(tmpquat.copy(this.orientationWorld).inverse());
      }
    }();
    // local direction to world direction
    this.localToWorldDir = function(dir) {
      return dir.applyQuaternion(this.orientationWorld);
    }

    this.isPotentiallyColliding = function() {
      // closure scratch vars
      var thispos = new THREE.Vector3(),
          otherpos = new THREE.Vector3(),
          diff = new THREE.Vector3();

      return function(other) {
        other.localToWorldPos(otherpos.set(0,0,0));
        this.localToWorldPos(thispos.set(0,0,0));
        diff.subVectors(otherpos, thispos);
        var radius = this.collider.radius + other.collider.radius;
        return (
          //other.object != this.object.parent &&
          //this.object != other.object.parent &&
          diff.lengthSq() <= radius * radius
         );
      }
    }();
    this.getContacts = function(other, collisions) {
      var hasContacts = false;
      if (this.collider && other.collider) {
        hasContacts = this.collider.getContacts(other.collider, collisions);
      }
      return hasContacts;
    }
    this.setCollider = function(type, colliderargs) {
      if (typeof type == 'object') {
        this.collider = type;
        this.collider.body = this;
      } else {
        if (typeof elation.physics.colliders[type] == 'function') {
          this.collider = new elation.physics.colliders[type](this, colliderargs);
        } else {
          console.log('Unknown collider type ' + type);
        }
      }
      this.collider.getInertialMoment();
    }
    this.setDamping = function(linear, angular) {
      if (typeof angular == 'undefined') angular = linear;
      this.setLinearDamping(linear);
      this.setAngularDamping(angular);
    }
    this.setLinearDamping = function(linear) {
      this.linearDamping = linear;
    }
    this.setAngularDamping = function(angular) {
      this.angularDamping = angular;
    }
    this.add = function(body) {
      var idx = this.children.indexOf(body);
      if (idx == -1) this.children.push(body);
      body.parent = this;
    }
    this.remove = function(body) {
      var idx = this.children.indexOf(body);
      if (idx != -1) {
        this.children.splice(idx,1);
        body.parent = undefined;
      }
    }
    this.processConstraints = function(contactlist) {
      var wasConstrained = false;
      for (var i = 0; i < this.constraints.length; i++) {
        wasConstrained = wasConstrained || this.constraints[i].apply(contactlist);
      }
      return wasConstrained;
    }
    this.init();
  });
});
<|endoftext|>


<commit_before>'use babel';

import fs from 'fs-extra';
import temp from 'temp';
import { vouch } from 'atom-build-spec-helpers';
import { provideBuilder } from '../lib/make';

describe('make', () => {
  let directory;
  const builder = provideBuilder();

  beforeEach(() => {
    waitsForPromise(() => {
      return vouch(temp.mkdir, 'atom-build-make-spec-')
        .then((dir) => vouch(fs.realpath, dir))
        .then((dir) => (directory = `${dir}/`));
    });
  });

  afterEach(() => {
    fs.removeSync(directory);
  });

  describe('when makefile exists', () => {
    it('should be eligible', () => {
      fs.writeFileSync(directory + 'Makefile', fs.readFileSync(__dirname + '/Makefile'));
      expect(builder.isEligable(directory)).toBe(true);
    });

    it('should give default target', () => {
      fs.writeFileSync(directory + 'Makefile', fs.readFileSync(__dirname + '/Makefile'));
      waitsForPromise(() => {
        return Promise.resolve(builder.settings(directory)).then((settings) => {
          expect(settings.length).toBe(1);
          const s = settings[0];
          expect(s.name).toBe('GNU Make: default');
          expect(s.exec).toBe('make');
          expect(s.args).toBe(undefined);
          expect(s.sh).toBe(false);
        });
      });
    });
  });

  describe('when makefile does not exist', () => {
    it('should not be eligible', () => {
      expect(builder.isEligable(directory)).toBe(false);
    });
  });
});
<commit_msg>Fix specs<commit_after>'use babel';

import fs from 'fs-extra';
import temp from 'temp';
import { vouch } from 'atom-build-spec-helpers';
import { provideBuilder } from '../lib/make';

describe('make', () => {
  let directory;
  let builder;
  const Builder = provideBuilder();

  beforeEach(() => {
    waitsForPromise(() => {
      return vouch(temp.mkdir, 'atom-build-make-spec-')
        .then((dir) => vouch(fs.realpath, dir))
        .then((dir) => (directory = `${dir}/`))
        .then((dir) => builder = new Builder(dir));
    });
  });

  afterEach(() => {
    fs.removeSync(directory);
  });

  describe('when makefile exists', () => {
    it('should be eligible', () => {
      fs.writeFileSync(directory + 'Makefile', fs.readFileSync(__dirname + '/Makefile'));
      expect(builder.isEligible(directory)).toBe(true);
    });

    it('should give default target', () => {
      fs.writeFileSync(directory + 'Makefile', fs.readFileSync(__dirname + '/Makefile'));
      waitsForPromise(() => {
        return Promise.resolve(builder.settings(directory)).then((settings) => {
          expect(settings.length).toBe(1);
          const s = settings[0];
          expect(s.name).toBe('GNU Make: default');
          expect(s.exec).toBe('make');
          expect(s.args).toBe(undefined);
          expect(s.sh).toBe(false);
        });
      });
    });
  });

  describe('when makefile does not exist', () => {
    it('should not be eligible', () => {
      expect(builder.isEligible(directory)).toBe(false);
    });
  });
});
<|endoftext|>


<commit_before>var mockCouch = require("mock-couch");
var nanoLib = require("nano");

var ensureNano = require("../index.js");

var couchDb;
var connectionString;
var nano;

beforeEach(function() {
    var tcpPort = 32125;
    couchDb = mockCouch.createServer({ keepAlive: false });
    couchDb.listen(tcpPort);
    connectionString = "http://localhost:" + tcpPort;
    nano = nanoLib(connectionString);
});

afterEach(function() {
    couchDb.close();
});

describe("ensureNano", function() {
    it("can take a nano-object and a database name as an argument and return a nano.db object", function(done) {
        var database = ensureNano(nano, "test-database");

        function recursiveCheck(originalObject, testObject) {
            Object.keys(originalObject).forEach(function(method) {
                expect(testObject[method]).toBeDefined();

                if (typeof testObject[method] == "object") {
                    recursiveCheck(originalObject[method], testObject[method]);
                }
            })
        }

        recursiveCheck(nano.use("test-database"), database);

        expect(database.config.url).toBe(connectionString);
        expect(database.config.db).toBe("test-database");

        done();
    });

    describe("on first request", function() {
        it("it creates the database and insert the document", function(done) {
            spyOn(nano.db, "create").andCallThrough();

            var db = ensureNano(nano, "test-database");
            db.insert({"test": true}, "test", function(error, body) {
                expect(nano.db.create).toHaveBeenCalled();
                expect(nano.db.create.argsForCall[0][0]).toBe("test-database");
                expect(Object.keys(couchDb.databases)[0]).toBe("test-database");
                expect(error).toBeNull();
                expect(body).toBeDefined();
                done();
            });
        });

        it("It inserts the document into the database", function(done) {
            couchDb.addDB("test-database");
            var db = ensureNano(nano, "test-database");

            db.insert({"test": true}, "test", function(error, body) {
                expect(error).toBeNull();
                expect(body).toBeDefined();
                done();
            });
        });
    });

    describe("multiple databases", function() {
        it("can handle more than one database or nano object", function(done) {
            var nano1 = nano;
            var nano2 = nanoLib("http://localhost:5984");

            var db1 = ensureNano(nano1, "db1");
            var db2 = ensureNano(nano2, "db2");

            expect(db1.config.url).toBe(connectionString);
            expect(db1.config.db).toBe("db1");

            expect(db2.config.url).toBe("http://localhost:5984");
            expect(db2.config.db).toBe("db2");

            done();
        });

        it("can insert (and get) documents into/from two different databases", function(done) {
            var db1 = ensureNano(nano, "db1");
            var db2 = ensureNano(nano, "db2");

            db1.insert({"test": true}, "test1", function(error, body) {
                expect(Object.keys(couchDb.databases)[0]).toBe("db1");
                expect(error).toBeNull();
                expect(body).toBeDefined();
                db2.insert({"test": true}, "test2", function(error, body) {
                    expect(Object.keys(couchDb.databases)[1]).toBe("db2");
                    expect(error).toBeNull();
                    expect(body).toBeDefined();
                    db1.get("test1", function(error, document) {
                        expect(error).toBeNull();
                        expect(document).toBeDefined();
                        db2.get("test2", function(error, document) {
                            expect(error).toBeNull();
                            expect(document).toBeDefined();
                            done();
                        });
                    });
                });
            });
        });
    });
});
<commit_msg>Ensure database is only created once<commit_after>var mockCouch = require("mock-couch");
var nanoLib = require("nano");

var ensureNano = require("../index.js");

var couchDb;
var connectionString;
var nano;

beforeEach(function() {
    var tcpPort = 32125;
    couchDb = mockCouch.createServer({ keepAlive: false });
    couchDb.listen(tcpPort);
    connectionString = "http://localhost:" + tcpPort;
    nano = nanoLib(connectionString);
});

afterEach(function() {
    couchDb.close();
});

describe("ensureNano", function() {
    it("can take a nano-object and a database name as an argument and return a nano.db object", function(done) {
        var database = ensureNano(nano, "test-database");

        function recursiveCheck(originalObject, testObject) {
            Object.keys(originalObject).forEach(function(method) {
                expect(testObject[method]).toBeDefined();

                if (typeof testObject[method] == "object") {
                    recursiveCheck(originalObject[method], testObject[method]);
                }
            })
        }

        recursiveCheck(nano.use("test-database"), database);

        expect(database.config.url).toBe(connectionString);
        expect(database.config.db).toBe("test-database");

        done();
    });

    describe("on first request", function() {
        it("it creates the database and insert the document", function(done) {
            spyOn(nano.db, "create").andCallThrough();

            var db = ensureNano(nano, "test-database");
            db.insert({"test": true}, "test", function(error, body) {
                expect(nano.db.create).toHaveBeenCalled();
                expect(nano.db.create.argsForCall[0][0]).toBe("test-database");
                expect(Object.keys(couchDb.databases)[0]).toBe("test-database");
                expect(error).toBeNull();
                expect(body).toBeDefined();
                done();
            });
        });

        it("It inserts the document into the database", function(done) {
            couchDb.addDB("test-database");
            var db = ensureNano(nano, "test-database");

            db.insert({"test": true}, "test", function(error, body) {
                expect(error).toBeNull();
                expect(body).toBeDefined();
                done();
            });
        });

        it("it only makes one call to create the database", function(done) {
            spyOn(nano.db, "create").andCallThrough();

            var db = ensureNano(nano, "test-database");
            db.insert({"test": true}, "test", function(error, body) {
                expect(nano.db.create).toHaveBeenCalled();
                expect(nano.db.create.argsForCall[0][0]).toBe("test-database");
                expect(Object.keys(couchDb.databases)[0]).toBe("test-database");
                expect(error).toBeNull();
                expect(body).toBeDefined();
                db.get("test", function(error, body) {
                    expect(error).toBeNull();
                    expect(body.test).toBe(true);
                    expect(nano.db.create.callCount).toBe(1);
                    done();
                });
            });
        });
    });

    describe("multiple databases", function() {
        it("can handle more than one database or nano object", function(done) {
            var nano1 = nano;
            var nano2 = nanoLib("http://localhost:5984");

            var db1 = ensureNano(nano1, "db1");
            var db2 = ensureNano(nano2, "db2");

            expect(db1.config.url).toBe(connectionString);
            expect(db1.config.db).toBe("db1");

            expect(db2.config.url).toBe("http://localhost:5984");
            expect(db2.config.db).toBe("db2");

            done();
        });

        it("can insert (and get) documents into/from two different databases", function(done) {
            var db1 = ensureNano(nano, "db1");
            var db2 = ensureNano(nano, "db2");

            db1.insert({"test": true}, "test1", function(error, body) {
                expect(Object.keys(couchDb.databases)[0]).toBe("db1");
                expect(error).toBeNull();
                expect(body).toBeDefined();
                db2.insert({"test": true}, "test2", function(error, body) {
                    expect(Object.keys(couchDb.databases)[1]).toBe("db2");
                    expect(error).toBeNull();
                    expect(body).toBeDefined();
                    db1.get("test1", function(error, document) {
                        expect(error).toBeNull();
                        expect(document).toBeDefined();
                        db2.get("test2", function(error, document) {
                            expect(error).toBeNull();
                            expect(document).toBeDefined();
                            done();
                        });
                    });
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>const getPixels = require('get-pixels');
const quantize = require('quantize');

function createPixelArray(imgData, pixelCount, quality) {
    const pixels = imgData;
    const pixelArray = [];

    for (let i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {
        offset = i * 4;
        r = pixels[offset + 0];
        g = pixels[offset + 1];
        b = pixels[offset + 2];
        a = pixels[offset + 3];

        // If pixel is mostly opaque and not white
        if (typeof a === 'undefined' || a >= 125) {
            if (!(r > 250 && g > 250 && b > 250)) {
                pixelArray.push([r, g, b]);
            }
        }
    }
    return pixelArray;
}

function validateOptions(options) {
    let { colorCount, quality } = options;

    if (typeof colorCount === 'undefined' || !Number.isInteger(colorCount)) {
        colorCount = 10;
    } else if (colorCount === 1 ) {
        throw new Error('colorCount should be between 2 and 20. To get one color, call getColor() instead of getPalette()');
    } else {
        colorCount = Math.max(colorCount, 2);
        colorCount = Math.min(colorCount, 20);
    }

    if (typeof quality === 'undefined' || Number.isInteger(quality)) {
        quality = 10;
    } else if (quality < 1) {
        quality = 10;
    }

    return {
        colorCount,
        quality
    }
}

function loadImg(img) {
    return new Promise((resolve, reject) => {
        getPixels(img, function(err, data) {
            if(err) {
                reject(err)
            } else {
                resolve(data);
            }
        })
    });
}

function getColor(img, quality) {
    return new Promise((resolve, reject) => {
        getPalette(img, 5, quality)
            .then(palette => {
                resolve(palette[0]);
            })
            .catch(err => {
                reject(err);
            })
    });

}

function getPalette(img, colorCount = 10, quality = 10) {
    const options = validateOptions({
        colorCount,
        quality
    });

    return new Promise((resolve, reject) => {
        loadImg(img)
            .then(imgData => {
                const pixelCount = imgData.shape[0] * imgData.shape[1];
                const pixelArray = createPixelArray(imgData.data, pixelCount, options.quality);

                const cmap = quantize(pixelArray, options.colorCount);
                const palette = cmap? cmap.palette() : null;

                resolve(palette);
            })
            .catch(err => {
                reject(err);
            })
    });
}

module.exports = {
    getColor,
    getPalette
};

<commit_msg>adds identical quality option fix to color-thief-node.js<commit_after>const getPixels = require('get-pixels');
const quantize = require('quantize');

function createPixelArray(imgData, pixelCount, quality) {
    const pixels = imgData;
    const pixelArray = [];

    for (let i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {
        offset = i * 4;
        r = pixels[offset + 0];
        g = pixels[offset + 1];
        b = pixels[offset + 2];
        a = pixels[offset + 3];

        // If pixel is mostly opaque and not white
        if (typeof a === 'undefined' || a >= 125) {
            if (!(r > 250 && g > 250 && b > 250)) {
                pixelArray.push([r, g, b]);
            }
        }
    }
    return pixelArray;
}

function validateOptions(options) {
    let { colorCount, quality } = options;

    if (typeof colorCount === 'undefined' || !Number.isInteger(colorCount)) {
        colorCount = 10;
    } else if (colorCount === 1 ) {
        throw new Error('colorCount should be between 2 and 20. To get one color, call getColor() instead of getPalette()');
    } else {
        colorCount = Math.max(colorCount, 2);
        colorCount = Math.min(colorCount, 20);
    }

    if (typeof quality === 'undefined' || !Number.isInteger(quality) || quality < 1) {
        quality = 10;
    }

    return {
        colorCount,
        quality
    }
}

function loadImg(img) {
    return new Promise((resolve, reject) => {
        getPixels(img, function(err, data) {
            if(err) {
                reject(err)
            } else {
                resolve(data);
            }
        })
    });
}

function getColor(img, quality) {
    return new Promise((resolve, reject) => {
        getPalette(img, 5, quality)
            .then(palette => {
                resolve(palette[0]);
            })
            .catch(err => {
                reject(err);
            })
    });

}

function getPalette(img, colorCount = 10, quality = 10) {
    const options = validateOptions({
        colorCount,
        quality
    });

    return new Promise((resolve, reject) => {
        loadImg(img)
            .then(imgData => {
                const pixelCount = imgData.shape[0] * imgData.shape[1];
                const pixelArray = createPixelArray(imgData.data, pixelCount, options.quality);

                const cmap = quantize(pixelArray, options.colorCount);
                const palette = cmap? cmap.palette() : null;

                resolve(palette);
            })
            .catch(err => {
                reject(err);
            })
    });
}

module.exports = {
    getColor,
    getPalette
};

<|endoftext|>


<commit_before>const config = require('../config.js')
const log = require('../util/logger.js')
const MenuUtils = require('../structs/MenuUtils.js')
const moment = require('moment')
const storage = require('../util/storage.js')
const Translator = require('../structs/Translator.js')
const GuildProfile = require('../structs/db/GuildProfile.js')
const AssignedSchedule = require('../structs/db/AssignedSchedule.js')
const FailCounter = require('../structs/db/FailCounter.js')
const Supporter = require('../structs/db/Supporter.js')
const Feed = require('../structs/db/Feed.js')

module.exports = async (bot, message, command) => {
  try {
    const [ profile, supporter ] = await Promise.all([
      GuildProfile.get(message.guild.id),
      Supporter.getValidSupporterOfGuild(message.guild.id)
    ])
    const translate = Translator.createLocaleTranslator(profile ? profile.locale : undefined)
    const feeds = await Feed.getManyBy('guild', message.guild.id)
    if (feeds.length === 0) {
      return await message.channel.send(translate('commands.rsslist.noFeeds'))
    }

    const failedLinks = {}
    const maxFeedsAllowed = supporter ? await supporter.getMaxFeeds() : config.feeds.max

    // Generate the info for each feed as an array, and push into another array
    const failCounters = await Promise.all(feeds.map(feed => FailCounter.getBy('url', feed.url)))
    const shard = message.client.shard && message.client.shard.count > 0 ? message.client.shard.id : -1
    const schedulesToFetch = feeds.map(feed => AssignedSchedule.getByFeedAndShard(feed._id, shard))
    const schedulesByFeedIDs = {}

    const assignedSchedules = await Promise.all(schedulesToFetch)

    for (const counter of failCounters) {
      if (counter) {
        failedLinks[counter.url] = counter
      }
    }
    for (const assigned of assignedSchedules) {
      schedulesByFeedIDs[assigned.feed] = assigned
    }

    let vipDetails = ''
    if (supporter) {
      vipDetails += '**Patron Until:** '
      if (supporter.expireAt) {
        const expireAt = moment(supporter.expireAt)
        const daysLeft = Math.round(moment.duration(expireAt.diff(moment())).asDays())
        vipDetails += `${expireAt.format('D MMMM YYYY')} (${daysLeft} days)\n`
      } else {
        vipDetails += 'Ongoing\n'
      }
    } else {
      vipDetails = '\n'
    }

    let desc = maxFeedsAllowed === 0 ? `${vipDetails}\u200b\n` : `${vipDetails}**${translate('commands.rsslist.serverLimit')}:** ${feeds.length}/${maxFeedsAllowed} [＋](https://www.patreon.com/discordrss)\n\n\u200b`
    // desc += failedFeedCount > 0 ? translate('commands.rsslist.failAlert', { failLimit: FAIL_LIMIT, prefix: profile.prefix || config.bot.prefix }) : ''

    const list = new MenuUtils.Menu(message)
      .setAuthor(translate('commands.rsslist.currentActiveFeeds'))
      .setDescription(desc)

    if (supporter) {
      list.setFooter(`Patronage backed by ${supporter._id}`)
    }

    feeds.forEach(feed => {
      // URL
      const url = feed.url.length > 500 ? translate('commands.rsslist.exceeds500Characters') : feed.url

      // Title
      const title = feed.title

      // Channel
      const channelName = bot.channels.get(feed.channel) ? bot.channels.get(feed.channel).name : 'Unknown'

      // Status
      let status = ''
      if (feed.disabled) {
        status = translate('commands.rsslist.statusDisabled', { reason: feed.disabled })
      } else if (FailCounter.limit !== 0) {
        const failCounter = failedLinks[feed.url]
        const count = !failCounter ? 0 : failCounter.count
        if (!failCounter || !failCounter.hasFailed()) {
          const failCountText = count > Math.ceil(FailCounter.limit / 5) ? `(failed ${count}/${FailCounter.limit} times` : ''
          status = translate('commands.rsslist.statusOk', { failCount: failCountText })
        } else {
          status = translate('commands.rsslist.statusFailed')
        }
      }

      // Title checks
      const titleChecks = feed.checkTitles === true ? translate('commands.rsslist.titleChecksEnabled') : ''

      // Webhook
      const webhook = feed.webhook ? `${translate('commands.rsslist.webhook')}: ${feed.webhook.id}\n` : ''

      // Refresh rate
      const schedule = storage.scheduleManager.getSchedule(schedulesByFeedIDs[feed._id].schedule)
      let refreshRate = schedule ? schedule.refreshRate < 1 ? `${schedule.refreshRate * 60} ${translate('commands.rsslist.seconds')}` : `${schedule.refreshRate} ${translate('commands.rsslist.minutes')}` : translate('commands.rsslist.unknown')

      // Patreon link
      if (Supporter.enabled && !supporter) {
        refreshRate += ' [－](https://www.patreon.com/discordrss)'
      }
      list.addOption(`${title.length > 200 ? title.slice(0, 200) + '[...]' : title}`, `${titleChecks}${status}${translate('generics.channelUpper')}: #${channelName}\n${translate('commands.rsslist.refreshRate')}: ${refreshRate}\n${webhook}${translate('commands.rsslist.link')}: ${url}`)
    })

    await list.send()
  } catch (err) {
    log.command.warning(`rsslist`, message.guild, err)
    if (err.code !== 50013) message.channel.send(err.message).catch(err => log.command.warning('rsslist 1', message.guild, err))
  }
}
<commit_msg>Rewrite rsslist to not use AssignedSchedule<commit_after>const config = require('../config.js')
const log = require('../util/logger.js')
const MenuUtils = require('../structs/MenuUtils.js')
const moment = require('moment')
const Schedule = require('../structs/db/Schedule.js')
const Translator = require('../structs/Translator.js')
const GuildProfile = require('../structs/db/GuildProfile.js')
const FailCounter = require('../structs/db/FailCounter.js')
const Supporter = require('../structs/db/Supporter.js')
const Feed = require('../structs/db/Feed.js')

module.exports = async (bot, message, command) => {
  try {
    const [ profile, supporter, schedules, supporterGuilds ] = await Promise.all([
      GuildProfile.get(message.guild.id),
      Supporter.getValidSupporterOfGuild(message.guild.id),
      Schedule.getAll(),
      Supporter.getValidGuilds()
    ])
    const translate = Translator.createLocaleTranslator(profile ? profile.locale : undefined)
    const feeds = await Feed.getManyBy('guild', message.guild.id)
    if (feeds.length === 0) {
      return await message.channel.send(translate('commands.rsslist.noFeeds'))
    }

    const failedLinks = {}
    const maxFeedsAllowed = supporter ? await supporter.getMaxFeeds() : config.feeds.max

    // Generate the info for each feed as an array, and push into another array
    const failCounters = await Promise.all(feeds.map(feed => FailCounter.getBy('url', feed.url)))
    const fetchedSchedules = await Promise.all(feeds.map(feed => feed.determineSchedule(schedules, supporterGuilds)))

    for (const counter of failCounters) {
      if (counter) {
        failedLinks[counter.url] = counter
      }
    }
    let vipDetails = ''
    if (supporter) {
      vipDetails += '**Patron Until:** '
      if (supporter.expireAt) {
        const expireAt = moment(supporter.expireAt)
        const daysLeft = Math.round(moment.duration(expireAt.diff(moment())).asDays())
        vipDetails += `${expireAt.format('D MMMM YYYY')} (${daysLeft} days)\n`
      } else {
        vipDetails += 'Ongoing\n'
      }
    } else {
      vipDetails = '\n'
    }

    let desc = maxFeedsAllowed === 0 ? `${vipDetails}\u200b\n` : `${vipDetails}**${translate('commands.rsslist.serverLimit')}:** ${feeds.length}/${maxFeedsAllowed} [＋](https://www.patreon.com/discordrss)\n\n\u200b`
    // desc += failedFeedCount > 0 ? translate('commands.rsslist.failAlert', { failLimit: FAIL_LIMIT, prefix: profile.prefix || config.bot.prefix }) : ''

    const list = new MenuUtils.Menu(message)
      .setAuthor(translate('commands.rsslist.currentActiveFeeds'))
      .setDescription(desc)

    if (supporter) {
      list.setFooter(`Patronage backed by ${supporter._id}`)
    }

    feeds.forEach((feed, i) => {
      // URL
      const url = feed.url.length > 500 ? translate('commands.rsslist.exceeds500Characters') : feed.url

      // Title
      const title = feed.title

      // Channel
      const channelName = bot.channels.get(feed.channel) ? bot.channels.get(feed.channel).name : 'Unknown'

      // Status
      let status = ''
      if (feed.disabled) {
        status = translate('commands.rsslist.statusDisabled', { reason: feed.disabled })
      } else if (FailCounter.limit !== 0) {
        const failCounter = failedLinks[feed.url]
        const count = !failCounter ? 0 : failCounter.count
        if (!failCounter || !failCounter.hasFailed()) {
          const failCountText = count > Math.ceil(FailCounter.limit / 5) ? `(failed ${count}/${FailCounter.limit} times` : ''
          status = translate('commands.rsslist.statusOk', { failCount: failCountText })
        } else {
          status = translate('commands.rsslist.statusFailed')
        }
      }

      // Title checks
      const titleChecks = feed.checkTitles === true ? translate('commands.rsslist.titleChecksEnabled') : ''

      // Webhook
      const webhook = feed.webhook ? `${translate('commands.rsslist.webhook')}: ${feed.webhook.id}\n` : ''

      // Refresh rate
      const schedule = fetchedSchedules[i]
      let refreshRate = schedule.refreshRateMinutes < 1 ? `${schedule.refreshRateMinutes * 60} ${translate('commands.rsslist.seconds')}` : `${schedule.refreshRateMinutes} ${translate('commands.rsslist.minutes')}`
      // : translate('commands.rsslist.unknown')

      // Patreon link
      if (Supporter.enabled && !supporter) {
        refreshRate += ' [－](https://www.patreon.com/discordrss)'
      }
      list.addOption(`${title.length > 200 ? title.slice(0, 200) + '[...]' : title}`, `${titleChecks}${status}${translate('generics.channelUpper')}: #${channelName}\n${translate('commands.rsslist.refreshRate')}: ${refreshRate}\n${webhook}${translate('commands.rsslist.link')}: ${url}`)
    })

    await list.send()
  } catch (err) {
    log.command.warning(`rsslist`, message.guild, err)
    if (err.code !== 50013) message.channel.send(err.message).catch(err => log.command.warning('rsslist 1', message.guild, err))
  }
}
<|endoftext|>


<commit_before>'use babel';
/* eslint-env jasmine */

describe('The php -l provider for Linter', () => {
  const lint = require('../lib/main').provideLinter().lint;

  beforeEach(() => {
    atom.workspace.destroyActivePaneItem();
    waitsForPromise(() => {
      atom.packages.activatePackage('linter-php');
      return atom.packages.activatePackage('language-php').then(() =>
        atom.workspace.open(__dirname + '/files/bad.php')
      );
    });
  });

  it('should be in the packages list', () => {
    return expect(atom.packages.isPackageLoaded('linter-php')).toBe(true);
  });

  it('should be an active package', () => {
    return expect(atom.packages.isPackageActive('linter-php')).toBe(true);
  });

  describe('checks bad.php and', () => {
    let editor = null;
    beforeEach(() => {
      waitsForPromise(() => {
        return atom.workspace.open(__dirname + '/files/bad.php').then(openEditor => {
          editor = openEditor;
        });
      });
    });

    it('finds at least one message', () => {
      waitsForPromise(() => {
        return lint(editor).then(messages => {
          expect(messages.length).toEqual(1);
        });
      });
    });

    it('verifies that message', () => {
      waitsForPromise(() => {
        return lint(editor).then(messages => {
          expect(messages[0].type).toBeDefined();
          expect(messages[0].type).toEqual('Error');
          expect(messages[0].text).toBeDefined();
          expect(messages[0].text).toEqual('syntax error, unexpected \'{\' in -');
          expect(messages[0].filePath).toBeDefined();
          expect(messages[0].filePath).toMatch(/.+bad\.php$/);
          expect(messages[0].range).toBeDefined();
          expect(messages[0].range.length).toEqual(2);
          expect(messages[0].range).toEqual([[1, 0], [1, 5]]);
        });
      });
    });
  });

  it('finds nothing wrong with an empty file', () => {
    waitsForPromise(() => {
      return atom.workspace.open(__dirname + '/files/empty.php').then(editor => {
        return lint(editor).then(messages => {
          expect(messages.length).toEqual(0);
        });
      });
    });
  });

  it('finds nothing wrong with a valid file', () => {
    waitsForPromise(() => {
      return atom.workspace.open(__dirname + '/files/good.php').then(editor => {
        return lint(editor).then(messages => {
          expect(messages.length).toEqual(0);
        });
      });
    });
  });
});
<commit_msg>Correct the range<commit_after>'use babel';
/* eslint-env jasmine */

describe('The php -l provider for Linter', () => {
  const lint = require('../lib/main').provideLinter().lint;

  beforeEach(() => {
    atom.workspace.destroyActivePaneItem();
    waitsForPromise(() => {
      atom.packages.activatePackage('linter-php');
      return atom.packages.activatePackage('language-php').then(() =>
        atom.workspace.open(__dirname + '/files/bad.php')
      );
    });
  });

  it('should be in the packages list', () => {
    return expect(atom.packages.isPackageLoaded('linter-php')).toBe(true);
  });

  it('should be an active package', () => {
    return expect(atom.packages.isPackageActive('linter-php')).toBe(true);
  });

  describe('checks bad.php and', () => {
    let editor = null;
    beforeEach(() => {
      waitsForPromise(() => {
        return atom.workspace.open(__dirname + '/files/bad.php').then(openEditor => {
          editor = openEditor;
        });
      });
    });

    it('finds at least one message', () => {
      waitsForPromise(() => {
        return lint(editor).then(messages => {
          expect(messages.length).toEqual(1);
        });
      });
    });

    it('verifies that message', () => {
      waitsForPromise(() => {
        return lint(editor).then(messages => {
          expect(messages[0].type).toBeDefined();
          expect(messages[0].type).toEqual('Error');
          expect(messages[0].text).toBeDefined();
          expect(messages[0].text).toEqual('syntax error, unexpected \'{\' in -');
          expect(messages[0].filePath).toBeDefined();
          expect(messages[0].filePath).toMatch(/.+bad\.php$/);
          expect(messages[0].range).toBeDefined();
          expect(messages[0].range.length).toEqual(2);
          expect(messages[0].range).toEqual([[1, 0], [1, 6]]);
        });
      });
    });
  });

  it('finds nothing wrong with an empty file', () => {
    waitsForPromise(() => {
      return atom.workspace.open(__dirname + '/files/empty.php').then(editor => {
        return lint(editor).then(messages => {
          expect(messages.length).toEqual(0);
        });
      });
    });
  });

  it('finds nothing wrong with a valid file', () => {
    waitsForPromise(() => {
      return atom.workspace.open(__dirname + '/files/good.php').then(editor => {
        return lint(editor).then(messages => {
          expect(messages.length).toEqual(0);
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
  * Copyright 2016 Benjamin Blais
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */

/**
 * Modified version of pageBuilder from templatizer, used primaraly to generate
 * blog content, should always be run in root
 */
"use strict";
var fs = require('fs');
var path = require('path');
var htmlTemplatize = require('./Templateizer/htmlTemplatize');

//Define constants used for configuration
const outputHtmlName = "index.html";
const headerImageName = "header.jpg";

const titleGenerator = (context) => {

  const titleFileName = path.basename(context.partialPath, '.html');

  const title = titleFileName.replace(/([a-z])([A-Z])/g, '$1 $2');

  return title;

};

//Add function for title
htmlTemplatize.registerCommand('title', titleGenerator);

htmlTemplatize.registerCommand('postList', (context, args) => {

  if(args.length < 1)
  {
    console.error(`Cannot generate post list for ${context.templatePath}, no post template was provided`);
    return "";
  }

  let result = "";

  //Clone the array and remove this partial
  let postList = context.allPartials.slice(0);
  postList.splice(postList.indexOf(context.templatePath), 1);

  //Sort the new array
  postList.sort();

  let meOutPath = path.dirname(context.templatePath);

  //Get the template for the post list
  let postListItemTemplatePath = path.normalize(args[0]);

  //If this is not a full path then append the path to the template path
  if(!/^([A-Za-z]:)?[\\\/]/.test(postListItemTemplatePath))
  {
    postListItemTemplatePath = meOutPath + "/" + postListItemTemplatePath;
  }

  //Read the template in so we can parse it for each item on the list
  const postListItemTemplate = fs.readFileSync(postListItemTemplatePath, {encoding: "UTF-8"});

  //Copy the context so that we can swap out the template and generate a text output.
  const itemContext = htmlTemplatize.util.copyContext(context);

  //Now generate a string for elements
  for(let item of postList)
  {
    console.log(`Item is ${item}`);

    //Generate the output path
    let outputPath = item;
    outputPath = path.relative(meOutPath, outputPath);
    outputPath = path.dirname(outputPath) + "/" + outputHtmlName;
    outputPath = outputPath.replace(/\\/g, "/");

    //Get the output image path
    let outputImage = path.dirname(outputPath) + "/header.jpg";

    let outputTitle = titleGenerator({partialPath : item});

    //Set the values for the context
    itemContext.outputPath = outputPath;
    itemContext.outputImage = outputImage;
    itemContext.title = outputTitle;

    let itemResult = htmlTemplatize.templatizeString(postListItemTemplate, itemContext);

    result += itemResult + "\n";
  }

  return result;
});

fs.mkdirParentSync = function(dirPath, mode)
{
  //Try to find parent dir
  try
  {
    fs.mkdirSync(dirPath, mode);
  }
  catch(error)
  {
    console.log("entered catch");
    if(error.code && error.code === 'ENOENT')
    {
      console.log(`calling folder ${path.dirname(dirPath)}`);
      //Attempt to make parent folder(s)
      fs.mkdirParentSync(path.dirname(dirPath), mode);
      fs.mkdirParentSync(dirPath, mode);
    }
    else
    {
      //Rethrow error if not because dir doesn't exist
      throw error;
    }
  }

  //Parents are made, make the child
  fs.mkdirSync(dirPath, mode);
};

var partialList = [];

var outList = [];

//Start by getting the template
var templateArg = "template.html";

//Then the partial dir
var partialPath = "partials/"

//Finally get the output dir
var outputDirArg = ".";

//Handle this as a stack
let stack = [partialPath];

//Get all the children of the directory itteratively
while(stack.length > 0)
{
  let value = stack.pop();

  //Check for directory
  let info = fs.lstatSync(value);

  if(info.isFile())
  {
    //Check for html extension
    if(path.extname(value) === '.html')
    {
      partialList.push(value);
    }
  }
  else
  {
    //Get the children and add them to the stack
    let children  = fs.readdirSync(value, "UTF-8");

    for(let index in children)
    {
      let child = children[index]
      let fullPath = value + path.sep + child;
      stack.push(fullPath);
    }
  }
}

//Create the output dirs
for(let index = 0; index < partialList.length; ++index)
{
  let outputValue = path.normalize(partialList[index].replace(partialPath, outputDirArg));

  //The blog needs to have all the entries renamed to the proper output name
  let dirName = path.dirname(outputValue);
  let correctedOutputValue = dirName + "/" + outputHtmlName;

  outList[index] = correctedOutputValue;
  try
  {
    fs.mkdirParentSync(path.dirname(outputValue));
  }
  catch(error)
  {
    if(error.code !== 'EEXIST')
    {
      throw error;
    }
  }

  let imageFromPath = path.dirname(partialList[index]) + "/" + headerImageName;
  let imageToPath = dirName + "/" + headerImageName;

  if(fs.statSync(imageToPath).isFile() && fs.statSync(imageToPath).isFile())
  {
    //Copy header.jpg to the destination directory
    fs.createReadStream(imageFromPath).on('error', _ => null).pipe(fs.createWriteStream(imageToPath).on('error', _ => null));
  }
}

((template, partials, output, ctx) => {
  htmlTemplatize.templatize(template, partials, output, ctx);
})(templateArg, partialList, outList, {outputBase : outputDirArg, partialBase : partialPath, allPartials : partialList});<commit_msg>Added date generator to page builder<commit_after>/**
  * Copyright 2016 Benjamin Blais
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */

/**
 * Modified version of pageBuilder from templatizer, used primaraly to generate
 * blog content, should always be run in root
 */
"use strict";
var fs = require('fs');
var path = require('path');
var htmlTemplatize = require('./Templateizer/htmlTemplatize');

//Define constants used for configuration
const outputHtmlName = "index.html";
const headerImageName = "header.jpg";

const titleGenerator = (context) => {

  const titleFileName = path.basename(context.partialPath, '.html');

  const title = titleFileName.replace(/([a-z])([A-Z])/g, '$1 $2');

  return title;

};

const dateGenerator = (context) => {
  const outputPath = context.outputPath;

  const fileRemoved = path.dirname(outputPath);

  const isoDate = fileRemoved.replace('articles/' , '');

  return isoDate;
}

const humanReadableDate = (context) => {

  const months = ['January', 'February', 'March', 'April', 'May', 'June',
                  'July', 'August', 'September', 'October', 'November',
                  'December'];
  const isoDate = dateGenerator(context);
  const date = isoDate.split('/');

  if(date.length < 3)
  {
    return isoDate;
  }

  const year = date[0];
  const monthNumber = Number(date[1]);
  const dayOfMonth = date[2];

  const month = months[monthNumber - 1];

  return `${month} ${dayOfMonth}, ${year}`;
}

//Add function for title
htmlTemplatize.registerCommand('title', titleGenerator);

htmlTemplatize.registerCommand('postList', (context, args) => {

  if(args.length < 1)
  {
    console.error(`Cannot generate post list for ${context.templatePath}, no post template was provided`);
    return "";
  }

  let result = "";

  //Clone the array and remove this partial
  let postList = context.allPartials.slice(0);
  postList.splice(postList.indexOf(context.templatePath), 1);

  //Sort the new array
  postList.sort();

  let meOutPath = path.dirname(context.templatePath);

  //Get the template for the post list
  let postListItemTemplatePath = path.normalize(args[0]);

  //If this is not a full path then append the path to the template path
  if(!/^([A-Za-z]:)?[\\\/]/.test(postListItemTemplatePath))
  {
    postListItemTemplatePath = meOutPath + "/" + postListItemTemplatePath;
  }

  //Read the template in so we can parse it for each item on the list
  const postListItemTemplate = fs.readFileSync(postListItemTemplatePath, {encoding: "UTF-8"});

  //Copy the context so that we can swap out the template and generate a text output.
  const itemContext = htmlTemplatize.util.copyContext(context);

  //Now generate a string for elements
  for(let item of postList)
  {
    console.log(`Item is ${item}`);

    //Generate the output path
    let outputPath = item;
    outputPath = path.relative(meOutPath, outputPath);
    outputPath = path.dirname(outputPath) + "/" + outputHtmlName;
    outputPath = outputPath.replace(/\\/g, "/");

    //Get the output image path
    let outputImage = path.dirname(outputPath) + "/header.jpg";

    let outputTitle = titleGenerator({partialPath : item});

    //Generate the date
    let outputDate = humanReadableDate({outputPath: outputPath});

    //Set the values for the context
    itemContext.outputPath = outputPath;
    itemContext.outputImage = outputImage;
    itemContext.title = outputTitle;
    itemContext.date = outputDate;

    let itemResult = htmlTemplatize.templatizeString(postListItemTemplate, itemContext);

    result += itemResult + "\n";
  }

  return result;
});

fs.mkdirParentSync = function(dirPath, mode)
{
  //Try to find parent dir
  try
  {
    fs.mkdirSync(dirPath, mode);
  }
  catch(error)
  {
    console.log("entered catch");
    if(error.code && error.code === 'ENOENT')
    {
      console.log(`calling folder ${path.dirname(dirPath)}`);
      //Attempt to make parent folder(s)
      fs.mkdirParentSync(path.dirname(dirPath), mode);
      fs.mkdirParentSync(dirPath, mode);
    }
    else
    {
      //Rethrow error if not because dir doesn't exist
      throw error;
    }
  }

  //Parents are made, make the child
  fs.mkdirSync(dirPath, mode);
};

var partialList = [];

var outList = [];

//Start by getting the template
var templateArg = "template.html";

//Then the partial dir
var partialPath = "partials/"

//Finally get the output dir
var outputDirArg = ".";

//Handle this as a stack
let stack = [partialPath];

//Get all the children of the directory itteratively
while(stack.length > 0)
{
  let value = stack.pop();

  //Check for directory
  let info = fs.lstatSync(value);

  if(info.isFile())
  {
    //Check for html extension
    if(path.extname(value) === '.html')
    {
      partialList.push(value);
    }
  }
  else
  {
    //Get the children and add them to the stack
    let children  = fs.readdirSync(value, "UTF-8");

    for(let index in children)
    {
      let child = children[index]
      let fullPath = value + path.sep + child;
      stack.push(fullPath);
    }
  }
}

//Create the output dirs
for(let index = 0; index < partialList.length; ++index)
{
  let outputValue = path.normalize(partialList[index].replace(partialPath, outputDirArg));

  //The blog needs to have all the entries renamed to the proper output name
  let dirName = path.dirname(outputValue);
  let correctedOutputValue = dirName + "/" + outputHtmlName;

  outList[index] = correctedOutputValue;
  try
  {
    fs.mkdirParentSync(path.dirname(outputValue));
  }
  catch(error)
  {
    if(error.code !== 'EEXIST')
    {
      throw error;
    }
  }

  let imageFromPath = path.dirname(partialList[index]) + "/" + headerImageName;
  let imageToPath = dirName + "/" + headerImageName;

  if(fs.statSync(imageFromPath).isFile())
  {
    //Copy header.jpg to the destination directory
    fs.createReadStream(imageFromPath).on('error', _ => null).pipe(fs.createWriteStream(imageToPath).on('error', _ => null));
  }
}

((template, partials, output, ctx) => {
  htmlTemplatize.templatize(template, partials, output, ctx);
})(templateArg, partialList, outList, {outputBase : outputDirArg, partialBase : partialPath, allPartials : partialList});<|endoftext|>