<commit_before>import fs from "fs";
import { join, parse } from "path";
import matter from "gray-matter";
import toml from "@iarna/toml";
import { DateTime } from "luxon";

const directories = (dir) => {
  switch (dir) {
    case "blog":
      return join(process.cwd(), "content/blog");
    case "events":
      return join(process.cwd(), "content/events");
    case "docs":
      return join(process.cwd(), "content/docs");
    case "grants":
      return join(process.cwd(), "content/grants");
    case "media":
      return join(process.cwd(), "content/media");
    case "updates":
      return join(process.cwd(), "content/updates");
    case "/":
      return join(process.cwd(), "content");
    default:
      return join(process.cwd(), `content/${dir}`);
  }
};

export function getPostSlugs(key) {
  const dir = fs.existsSync(directories(key))
    ? fs.readdirSync(directories(key), { withFileTypes: true })
    : [];
  return dir
    .filter((f) => f.isFile() && f.name !== "_index.md")
    .map((f) => f.name);
}

// NB Gavin: This could be much simpler if we converted everything to a more common standard, like YAML
const options = {
  engines: {
    toml: toml.parse.bind(toml),
  },
  language: "toml",
  delimiters: "+++",
};

export function getPostBySlug(slug, fields = [], key) {
  const realSlug = slug.replace(/\.md$/, "");
  const fullPath = join(directories(key), `${realSlug}.md`);
  const fileContents = fs.readFileSync(fullPath, "utf8");
  const { data, content } = matter(fileContents, options);
  const items = {};

  // Ensure only the minimal needed data is exposed
  fields.forEach((field) => {
    if (field === "slug") {
      items[field] = realSlug;
    }

    if (field === "content") {
      items[field] = content;
    }

    if (data[field]) {
      items[field] = data[field];
    }
  });

  return items;
}

export function getAllPosts(fields = [], key, sort = "") {
  const slugs = getPostSlugs(key);
  const posts = slugs
    .map((slug) => getPostBySlug(slug, fields, key))
    // sort posts by date in descending order
    .sort((post1, post2) => {
      if (sort === "date") {
        return DateTime.fromISO(post1.date) > DateTime.fromISO(post2.date)
          ? -1
          : 1;
      } else if (sort === "weight") {
        return post1.weight > post2.weight ? -1 : 1;
      }
    });
  return posts;
}

export function getAllEvents(fields = [], key) {
  const slugs = getPostSlugs(key);
  const posts = slugs
    .map((slug) => getPostBySlug(slug, fields, key))
    // sort posts by date in descending order
    .sort((post1, post2) =>
      DateTime.fromISO(post1.starts) > DateTime.fromISO(post2.starts) ? -1 : 1
    );
  return posts;
}

function getAllPaths(dirPath, arrayOfFiles) {
  let files = fs.readdirSync(dirPath);

  arrayOfFiles = arrayOfFiles || [];

  files.forEach(function (file) {
    if (fs.statSync(dirPath + "/" + file).isDirectory()) {
      arrayOfFiles = getAllPaths(dirPath + "/" + file, arrayOfFiles);
    } else {
      arrayOfFiles.push(join(dirPath, "/", file));
    }
  });

  return arrayOfFiles;
}

export function getDocsPaths() {
  return getAllPaths(directories("docs"), []);
}

export function getNextPost(slug, fields = [], key, sort = "date") {
  let resultPost = null;

  getAllPosts(fields, key, sort).forEach((post, index, array) => {
    if (post.slug === slug) {
      if (typeof array[index - 1] !== "undefined") {
        resultPost = array[index - 1];
      }
    }
  });
  return resultPost;
}

export function getPreviousPost(slug, fields = [], key, sort = "date") {
  let resultPost = null;

  getAllPosts(fields, key, sort).forEach((post, index, array) => {
    if (post.slug === slug) {
      if (typeof array[index + 1] !== "undefined") {
        resultPost = array[index + 1];
      }
    }
  });
  return resultPost;
}

export function formatDateWithTime(d) {
  const date = DateTime.fromISO(d, {
    setZone: true,
  }).toLocaleString(DateTime.DATETIME_FULL);
  return date;
}

export function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

// Takes an ISO 8601 date string
// Returns a time relative to the IANA timezone and iso8601 date
export function generateDisplayDate(iso8601, zone = "America/Los_Angeles") {
  return DateTime.fromISO(iso8601, { zone });
}

// Takes an ISO 8601 date string
// Returns a time relative to user's current timezone
export function generateRealtimeDate(iso8601) {
  return DateTime.fromISO(iso8601).setZone("system");
}

// Formats a DateTime object to something like "July 15, 2021, 5:00 PM"
export function formatDateAndTime(dateTimeObject) {
  return dateTimeObject.toLocaleString(DateTime.DATETIME_HUGE);
}

// Formats a DateTime object to something like "5:00 PM"
export function formatTime(dateTimeObject) {
  const dt = dateTimeObject.toLocaleString(DateTime.TIME_SIMPLE);
  return dt.replace(/:00/g, "");
}

export function formatTimeZone(dateTimeObject) {
  return dateTimeObject.offsetNameShort;
}

// Formats a DateTime object to something like "Jul 15, 2021"
export function formatDate(dateTimeObject) {
  return dateTimeObject.toLocaleString(DateTime.DATE_FULL);
}

// export function generateCrumbs(path) {
//   const crumbs = path.split('/')
//   return crumbs
// 	.filter(v => v !== '')
// 	.map((crumb, index) => ({
// 	  name: capitalize(crumb),
// 	  key: crumb,
// 	  path: crumbs.slice(0, index+2).join('/'),
//   }))
// }

export const getPage = (path) => {
  try {
    let fileContents = fs.readFileSync(`${path}.md`, "utf8");
    if (fileContents) {
      const { data, content } = matter(fileContents, options);
      return { data, content };
    }
  } catch {
    try {
      let fileContents = fs.readFileSync(`${path}/_index.md`, "utf8");
      if (fileContents) {
        const { data, content } = matter(fileContents, options);
        return { data, content };
      }
    } catch {
      console.error("no md file for slug");
    }
  }
};

// Returns an array of unique grants categories
export function getGrantsCategories() {
  const paths = fs.readdirSync(directories("grants"));
  const uniqueCategories = paths
    // Get only markdown files
    .filter((path) => parse(path).ext === ".md")
    // Parse frontmatter
    .map((path) =>
      matter(fs.readFileSync(join(directories("grants"), path)), options)
    )
    // Each markdown file has an array of categories. Collapse these arrays into one array.
    .reduce((acc, metadata) => {
      return [...acc, ...metadata.data.taxonomies.grant_category];
    }, [])
    // Deduplicate single array of categories such that the output is an array where each category is represented only once.
    .reduce((acc, uniqueItem) => {
      if (acc.includes(uniqueItem)) {
        return acc;
      }
      return [...acc, uniqueItem];
    }, []);
  return uniqueCategories;
}

// Returns an array of unique grants types
export function getGrantsTypes() {
  const paths = fs.readdirSync(directories("grants"));
  const uniqueTypes = paths
    // Get only markdown files
    .filter((path) => parse(path).ext === ".md")
    // Parse frontmatter to JSON
    .map((path) =>
      matter(fs.readFileSync(join(directories("grants"), path)), options)
    )
    // Each markdown file has an array of types. Collapse these arrays into one array.
    .reduce((acc, metadata) => {
      return [...acc, ...metadata.data.taxonomies.grant_type];
    }, [])
    // Deduplicate single array of types such that the output is an array where each type is represented only once.
    .reduce((acc, uniqueItem) => {
      if (acc.includes(uniqueItem)) {
        return acc;
      }
      return [...acc, uniqueItem];
    }, []);
  return uniqueTypes;
}

// Returns a number which represents how many grants are open, or uncompleted
export function getOpenGrantsCount() {
  const paths = fs.readdirSync(directories("grants"));
  const count = paths
    // Get only markdown files
    .filter((path) => parse(path).ext === ".md")
    // Parse frontmatter to JSON
    .map((path) =>
      matter(fs.readFileSync(join(directories("grants"), path)), options)
    )
    // Count grants which are both uncompleted and not assigned
    .reduce((acc, metadata) => {
      if (
        !metadata.data.extra.completed &&
        !metadata.data.extra.canceled &&
        metadata.data.extra.assignee === ""
      ) {
        return acc + 1;
      }
      return acc;
    }, 0);
  return count;
}
<commit_msg>lib: add pair to library<commit_after>import fs from "fs";
import { join, parse } from "path";
import matter from "gray-matter";
import toml from "@iarna/toml";
import { DateTime } from "luxon";

const directories = (dir) => {
  switch (dir) {
    case "blog":
      return join(process.cwd(), "content/blog");
    case "events":
      return join(process.cwd(), "content/events");
    case "docs":
      return join(process.cwd(), "content/docs");
    case "grants":
      return join(process.cwd(), "content/grants");
    case "media":
      return join(process.cwd(), "content/media");
    case "updates":
      return join(process.cwd(), "content/updates");
    case "/":
      return join(process.cwd(), "content");
    default:
      return join(process.cwd(), `content/${dir}`);
  }
};

export function getPostSlugs(key) {
  const dir = fs.existsSync(directories(key))
    ? fs.readdirSync(directories(key), { withFileTypes: true })
    : [];
  return dir
    .filter((f) => f.isFile() && f.name !== "_index.md")
    .map((f) => f.name);
}

// NB Gavin: This could be much simpler if we converted everything to a more common standard, like YAML
const options = {
  engines: {
    toml: toml.parse.bind(toml),
  },
  language: "toml",
  delimiters: "+++",
};

export function getPostBySlug(slug, fields = [], key) {
  const realSlug = slug.replace(/\.md$/, "");
  const fullPath = join(directories(key), `${realSlug}.md`);
  const fileContents = fs.readFileSync(fullPath, "utf8");
  const { data, content } = matter(fileContents, options);
  const items = {};

  // Ensure only the minimal needed data is exposed
  fields.forEach((field) => {
    if (field === "slug") {
      items[field] = realSlug;
    }

    if (field === "content") {
      items[field] = content;
    }

    if (data[field]) {
      items[field] = data[field];
    }
  });

  return items;
}

export function getAllPosts(fields = [], key, sort = "") {
  const slugs = getPostSlugs(key);
  const posts = slugs
    .map((slug) => getPostBySlug(slug, fields, key))
    // sort posts by date in descending order
    .sort((post1, post2) => {
      if (sort === "date") {
        return DateTime.fromISO(post1.date) > DateTime.fromISO(post2.date)
          ? -1
          : 1;
      } else if (sort === "weight") {
        return post1.weight > post2.weight ? -1 : 1;
      }
    });
  return posts;
}

export function getAllEvents(fields = [], key) {
  const slugs = getPostSlugs(key);
  const posts = slugs
    .map((slug) => getPostBySlug(slug, fields, key))
    // sort posts by date in descending order
    .sort((post1, post2) =>
      DateTime.fromISO(post1.starts) > DateTime.fromISO(post2.starts) ? -1 : 1
    );
  return posts;
}

function getAllPaths(dirPath, arrayOfFiles) {
  let files = fs.readdirSync(dirPath);

  arrayOfFiles = arrayOfFiles || [];

  files.forEach(function (file) {
    if (fs.statSync(dirPath + "/" + file).isDirectory()) {
      arrayOfFiles = getAllPaths(dirPath + "/" + file, arrayOfFiles);
    } else {
      arrayOfFiles.push(join(dirPath, "/", file));
    }
  });

  return arrayOfFiles;
}

export function getDocsPaths() {
  return getAllPaths(directories("docs"), []);
}

export function getNextPost(slug, fields = [], key, sort = "date") {
  let resultPost = null;

  getAllPosts(fields, key, sort).forEach((post, index, array) => {
    if (post.slug === slug) {
      if (typeof array[index - 1] !== "undefined") {
        resultPost = array[index - 1];
      }
    }
  });
  return resultPost;
}

export function getPreviousPost(slug, fields = [], key, sort = "date") {
  let resultPost = null;

  getAllPosts(fields, key, sort).forEach((post, index, array) => {
    if (post.slug === slug) {
      if (typeof array[index + 1] !== "undefined") {
        resultPost = array[index + 1];
      }
    }
  });
  return resultPost;
}

export function formatDateWithTime(d) {
  const date = DateTime.fromISO(d, {
    setZone: true,
  }).toLocaleString(DateTime.DATETIME_FULL);
  return date;
}

export function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

// Takes an ISO 8601 date string
// Returns a time relative to the IANA timezone and iso8601 date
export function generateDisplayDate(iso8601, zone = "America/Los_Angeles") {
  return DateTime.fromISO(iso8601, { zone });
}

// Takes an ISO 8601 date string
// Returns a time relative to user's current timezone
export function generateRealtimeDate(iso8601) {
  return DateTime.fromISO(iso8601).setZone("system");
}

// Formats a DateTime object to something like "July 15, 2021, 5:00 PM"
export function formatDateAndTime(dateTimeObject) {
  return dateTimeObject.toLocaleString(DateTime.DATETIME_HUGE);
}

// Formats a DateTime object to something like "5:00 PM"
export function formatTime(dateTimeObject) {
  const dt = dateTimeObject.toLocaleString(DateTime.TIME_SIMPLE);
  return dt.replace(/:00/g, "");
}

export function formatTimeZone(dateTimeObject) {
  return dateTimeObject.offsetNameShort;
}

// Formats a DateTime object to something like "Jul 15, 2021"
export function formatDate(dateTimeObject) {
  return dateTimeObject.toLocaleString(DateTime.DATE_FULL);
}

// export function generateCrumbs(path) {
//   const crumbs = path.split('/')
//   return crumbs
// 	.filter(v => v !== '')
// 	.map((crumb, index) => ({
// 	  name: capitalize(crumb),
// 	  key: crumb,
// 	  path: crumbs.slice(0, index+2).join('/'),
//   }))
// }

export const getPage = (path) => {
  try {
    let fileContents = fs.readFileSync(`${path}.md`, "utf8");
    if (fileContents) {
      const { data, content } = matter(fileContents, options);
      return { data, content };
    }
  } catch {
    try {
      let fileContents = fs.readFileSync(`${path}/_index.md`, "utf8");
      if (fileContents) {
        const { data, content } = matter(fileContents, options);
        return { data, content };
      }
    } catch {
      console.error("no md file for slug");
    }
  }
};

// Returns an array of unique grants categories
export function getGrantsCategories() {
  const paths = fs.readdirSync(directories("grants"));
  const uniqueCategories = paths
    // Get only markdown files
    .filter((path) => parse(path).ext === ".md")
    // Parse frontmatter
    .map((path) =>
      matter(fs.readFileSync(join(directories("grants"), path)), options)
    )
    // Each markdown file has an array of categories. Collapse these arrays into one array.
    .reduce((acc, metadata) => {
      return [...acc, ...metadata.data.taxonomies.grant_category];
    }, [])
    // Deduplicate single array of categories such that the output is an array where each category is represented only once.
    .reduce((acc, uniqueItem) => {
      if (acc.includes(uniqueItem)) {
        return acc;
      }
      return [...acc, uniqueItem];
    }, []);
  return uniqueCategories;
}

// Returns an array of unique grants types
export function getGrantsTypes() {
  const paths = fs.readdirSync(directories("grants"));
  const uniqueTypes = paths
    // Get only markdown files
    .filter((path) => parse(path).ext === ".md")
    // Parse frontmatter to JSON
    .map((path) =>
      matter(fs.readFileSync(join(directories("grants"), path)), options)
    )
    // Each markdown file has an array of types. Collapse these arrays into one array.
    .reduce((acc, metadata) => {
      return [...acc, ...metadata.data.taxonomies.grant_type];
    }, [])
    // Deduplicate single array of types such that the output is an array where each type is represented only once.
    .reduce((acc, uniqueItem) => {
      if (acc.includes(uniqueItem)) {
        return acc;
      }
      return [...acc, uniqueItem];
    }, []);
  return uniqueTypes;
}

// Returns a number which represents how many grants are open, or uncompleted
export function getOpenGrantsCount() {
  const paths = fs.readdirSync(directories("grants"));
  const count = paths
    // Get only markdown files
    .filter((path) => parse(path).ext === ".md")
    // Parse frontmatter to JSON
    .map((path) =>
      matter(fs.readFileSync(join(directories("grants"), path)), options)
    )
    // Count grants which are both uncompleted and not assigned
    .reduce((acc, metadata) => {
      if (
        !metadata.data.extra.completed &&
        !metadata.data.extra.canceled &&
        metadata.data.extra.assignee === ""
      ) {
        return acc + 1;
      }
      return acc;
    }, 0);
  return count;
}

// Groups arrays into an array of arrays with 2 members
export const pair = (arr) =>
  arr.reduce(function (rows, key, index) {
    return (
      (index % 2 == 0 ? rows.push([key]) : rows[rows.length - 1].push(key)) &&
      rows
    );
  }, []);
<|endoftext|>


<commit_before>'use strict';

const winston = require('winston');

const LEVELS = {
  fatal: 0,
  error: 1,
  info: 2,
  warn: 3,
  debug: 4
};

const logger = new winston.Logger({
  transports: [
    new winston.transports.Console({
      level: 'debug',
      colorize: true,
      json: false,
      stringify: true
    })
  ],
  levels: LEVELS
});

module.exports = logger;
<commit_msg>Delete log.js<commit_after><|endoftext|>


<commit_before>
exports.mixin = function(_){

    function consoleTransport(log, logLevel, timestamp, entry){
        var writer = _.stdout;
        var priority = log.priority(logLevel);

        // error or worse
        if(priority > 3){ writer = _.stderr; }

        if(log.timestamp()){ writer(_.moment(timestamp).format("YYYY-MM-DD HH:MM:SS") + ":", entry); }
        else{ writer(entry); }
    }

    function logger(options){

        if(_.isString(options)){
            options = { namespace: options };
        }

        options = options || {};

        this._namespace = options.namespace ? options.namespace : "";
        this.timestamp(options.timestamp);

        if(options.parent){
            this._parent = options.parent;
            this._transports = [];
        }else{
            this._parent = null;
            this._transports = _.clone(this._defaultTransports);
        }

        this.level('debug');
        if(options.level){ this.level(options.level); }
    }

    logger.prototype._levels = ['debug', 'info', 'notice', 'warning', 'error', 'crit', 'alert', 'emerg'];
    logger.prototype._priorities = { 'debug' : 0, 'info' : 1, 'notice' : 2, 'warning' : 3, 'error' : 4, 'crit' : 5, 'alert' : 6, 'emerg' : 7 };

    logger.prototype.levels = function(){ return(this._levels); };
    logger.prototype.priorities = function(){ return(this._priorities); };

    logger.prototype._defaultTransports = [consoleTransport];

    logger.prototype.transports = function(t){
        if(t){ this._transports = t; }
        else{ return(this._transports); }
    };

    logger.prototype.priority = function(level){
        if(level === undefined){
            return(this.priority(this.level()));
        }else if(this._priorities[level] !== undefined){
            return(this._priorities[level]);
        }else{
            return(-1);
        }
    };

    logger.prototype.level = function(level){
        if(level === undefined){
            return(this._level);
        }else{
            if(this.priority(level) < 0){ return; }
            this._level = level;
        }
    };

    logger.prototype.namespace = function(ns){
        if(ns !== undefined){ this._namespace = ns; }

        var ns = "";

        if(this.parent()){ ns += this.parent().namespace(); }
        if(this._namespace){
            if(ns){ ns += "."; }
            ns += this._namespace;
        }

        return(ns);
    };

    logger.prototype._write = function(logLevel, pieces){

        var ns = this.namespace();
        if(ns){ ns += ": "; }
        pieces.unshift(ns);
        var entry = _.format.apply(null, pieces);

        this._transport(logLevel, entry);
    }

    logger.prototype._transport = function(logLevel, entry){
        var self = this;
        var ts = _.timestamp();

        _.each(this.transports(), function(f){
            if(_.isFunction(f.writeEntry)){
                f.writeEntry(self, logLevel, ts, entry);
            }else if(_.isFunction(f)){
                f(self, logLevel, ts, entry);
            }
        });

        if(this.parent()){ this.parent()._transport(logLevel, entry); }
    }

    logger.prototype.parent = function(){
        if(this._parent){ return(this._parent); }
        else{ return(null); }
    };

    function makeLogFunction(logLevel){
        return(function(){
            /*
            _.p("log:", this);
            _.p("current log level:", this.level());
            _.p("current log priority:", this.priority());
            _.p("current log level priority:", this.priority(this.level()));
            _.p("incoming log level:", logLevel);
            _.p("incoming log level priority:", this.priority(logLevel));
            */

            if(this.priority(this.level()) <= this.priority(logLevel)){
                this._write(logLevel, _.toArray(arguments));
            }
            return(this);
        });
    }

    _.each(logger.prototype._levels, function(logLevel){
        logger.prototype[logLevel] = makeLogFunction(logLevel);
    });

    // you can revert to parent settings by nulling out child settings
    logger.prototype.setting = function(setting, defaultValue){
        if(this[setting] !== undefined && this[setting] !== null){
            return(this[setting]);
        }else if(this.parent()){
            return(this.parent().setting(setting, defaultValue));
        }else{
            return(defaultValue);
        }
    };

    logger.prototype.timestamp = function(enable){
        if(enable !== undefined){
            this._timestamp = enable;
            return(this);
        }else{
            return(this.setting("_timestamp", false));
        }
    };

    logger.prototype.make = function(options){
        return(new logger(options));
    };

    logger.prototype.child = function(ns){
        return(this.make({ namespace: ns, parent: this }));
    };

    function mixin(root, options){
        root = root || {};

        root.log = new logger(options);

        return(root.log);
    }

    return(mixin());
};

<commit_msg>make mixin a function of logger<commit_after>
exports.mixin = function(_){

    function consoleTransport(log, logLevel, timestamp, entry){
        var writer = _.stdout;
        var priority = log.priority(logLevel);

        // error or worse
        if(priority > 3){ writer = _.stderr; }

        if(log.timestamp()){ writer(_.moment(timestamp).format("YYYY-MM-DD HH:MM:SS") + ":", entry); }
        else{ writer(entry); }
    }

    function logger(options){

        if(_.isString(options)){
            options = { namespace: options };
        }

        options = options || {};

        this._namespace = options.namespace ? options.namespace : "";
        this.timestamp(options.timestamp);

        if(options.parent){
            this._parent = options.parent;
            this._transports = [];
        }else{
            this._parent = null;
            this._transports = _.clone(this._defaultTransports);
        }

        this.level('debug');
        if(options.level){ this.level(options.level); }
    }

    logger.prototype._levels = ['debug', 'info', 'notice', 'warning', 'error', 'crit', 'alert', 'emerg'];
    logger.prototype._priorities = { 'debug' : 0, 'info' : 1, 'notice' : 2, 'warning' : 3, 'error' : 4, 'crit' : 5, 'alert' : 6, 'emerg' : 7 };

    logger.prototype.levels = function(){ return(this._levels); };
    logger.prototype.priorities = function(){ return(this._priorities); };

    logger.prototype._defaultTransports = [consoleTransport];

    logger.prototype.transports = function(t){
        if(t){ this._transports = t; }
        else{ return(this._transports); }
    };

    logger.prototype.priority = function(level){
        if(level === undefined){
            return(this.priority(this.level()));
        }else if(this._priorities[level] !== undefined){
            return(this._priorities[level]);
        }else{
            return(-1);
        }
    };

    logger.prototype.level = function(level){
        if(level === undefined){
            return(this._level);
        }else{
            if(this.priority(level) < 0){ return; }
            this._level = level;
        }
    };

    logger.prototype.namespace = function(ns){
        if(ns !== undefined){ this._namespace = ns; }

        var ns = "";

        if(this.parent()){ ns += this.parent().namespace(); }
        if(this._namespace){
            if(ns){ ns += "."; }
            ns += this._namespace;
        }

        return(ns);
    };

    logger.prototype._write = function(logLevel, pieces){

        var ns = this.namespace();
        if(ns){ ns += ": "; }
        pieces.unshift(ns);
        var entry = _.format.apply(null, pieces);

        this._transport(logLevel, entry);
    }

    logger.prototype._transport = function(logLevel, entry){
        var self = this;
        var ts = _.timestamp();

        _.each(this.transports(), function(f){
            if(_.isFunction(f.writeEntry)){
                f.writeEntry(self, logLevel, ts, entry);
            }else if(_.isFunction(f)){
                f(self, logLevel, ts, entry);
            }
        });

        if(this.parent()){ this.parent()._transport(logLevel, entry); }
    }

    logger.prototype.parent = function(){
        if(this._parent){ return(this._parent); }
        else{ return(null); }
    };

    function makeLogFunction(logLevel){
        return(function(){
            /*
            _.p("log:", this);
            _.p("current log level:", this.level());
            _.p("current log priority:", this.priority());
            _.p("current log level priority:", this.priority(this.level()));
            _.p("incoming log level:", logLevel);
            _.p("incoming log level priority:", this.priority(logLevel));
            */

            if(this.priority(this.level()) <= this.priority(logLevel)){
                this._write(logLevel, _.toArray(arguments));
            }
            return(this);
        });
    }

    _.each(logger.prototype._levels, function(logLevel){
        logger.prototype[logLevel] = makeLogFunction(logLevel);
    });

    // you can revert to parent settings by nulling out child settings
    logger.prototype.setting = function(setting, defaultValue){
        if(this[setting] !== undefined && this[setting] !== null){
            return(this[setting]);
        }else if(this.parent()){
            return(this.parent().setting(setting, defaultValue));
        }else{
            return(defaultValue);
        }
    };

    logger.prototype.timestamp = function(enable){
        if(enable !== undefined){
            this._timestamp = enable;
            return(this);
        }else{
            return(this.setting("_timestamp", false));
        }
    };

    logger.prototype.make = function(options){
        return(new logger(options));
    };

    logger.prototype.child = function(ns){
        return(this.make({ namespace: ns, parent: this }));
    };

    logger.prototype.mixin = function(root, options){
        root = root || {};

        root.log = new logger(options);

        return(root.log);
    }

    return(logger.prototype.mixin());
};

<|endoftext|>


<commit_before>const https = require( 'https' );

const cheerio = require( 'cheerio' );
const moment = require( 'moment-timezone' );

const getTeamData = require( './teamdata' );

const POSTS_PATH = '/artiklar';
const RSS_ITEMS_TO_LOAD = 10;

class RSS {
    getTeamUrl ( team, path ) {
        const currentTeamData = getTeamData( team );

        return `https://${ currentTeamData.homepage }${ path }`;
    }

    loadPage ( team, path ) {
        return new Promise( ( resolve, reject ) => {
            const url = this.getTeamUrl( team, path );

            console.log( `loading ${ url }` );
            const request = https.get( url, ( response ) => {
                response.setEncoding( 'utf8' );
                let rawData = '';

                if ( response.statusCode !== 200 ) {
                    reject( new Error( `${ url } failed. It returned with status ${ response.statusCode }` ) );

                    return false;
                }

                response.on( 'data', ( chunk ) => {
                    rawData = `${ rawData }${ chunk }`;
                } );

                response.on( 'end', () => {
                    resolve( rawData.toString() );
                } );
            } );

            request.on( 'error', ( requestError ) => {
                reject( requestError );
            } );
        } );
    }

    fixPostContent ( team, rawPostContent ) {
        let postContent = rawPostContent;
        let $;
        const currentTeamData = getTeamData( team );

        // Fix external multi-protocol urls
        postContent = postContent.replace( 'src="//', 'src="https://' );
        postContent = postContent.replace( 'href="//', 'href="https://' );

        // Fix urls
        postContent = postContent.replace( 'src="/', `src="${ currentTeamData.homepage }/` );
        postContent = postContent.replace( 'href="/', `href="${ currentTeamData.homepage }/` );

        // Remove all data-* tags
        postContent = postContent.replace( /data-.+?".+?"/gim, '' );

        $ = cheerio.load( postContent );

        $( 'h1' ).remove();
        $( 'script' ).remove();
        $( '.social-buttons-article-top' ).remove();
        $( '.social-buttons-article-bottom' ).remove();

        $( '[data-srcset]' ).each( ( index, element ) => {
            const imageSizes = $( element ).attr( 'data-srcset' ).match( /([^\s]+?)\s(.+?),/g );

            for ( let i = 0; i < imageSizes.length; i = i + 1 ) {
                let [ url, size ] = imageSizes[ i ].split( ' ' );

                if ( size === '1280w,' ) {
                    $( element ).attr( 'srcset', url );

                    return true;
                }
            }
        } );

        return $.html();
    }

    getFullPost( team, path ) {
        return this.loadPage( team, path )
            .then( ( postPage ) => {
                const $ = cheerio.load( postPage );

                return this.fixPostContent( team, $( '.rmss_article-main' ).html() );
            } );
    }

    getFeed( team ) {
        const teamData = getTeamData( team );

        if ( !teamData.homepage ) {
            return Promise.resolve( `<?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title>${ team } News Not Implemented</title>
                    <link>https://hockey-mchockeyface.herokuapp.com/rss/${ team }</link>
                    <description>This will be a feed of the latest ${ team } news</description>
                    <language>sv-se</language>
                    <copyright>Nah, fuck that shit :D</copyright>
                </channel>
            </rss>` );
        }

        return this.getPosts( team )
            .then( ( articleObjects ) => {
                let feedString = `<?xml version="1.0" encoding="UTF-8"?>
                <rss version="2.0">
                    <channel>
                        <title>${ team } News</title>
                        <link>https://hockey-mchockeyface.herokuapp.com/rss/${ team }</link>
                        <description>This is a feed of the latest ${ team } news</description>
                        <language>sv-se</language>
                        <copyright>Nah, fuck that shit :D</copyright>`;

                for ( const article of articleObjects ) {
                    feedString = `${ feedString }
                    <item>
                        <title>${ article.title }</title>
                        <description><![CDATA[${ article.description }]]></description>
                        <link>${ article.url }</link>
                        <pubDate>${ moment( article.timestamp ).format( 'ddd, DD MMM YYYY HH:mm:ss' ) }</pubDate>
                    </item>`;
                }

                feedString = `${ feedString }
                    </channel>
                </rss>`;

                return feedString;
            } )
            .catch( ( error ) => {
                console.error( error );
            } );
    }

    getPosts ( team ) {
        return this.loadPage( team, POSTS_PATH )
            .then( ( teamPage ) => {
                const $ = cheerio.load( teamPage );
                const itemPromises = [];

                $( '.rmss--has_media' ).each( ( index, element ) => {
                    if ( index >= RSS_ITEMS_TO_LOAD ) {
                        return true;
                    }

                    itemPromises.push( new Promise( ( resolve, reject ) => {
                        const $article = $( element );
                        const title = $article.find( 'h1' ).text();
                        const timestamp = $article.find( '.rmss_c-archive-article__publish-at' ).text();
                        const url = $article.find( 'a' ).attr( 'href' );

                        this.getFullPost( team, url )
                            .then( ( fullHTML ) => {
                                resolve( {
                                    title,
                                    timestamp,
                                    url: this.getTeamUrl( team, url ),
                                    description: fullHTML,
                                } );
                            } )
                            .catch( ( someError ) => {
                                reject( someError );
                            } );
                    } ) );
                } );

                return Promise.all( itemPromises );
            } );
    }
}

module.exports = new RSS();
<commit_msg>Remove invisible nulsl<commit_after>const https = require( 'https' );

const cheerio = require( 'cheerio' );
const moment = require( 'moment-timezone' );

const getTeamData = require( './teamdata' );

const POSTS_PATH = '/artiklar';
const RSS_ITEMS_TO_LOAD = 10;

class RSS {
    getTeamUrl ( team, path ) {
        const currentTeamData = getTeamData( team );

        return `https://${ currentTeamData.homepage }${ path }`;
    }

    loadPage ( team, path ) {
        return new Promise( ( resolve, reject ) => {
            const url = this.getTeamUrl( team, path );

            console.log( `loading ${ url }` );
            const request = https.get( url, ( response ) => {
                response.setEncoding( 'utf8' );
                let rawData = '';

                if ( response.statusCode !== 200 ) {
                    reject( new Error( `${ url } failed. It returned with status ${ response.statusCode }` ) );

                    return false;
                }

                response.on( 'data', ( chunk ) => {
                    rawData = `${ rawData }${ chunk }`;
                } );

                response.on( 'end', () => {
                    resolve( rawData.toString() );
                } );
            } );

            request.on( 'error', ( requestError ) => {
                reject( requestError );
            } );
        } );
    }

    fixPostContent ( team, rawPostContent ) {
        let postContent = rawPostContent;
        let $;
        const currentTeamData = getTeamData( team );

        // Fix external multi-protocol urls
        postContent = postContent.replace( 'src="//', 'src="https://' );
        postContent = postContent.replace( 'href="//', 'href="https://' );

        // Fix urls
        postContent = postContent.replace( 'src="/', `src="${ currentTeamData.homepage }/` );
        postContent = postContent.replace( 'href="/', `href="${ currentTeamData.homepage }/` );

        // Remove all data-* tags
        postContent = postContent.replace( /data-.+?".+?"/gim, '' );

        $ = cheerio.load( postContent );

        $( 'h1' ).remove();
        $( 'script' ).remove();
        $( '.social-buttons-article-top' ).remove();
        $( '.social-buttons-article-bottom' ).remove();

        $( '[data-srcset]' ).each( ( index, element ) => {
            const imageSizes = $( element ).attr( 'data-srcset' ).match( /([^\s]+?)\s(.+?),/g );

            for ( let i = 0; i < imageSizes.length; i = i + 1 ) {
                let [ url, size ] = imageSizes[ i ].split( ' ' );

                if ( size === '1280w,' ) {
                    $( element ).attr( 'srcset', url );

                    return true;
                }
            }
        } );

        return $.html();
    }

    getFullPost( team, path ) {
        return this.loadPage( team, path )
            .then( ( postPage ) => {
                const $ = cheerio.load( postPage );

                return this.fixPostContent( team, $( '.rmss_article-main' ).html() );
            } );
    }

    getFeed( team ) {
        const teamData = getTeamData( team );

        if ( !teamData.homepage ) {
            return Promise.resolve( `<?xml version="1.0" encoding="UTF-8"?>
            <rss version="2.0">
                <channel>
                    <title>${ team } News Not Implemented</title>
                    <link>https://hockey-mchockeyface.herokuapp.com/rss/${ team }</link>
                    <description>This will be a feed of the latest ${ team } news</description>
                    <language>sv-se</language>
                    <copyright>Nah, fuck that shit :D</copyright>
                </channel>
            </rss>` );
        }

        return this.getPosts( team )
            .then( ( articleObjects ) => {
                let feedString = `<?xml version="1.0" encoding="UTF-8"?>
                <rss version="2.0">
                    <channel>
                        <title>${ team } News</title>
                        <link>https://hockey-mchockeyface.herokuapp.com/rss/${ team }</link>
                        <description>This is a feed of the latest ${ team } news</description>
                        <language>sv-se</language>
                        <copyright>Nah, fuck that shit :D</copyright>`;

                for ( const article of articleObjects ) {
                    feedString = `${ feedString }
                    <item>
                        <title>${ article.title }</title>
                        <description><![CDATA[${ article.description }]]></description>
                        <link>${ article.url }</link>
                        <pubDate>${ moment( article.timestamp ).format( 'ddd, DD MMM YYYY HH:mm:ss' ) }</pubDate>
                    </item>`;
                }

                feedString = `${ feedString }
                    </channel>
                </rss>`;

                return feedString;
            } )
            .catch( ( error ) => {
                console.error( error );
            } );
    }

    getPosts ( team ) {
        return this.loadPage( team, POSTS_PATH )
            .then( ( teamPage ) => {
                const $ = cheerio.load( teamPage );
                const itemPromises = [];

                $( '.rmss--has_media' ).each( ( index, element ) => {
                    if ( index >= RSS_ITEMS_TO_LOAD ) {
                        return true;
                    }

                    itemPromises.push( new Promise( ( resolve, reject ) => {
                        const $article = $( element );
                        const title = $article.find( 'h1' ).text();
                        const timestamp = $article.find( '.rmss_c-archive-article__publish-at' ).text();
                        const url = $article.find( 'a' ).attr( 'href' );

                        this.getFullPost( team, url )
                            .then( ( fullHTML ) => {
                                resolve( {
                                    title,
                                    timestamp,
                                    url: this.getTeamUrl( team, url ),
                                    description: fullHTML,
                                } );
                            } )
                            .catch( ( someError ) => {
                                reject( someError );
                            } );
                    } ) );
                } );

                return Promise.all( itemPromises );
            } );
    }
}

module.exports = new RSS();
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

var TG = {};

TG.Texture = function ( width, height ) {

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

	this.array = new Float32Array( width * height * 4 );
	this.arrayCopy = new Float32Array( width * height * 4 );

	return this;

};

TG.Texture.prototype = {

	constructor: TG.Texture,

	pass: function ( program, operation ) {

		if ( operation === undefined ) operation = '';

		var color = program.getColor();
		var source = program.getSource();

		this.arrayCopy.set( this.array );

		var string = [
			'var x = 0, y = 0;',
			'for ( var i = 0, il = dst.length; i < il; i += 4 ) {',
				'	' + source,
				color[ 0 ] !== 0 ? '	dst[ i + 0 ] ' + operation + '= color * ' + color[ 0 ] + ';' : '',
				color[ 1 ] !== 0 ? '	dst[ i + 1 ] ' + operation + '= color * ' + color[ 1 ] + ';' : '',
				color[ 2 ] !== 0 ? '	dst[ i + 2 ] ' + operation + '= color * ' + color[ 2 ] + ';' : '',
				'	if ( ++x === width ) { x = 0; y ++; }',
			'}'
		].join( '\n' );

		new Function( 'dst, src, width, height', string )( this.array, this.arrayCopy, this.width, this.height );

		return this;

	},

	add: function ( program ) {

		return this.pass( program, '+' );

	},

	sub: function ( program ) {

		return this.pass( program, '-' );

	},

	mul: function ( program ) {

		return this.pass( program, '*' );

	},

	div: function ( program ) {

		return this.pass( program, '/' );

	},

	toImageData: function ( context ) {

		var array = this.array;

		var imagedata = context.createImageData( this.width, this.height );
		var data = imagedata.data;

		for ( var i = 0, il = array.length; i < il; i += 4 ) {

			data[ i		 ] = array[ i		 ] * 255;
			data[ i + 1 ] = array[ i + 1 ] * 255;
			data[ i + 2 ] = array[ i + 2 ] * 255;
			data[ i + 3 ] = 255;

		}

		return imagedata;

	},

	toCanvas: function () {

		var canvas = document.createElement( 'canvas' );
		canvas.width = this.width;
		canvas.height = this.height;

		var context = canvas.getContext( '2d' );
		var imagedata = this.toImageData( context );

		context.putImageData( imagedata, 0, 0 );

		return canvas;

	}

};

TG.Program = function ( object ) {

	var color = [ 1, 1, 1 ];

	object.color = function ( r, g, b ) {
		color = [ r, g, b ];
		return this;
	};

	object.getColor = function () {
		return color;
	};

	return object;

};

TG.Number = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = 1;';
		}
	} );

};

TG.SinX = function () {

	var frequency = 1;
	var offset = 0;

	return new TG.Program( {
		frequency: function ( value ) {
			frequency = value * Math.PI;
			return this;
		},
		offset: function ( value ) {
			offset = value;
			return this;
		},
		getSource: function () {
			return 'var color = Math.sin( ( x + ' + offset + ' ) * ' + frequency + ' );';
		}
	} );

};

TG.SinY = function () {

	var frequency = 1;
	var offset = 0;

	return new TG.Program( {
		frequency: function ( value ) {
			frequency = value * Math.PI;
			return this;
		},
		offset: function ( value ) {
			offset = value;
			return this;
		},
		getSource: function () {
			return 'var color = Math.sin( ( y + ' + offset + ' ) * ' + frequency + ' );';
		}
	} );

};

TG.OR = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = ( x | y ) / width;';
		}
	} );

};

TG.XOR = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = ( x ^ y ) / width;';
		}
	} );

};

TG.Noise = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = Math.random();';
		}
	} );

};

TG.CheckerBoard = function () {

	var size = [ 32, 32 ];
	var offset = [ 0, 0 ];
	var rowShift = 0;

	return new TG.Program( {
		size: function ( x, y ) {
			size = [ x, y ];
			return this;
		},
		offset: function ( x, y ) {
			offset = [ x, y ];
			return this;
		},
		rowShift: function ( value ) {
			rowShift = value;
			return this;
		},
		getSource: function () {

			return 'var color = ( ( ( y + ' + offset[ 1 ] + ' ) / ' + size[ 1 ] + ' ) & 1 ) ^ ( ( ( x + ' + offset[ 0 ] + ' + parseInt( y / ' + size[ 1 ] + ' ) * ' + rowShift + ' ) / ' + size[ 0 ] + ' ) & 1 ) ? 0 : 1';

		}
	} );

};

TG.Rect = function () {

	var position = [ 0, 0 ];
	var size = [ 32, 32 ];

	return new TG.Program( {
		position: function ( x, y ) {
			position = [ x, y ];
			return this;
		},
		size: function ( x, y ) {
			size = [ x, y ];
			return this;
		},
		getSource: function () {

			return 'var color = ( x >= ' + position[ 0 ] + ' && x <= ' + ( position[ 0 ] + size[ 0 ] ) + ' && y <= ' + ( position[ 1 ] + size[ 1 ] ) + ' && y >= ' + position[ 1 ] + ' ) ? 1 : 0;';

		}
	} );

};

TG.Circle = function () {

	var position = [ 0, 0 ];
	var radius = 50;
	var delta = 1;

	return new TG.Program( {
		delta: function ( value ) {
			delta = value;
			return this;
		},
		position: function ( x, y ) {
			position = [ x, y ];
			return this;
		},
		radius: function ( value ) {
			radius = value;
			return this;
		},
		getSource: function () {
			return [
				'var dist = TG.Utils.distance( x, y, ' + position[ 0 ] + ',' + position[ 1 ] + ');',
				'var color = TG.Utils.smoothStep( ' + radius + ' - ' + delta + ', ' + radius + ', dist );',
			].join('\n');
		}
	} );

};

// Filters

TG.SineDistort = function () {

	var sines = [ 4, 4 ];
	var offset = [ 0, 0 ];
	var amplitude = [ 16, 16 ];

	return new TG.Program( {
		sines: function ( x, y ) {
			sines = [ x, y ];
			return this;
		},
		offset: function ( x, y ) {
			offset = [ x, y ];
			return this;
		},
		amplitude: function ( x, y ) {
			amplitude = [ x, y ];
			return this;
		},
		getSource: function () {
			return [
				'var sx = Math.sin(' + sines[ 0 ] / 100 + ' * y + ' + offset[ 0 ] + ') * ' + amplitude[ 0 ] + ' + x;',
				'var sy = Math.sin(' + sines[ 1 ] / 100 + ' * x + ' + offset[ 1 ] + ') * ' + amplitude[ 1 ] + ' + y;',
				'var color = TG.Utils.getPixelBilinear(src, sx, sy, 0, width);'
				].join( '\n' );
		}
	} );
}

TG.Twirl = function () {

	var strength = 0;
	var radius = 120;
	var position = [ 128, 128 ];

	return new TG.Program( {
		strength: function ( value ) {
			strength = value / 100.0;
			return this;
		},
		radius: function ( value ) {
			radius = value;
			return this;
		},
		position: function ( x, y ) {
			position = [ x, y ];
			return this;
		},
		getSource: function () {

			return [
				'var dist = TG.Utils.distance( x, y, ' + position[ 0 ] + ',' + position[ 1 ] + ');',

				// no distortion if outside of whirl radius.

				'dist = dist > '+ radius +' ? 0 : ('+ radius +' - dist) * (' + radius + ' - dist) / ' + radius + ';',

				'var angle = 2.0 * Math.PI * (dist / (' + radius + ' / ' + strength + '));',
				'var xpos = (((x - ' + position[ 0 ] + ') * Math.cos(angle)) - ((y - ' + position[ 0 ] + ') * Math.sin(angle)) + ' + position[ 0 ] + ' + 0.5);',
				'var ypos = (((y - ' + position[ 1 ] + ') * Math.cos(angle)) + ((x - ' + position[ 1 ] + ') * Math.sin(angle)) + ' + position[ 1 ] + ' + 0.5);',

				'var color = TG.Utils.getPixelBilinear(src, xpos, ypos, 0, width);'

				].join( '\n' );
		}
	} );

};

// Utils
TG.Utils = {

	smoothStep: function ( edge0, edge1, x ) {

		// Scale, bias and saturate x to 0..1 range
		x = TG.Utils.clamp( ( x - edge0 ) / ( edge1 - edge0 ), 0, 1 );

		// Evaluate polynomial
		return x * x * ( 3 - 2 * x );

	},

	distance: function( x0, y0, x1, y1 ) {

		var dx = x1 - x0, dy = y1 - y0;
		return Math.sqrt( dx * dx + dy * dy );

	},

	clamp: function( value, min, max ) {

		return Math.min( Math.max( value, min ), max );

	},

	getPixelNearest: function( pixels, x, y, offset, width ) {

		return pixels[ offset + Math.round( y ) * width * 4 + Math.round( x ) * 4 ];

	},

	getPixelBilinear: function( pixels, x, y, offset, width ) {

		var percentX = x - ( x ^ 0 );
		var percentX1 = 1.0 - percentX;
		var percentY = y - ( y ^ 0 );
		var fx4 = ( x ^ 0 ) * 4;
		var cx4 = fx4 + 4;
		var fy4 = ( y ^ 0 ) * 4;
		var cy4wo = ( fy4 + 4 ) * width + offset;
		var fy4wo = fy4 * width + offset;

		var top = pixels[ cy4wo + fx4 ] * percentX1 + pixels[ cy4wo + cx4 ] * percentX;
		var bottom = pixels[ fy4wo + fx4 ] * percentX1 + pixels[ fy4wo + cx4 ] * percentX;

		return top * percentY + bottom * ( 1.0 - percentY );

	}

};
<commit_msg>More code clean up.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

var TG = {};

TG.Texture = function ( width, height ) {

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

	this.array = new Float32Array( width * height * 4 );
	this.arrayCopy = new Float32Array( width * height * 4 );

	return this;

};

TG.Texture.prototype = {

	constructor: TG.Texture,

	pass: function ( program, operation ) {

		if ( operation === undefined ) operation = '';

		var color = program.getColor();
		var source = program.getSource();

		this.arrayCopy.set( this.array );

		var string = [
			'var x = 0, y = 0;',
			'for ( var i = 0, il = dst.length; i < il; i += 4 ) {',
				'	' + source,
				color[ 0 ] !== 0 ? '	dst[ i + 0 ] ' + operation + '= color * ' + color[ 0 ] + ';' : '',
				color[ 1 ] !== 0 ? '	dst[ i + 1 ] ' + operation + '= color * ' + color[ 1 ] + ';' : '',
				color[ 2 ] !== 0 ? '	dst[ i + 2 ] ' + operation + '= color * ' + color[ 2 ] + ';' : '',
				'	if ( ++x === width ) { x = 0; y ++; }',
			'}'
		].join( '\n' );

		new Function( 'dst, src, width, height', string )( this.array, this.arrayCopy, this.width, this.height );

		return this;

	},

	add: function ( program ) {

		return this.pass( program, '+' );

	},

	sub: function ( program ) {

		return this.pass( program, '-' );

	},

	mul: function ( program ) {

		return this.pass( program, '*' );

	},

	div: function ( program ) {

		return this.pass( program, '/' );

	},

	toImageData: function ( context ) {

		var array = this.array;

		var imagedata = context.createImageData( this.width, this.height );
		var data = imagedata.data;

		for ( var i = 0, il = array.length; i < il; i += 4 ) {

			data[ i		 ] = array[ i		 ] * 255;
			data[ i + 1 ] = array[ i + 1 ] * 255;
			data[ i + 2 ] = array[ i + 2 ] * 255;
			data[ i + 3 ] = 255;

		}

		return imagedata;

	},

	toCanvas: function () {

		var canvas = document.createElement( 'canvas' );
		canvas.width = this.width;
		canvas.height = this.height;

		var context = canvas.getContext( '2d' );
		var imagedata = this.toImageData( context );

		context.putImageData( imagedata, 0, 0 );

		return canvas;

	}

};

TG.Program = function ( object ) {

	var color = [ 1, 1, 1 ];

	object.color = function ( r, g, b ) {
		color = [ r, g, b ];
		return this;
	};

	object.getColor = function () {
		return color;
	};

	return object;

};

TG.Number = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = 1;';
		}
	} );

};

TG.SinX = function () {

	var frequency = 1;
	var offset = 0;

	return new TG.Program( {
		frequency: function ( value ) {
			frequency = value * Math.PI;
			return this;
		},
		offset: function ( value ) {
			offset = value;
			return this;
		},
		getSource: function () {
			return 'var color = Math.sin( ( x + ' + offset + ' ) * ' + frequency + ' );';
		}
	} );

};

TG.SinY = function () {

	var frequency = 1;
	var offset = 0;

	return new TG.Program( {
		frequency: function ( value ) {
			frequency = value * Math.PI;
			return this;
		},
		offset: function ( value ) {
			offset = value;
			return this;
		},
		getSource: function () {
			return 'var color = Math.sin( ( y + ' + offset + ' ) * ' + frequency + ' );';
		}
	} );

};

TG.OR = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = ( x | y ) / width;';
		}
	} );

};

TG.XOR = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = ( x ^ y ) / width;';
		}
	} );

};

TG.Noise = function () {

	return new TG.Program( {
		getSource: function () {
			return 'var color = Math.random();';
		}
	} );

};

TG.CheckerBoard = function () {

	var size = [ 32, 32 ];
	var offset = [ 0, 0 ];
	var rowShift = 0;

	return new TG.Program( {
		size: function ( x, y ) {
			size = [ x, y ];
			return this;
		},
		offset: function ( x, y ) {
			offset = [ x, y ];
			return this;
		},
		rowShift: function ( value ) {
			rowShift = value;
			return this;
		},
		getSource: function () {
			return 'var color = ( ( ( y + ' + offset[ 1 ] + ' ) / ' + size[ 1 ] + ' ) & 1 ) ^ ( ( ( x + ' + offset[ 0 ] + ' + parseInt( y / ' + size[ 1 ] + ' ) * ' + rowShift + ' ) / ' + size[ 0 ] + ' ) & 1 ) ? 0 : 1';
		}
	} );

};

TG.Rect = function () {

	var position = [ 0, 0 ];
	var size = [ 32, 32 ];

	return new TG.Program( {
		position: function ( x, y ) {
			position = [ x, y ];
			return this;
		},
		size: function ( x, y ) {
			size = [ x, y ];
			return this;
		},
		getSource: function () {
			return 'var color = ( x >= ' + position[ 0 ] + ' && x <= ' + ( position[ 0 ] + size[ 0 ] ) + ' && y <= ' + ( position[ 1 ] + size[ 1 ] ) + ' && y >= ' + position[ 1 ] + ' ) ? 1 : 0;';
		}
	} );

};

TG.Circle = function () {

	var position = [ 0, 0 ];
	var radius = 50;
	var delta = 1;

	return new TG.Program( {
		delta: function ( value ) {
			delta = value;
			return this;
		},
		position: function ( x, y ) {
			position = [ x, y ];
			return this;
		},
		radius: function ( value ) {
			radius = value;
			return this;
		},
		getSource: function () {
			return [
				'var dist = TG.Utils.distance( x, y, ' + position[ 0 ] + ',' + position[ 1 ] + ');',
				'var color = TG.Utils.smoothStep( ' + radius + ' - ' + delta + ', ' + radius + ', dist );',
			].join('\n');
		}
	} );

};

// Filters

TG.SineDistort = function () {

	var sines = [ 4, 4 ];
	var offset = [ 0, 0 ];
	var amplitude = [ 16, 16 ];

	return new TG.Program( {
		sines: function ( x, y ) {
			sines = [ x, y ];
			return this;
		},
		offset: function ( x, y ) {
			offset = [ x, y ];
			return this;
		},
		amplitude: function ( x, y ) {
			amplitude = [ x, y ];
			return this;
		},
		getSource: function () {
			return [
				'var sx = Math.sin(' + sines[ 0 ] / 100 + ' * y + ' + offset[ 0 ] + ') * ' + amplitude[ 0 ] + ' + x;',
				'var sy = Math.sin(' + sines[ 1 ] / 100 + ' * x + ' + offset[ 1 ] + ') * ' + amplitude[ 1 ] + ' + y;',
				'var color = TG.Utils.getPixelBilinear(src, sx, sy, 0, width);'
			].join( '\n' );
		}
	} );

};

TG.Twirl = function () {

	var strength = 0;
	var radius = 120;
	var position = [ 128, 128 ];

	return new TG.Program( {
		strength: function ( value ) {
			strength = value / 100.0;
			return this;
		},
		radius: function ( value ) {
			radius = value;
			return this;
		},
		position: function ( x, y ) {
			position = [ x, y ];
			return this;
		},
		getSource: function () {
			return [
				'var dist = TG.Utils.distance( x, y, ' + position[ 0 ] + ',' + position[ 1 ] + ');',

				// no distortion if outside of whirl radius.

				'dist = dist > '+ radius +' ? 0 : ('+ radius +' - dist) * (' + radius + ' - dist) / ' + radius + ';',

				'var angle = 2.0 * Math.PI * (dist / (' + radius + ' / ' + strength + '));',
				'var xpos = (((x - ' + position[ 0 ] + ') * Math.cos(angle)) - ((y - ' + position[ 0 ] + ') * Math.sin(angle)) + ' + position[ 0 ] + ' + 0.5);',
				'var ypos = (((y - ' + position[ 1 ] + ') * Math.cos(angle)) + ((x - ' + position[ 1 ] + ') * Math.sin(angle)) + ' + position[ 1 ] + ' + 0.5);',

				'var color = TG.Utils.getPixelBilinear(src, xpos, ypos, 0, width);'

			].join( '\n' );
		}
	} );

};

TG.Utils = {

	smoothStep: function ( edge0, edge1, x ) {

		// Scale, bias and saturate x to 0..1 range
		x = TG.Utils.clamp( ( x - edge0 ) / ( edge1 - edge0 ), 0, 1 );

		// Evaluate polynomial
		return x * x * ( 3 - 2 * x );

	},

	distance: function( x0, y0, x1, y1 ) {

		var dx = x1 - x0, dy = y1 - y0;
		return Math.sqrt( dx * dx + dy * dy );

	},

	clamp: function( value, min, max ) {

		return Math.min( Math.max( value, min ), max );

	},

	getPixelNearest: function( pixels, x, y, offset, width ) {

		return pixels[ offset + Math.round( y ) * width * 4 + Math.round( x ) * 4 ];

	},

	getPixelBilinear: function( pixels, x, y, offset, width ) {

		var percentX = x - ( x ^ 0 );
		var percentX1 = 1.0 - percentX;
		var percentY = y - ( y ^ 0 );
		var fx4 = ( x ^ 0 ) * 4;
		var cx4 = fx4 + 4;
		var fy4 = ( y ^ 0 ) * 4;
		var cy4wo = ( fy4 + 4 ) * width + offset;
		var fy4wo = fy4 * width + offset;

		var top = pixels[ cy4wo + fx4 ] * percentX1 + pixels[ cy4wo + cx4 ] * percentX;
		var bottom = pixels[ fy4wo + fx4 ] * percentX1 + pixels[ fy4wo + cx4 ] * percentX;

		return top * percentY + bottom * ( 1.0 - percentY );

	}

};
<|endoftext|>


<commit_before>
var url = require('url')
var debug = require('debug')
  , chalk = require('chalk')
  , prettyjson = require('prettyjson')
  , extend = require('extend')

var is = {
  req: debug('req'),
  res: debug('res'),
  http: debug('http'),
  raw: debug('raw'),
  body: debug('body'),
  json: debug('json')
}

var options = {
  keysColor: 'blue',
  stringColor: 'grey'
}

function log (req) {
  req.on('options', function (_options) {
    if (is.raw.name === 'enabled') {
      console.log(chalk.gray.inverse('options'))
      console.log(prettyjson.render(_options, options, 4))
    }
  })

  req.on('request', function (req, _options) {
    if (is.http.name === 'enabled') {
      console.log(chalk.gray.inverse('options'))
      console.log(prettyjson.render(_options, options, 4))
    }

    if (is.req.name === 'enabled') {
      var mt = method(req.method)
      console.log(
        chalk.yellow.inverse('req'),
        mt(req.method),
        chalk.yellow(uri(req))
      )

      var headers = {}
      for (var key in req._headerNames) {
        var name = req._headerNames[key]
        headers[name] = req._headers[key]
      }
      console.log(prettyjson.render(headers, options, 4))
    }

    if (is.body.name === 'enabled') {
      if (_options.body) {
        console.log(chalk.gray.inverse('body'), _options.body)
      }
    }
  })

  req.on('response', function (res) {
    var code = res.statusCode

    var st = status(res.statusCode)
    if (is.res.name === 'enabled') {
      console.log(
        st.inverse('res'),
        st(res.statusCode + ' ' + res.statusMessage))
      console.log(prettyjson.render(res.headers, options, 4))
    }
  })

  req.on('callback', function (body) {
    if (is.body.name === 'enabled') {
      console.log(chalk.gray.inverse('body'), body)
    }
  })

  req.on('json', function (body) {
    if (is.json.name === 'enabled') {
      console.log(chalk.gray.inverse('json'), body)
    }
  })
}

function method (verb) {
  if (/GET/.test(verb)) {
    return chalk.green
  }
  else if (/POST/.test(verb)) {
    return chalk.cyan
  }
  else if (/PUT/.test(verb)) {
    return chalk.cyan
  }
  else if (/DELETE/.test(verb)) {
    return chalk.red
  }
  else if (/HEAD|OPTIONS|CONNECT/.test(verb)) {
    return chalk.yellow
  }
  else if (/TRACE/.test(verb)) {
    return chalk.gray
  }
}

function uri (req) {
  return req.agent.protocol + '//' + req._headers.host +
    (req.path === '/' ? '' : req.path)

  // return url.format({
  //   protocol: req.agent.protocol,
  //   host: req._headers.host,
  //   pathname: (req.path === '/' ? '' : req.path)
  // })
}

function status (code) {
  if (code >= 100 && code <= 199) {
    return chalk.white
  }
  else if (code >= 200 && code <= 299) {
    return chalk.green
  }
  else if (code >= 300 && code <= 399) {
    return chalk.yellow
  }
  else if (code >= 400 && code <= 499) {
    return chalk.red
  }
  else if (code >= 500 && code <= 599) {
    return chalk.red.bold
  }
}

module.exports = log
<commit_msg>Change req and res log colors<commit_after>
var url = require('url')
var debug = require('debug')
  , chalk = require('chalk')
  , prettyjson = require('prettyjson')
  , extend = require('extend')

var is = {
  req: debug('req'),
  res: debug('res'),
  http: debug('http'),
  raw: debug('raw'),
  body: debug('body'),
  json: debug('json')
}

var options = {
  keysColor: 'blue',
  stringColor: 'grey'
}

function log (req) {
  req.on('options', function (_options) {
    if (is.raw.name === 'enabled') {
      console.log(chalk.gray.inverse('options'))
      console.log(prettyjson.render(_options, options, 4))
    }
  })

  req.on('request', function (req, _options) {
    if (is.http.name === 'enabled') {
      console.log(chalk.gray.inverse('options'))
      console.log(prettyjson.render(_options, options, 4))
    }

    if (is.req.name === 'enabled') {
      var mt = method(req.method)
      console.log(
        chalk.cyan.inverse('req'),
        mt(req.method),
        chalk.yellow(uri(req))
      )

      var headers = {}
      for (var key in req._headerNames) {
        var name = req._headerNames[key]
        headers[name] = req._headers[key]
      }
      console.log(prettyjson.render(headers, options, 4))
    }

    if (is.body.name === 'enabled') {
      if (_options.body) {
        console.log(chalk.gray.inverse('body'), _options.body)
      }
    }
  })

  req.on('response', function (res) {
    var code = res.statusCode

    var st = status(res.statusCode)
    if (is.res.name === 'enabled') {
      console.log(
        chalk.yellow.inverse('res'),
        st(res.statusCode + ' ' + res.statusMessage))
      console.log(prettyjson.render(res.headers, options, 4))
    }
  })

  req.on('callback', function (body) {
    if (is.body.name === 'enabled') {
      console.log(chalk.gray.inverse('body'), body)
    }
  })

  req.on('json', function (body) {
    if (is.json.name === 'enabled') {
      console.log(chalk.gray.inverse('json'), body)
    }
  })
}

function method (verb) {
  if (/GET/.test(verb)) {
    return chalk.green
  }
  else if (/POST/.test(verb)) {
    return chalk.cyan
  }
  else if (/PUT/.test(verb)) {
    return chalk.cyan
  }
  else if (/DELETE/.test(verb)) {
    return chalk.red
  }
  else if (/HEAD|OPTIONS|CONNECT/.test(verb)) {
    return chalk.yellow
  }
  else if (/TRACE/.test(verb)) {
    return chalk.gray
  }
}

function uri (req) {
  return req.agent.protocol + '//' + req._headers.host +
    (req.path === '/' ? '' : req.path)

  // return url.format({
  //   protocol: req.agent.protocol,
  //   host: req._headers.host,
  //   pathname: (req.path === '/' ? '' : req.path)
  // })
}

function status (code) {
  if (code >= 100 && code <= 199) {
    return chalk.white
  }
  else if (code >= 200 && code <= 299) {
    return chalk.green
  }
  else if (code >= 300 && code <= 399) {
    return chalk.yellow
  }
  else if (code >= 400 && code <= 499) {
    return chalk.red
  }
  else if (code >= 500 && code <= 599) {
    return chalk.red.bold
  }
}

module.exports = log
<|endoftext|>


<commit_before>(function() {
var echo_util = require('echo-util');
var foldl = echo_util.foldl;

var hasOwn = Object.prototype.hasOwnProperty;

function Map() {
    this.map = Object.create(null);
    this.map_size = 0;
}

Map.prototype.has = function (key) {
    return hasOwn.call(this.map, "%map" + key);
};

Map.prototype.set = function (key, val) {
    var entry_key = "%map" + key;
    var had_before = hasOwn.call(this.map, entry_key);
    this.map[entry_key] = { key: key, val: val };
    if (!had_before) this.map_size++;
};

Map.prototype.get = function (key, val) {
    var entry_key = "%map" + key;
    if (!hasOwn.call(this.map, entry_key)) return undefined;
    return this.map[entry_key].val;
};

Map.prototype.remove = function (key) {
    var entry_key = "%map" + key;
    var had_before = hasOwn.call(this.map, entry_key);

    delete this.map[entry_key];
    if (had_before) this.map_size--;
};

Map.prototype.clear = function () {
    this.map = Object.create(null);
    this.size = 0;
};

Map.prototype.forEach = function (f) {
    for (var p in this.map) {
	if (!hasOwn.call(this.map, p))
	    continue;
	var entry = this.map[p];
	f (entry.val, entry.key, this);
    }
};

Map.prototype.keys = function () {
    var result = [];
    for (var p in this.map) {
	if (!this.has (p))
	    continue;
	var entry = this.map[p];
	result.push (entry.key);
    }
    return result;
};
Map.prototype.values = function() {
    var result = [];
    for (var p in this.map) {
	if (!this.has (p))
	    continue;
	var entry = this.map[p];
	result.push (entry.value);
    }
    return result;
};

Map.prototype.size = function() {
    return this.map_size;
};

exports.Map = Map;
})();

/*
# Set tests

s1 = new Set [1, 2, 3, 4]
s2 = new Set [5, 6, 7, 8]

console.log "should be { 1 2 3 4 5 6 7 8 }:    #{(s1.union s2).toString()}"

s3 = new Set [1, 2, 3, 4, 5, 6, 7, 8]
s4 = new Set [5, 6, 7, 8]

console.log "should be { 1 2 3 4 }:    #{(s3.subtract s4).toString()}"

s5 = new Set [1, 2, 3, 4];
s6 = new Set [3, 4, 5];

console.log "should be { 3 4 }:    #{(s5.intersect s6).toString()}"

*/
<commit_msg>terrible, but we need to make the map keys unique.  time to upgrade node to something with a working Map<commit_after>(function() {
var echo_util = require('echo-util');
var foldl = echo_util.foldl;

var hasOwn = Object.prototype.hasOwnProperty;

function Map() {
    this.map = Object.create(null);
    this.map_size = 0;
}

Map.prototype.has = function (key) {
    return hasOwn.call(this.map, "%map" + JSON.stringify(key));
};

Map.prototype.set = function (key, val) {
    var entry_key = "%map" + JSON.stringify(key);
    var had_before = hasOwn.call(this.map, entry_key);
    this.map[entry_key] = { key: key, val: val };
    if (!had_before) this.map_size++;
};

Map.prototype.get = function (key, val) {
    var entry_key = "%map" + JSON.stringify(key);
    if (!hasOwn.call(this.map, entry_key)) return undefined;
    return this.map[entry_key].val;
};

Map.prototype.remove = function (key) {
    var entry_key = "%map" + JSON.stringify(key);
    var had_before = hasOwn.call(this.map, entry_key);

    delete this.map[entry_key];
    if (had_before) this.map_size--;
};

Map.prototype.clear = function () {
    this.map = Object.create(null);
    this.size = 0;
};

Map.prototype.forEach = function (f) {
    for (var p in this.map) {
	if (!hasOwn.call(this.map, p))
	    continue;
	var entry = this.map[p];
	f (entry.val, entry.key, this);
    }
};

Map.prototype.keys = function () {
    var result = [];
    for (var p in this.map) {
	if (!this.has (p))
	    continue;
	var entry = this.map[p];
	result.push (entry.key);
    }
    return result;
};
Map.prototype.values = function() {
    var result = [];
    for (var p in this.map) {
	if (!this.has (p))
	    continue;
	var entry = this.map[p];
	result.push (entry.value);
    }
    return result;
};

Map.prototype.size = function() {
    return this.map_size;
};

exports.Map = Map;
})();

/*
# Set tests

s1 = new Set [1, 2, 3, 4]
s2 = new Set [5, 6, 7, 8]

console.log "should be { 1 2 3 4 5 6 7 8 }:    #{(s1.union s2).toString()}"

s3 = new Set [1, 2, 3, 4, 5, 6, 7, 8]
s4 = new Set [5, 6, 7, 8]

console.log "should be { 1 2 3 4 }:    #{(s3.subtract s4).toString()}"

s5 = new Set [1, 2, 3, 4];
s6 = new Set [3, 4, 5];

console.log "should be { 3 4 }:    #{(s5.intersect s6).toString()}"

*/
<|endoftext|>


<commit_before>'use strict';

var Promise = require('./promise');
var normalizeObj = require('./normalizeObj');
var makeError = require('./makeError');
var checkTile = require('./checkTile');
var merc = require('./merc');
var mime = require('mime');
var mapnik = require('mapnik');
var Image = mapnik.Image;
var blend = mapnik.blend;
var Color = mapnik.Color;
var defaultCache = require('./memCache');
var EE = require('events').EventEmitter;
var util = require('util')
var makeUnknownError = require('./makeUnknownError');
var _abaculus = require('@mapbox/abaculus');
var abaculus = util.promisify(_abaculus);
var getEtag = require('./getEtag');
var find = require('./find');
var imageType = require('./image-type');

var requiredParams = [
  'layers',
  'bbox',
  'width',
  'height',
  'format',
  'srs'
];
const MAX_SIZE = 19008;
var fromBytes = util.promisify(Image.fromBytes);

function mapnikResize(img, width, height) {
  return new Promise((yes, no) => {
    img.resize(width, height, {
      scaling_method: mapnik.imageScaling.sinc
    }, (err, resp) => {
      if (err) {
        no(err);
      } else {
        yes(resp);
      }
    });
  });
}

function mapnikEncode(img, format) {
  return new Promise((yes, no) => {
    img.encode(format, (err, resp) => {
      if (err) {
        no(err);
      } else {
        yes(resp);
      }
    });
  });
}

function maybePremultiply(img) {
  if (img.premultiplied()) {
    return Promise.resolve(img);
  }
  return new Promise((yes, no) => {
    img.premultiply((err, buf) => {
      if (err) {
        return no(err);
      }
      yes(buf);
    });
  });
}

async function resize(image, format, width, height) {
  image = Array.isArray(image) ? image[0] : image;
  let mapnikImage = await fromBytes(image);
  let maybePremultiplied = await maybePremultiply(mapnikImage);
  let resized = await mapnikResize(maybePremultiplied, width, height);
  let output = await mapnikEncode(resized, format);
  return output;
}

async function getMap(layer, rawParams) {
  try {
    layer = await layer;
  } catch (e) {
    return makeUnknownError(e);
  }
  if (!layer) {
    throw new TypeError('must include layer');
  }
  var params = normalizeObj(rawParams);
  var i = -1;
  var len = requiredParams.length;
  var param;
  if (params.crs && !params.srs) {
    params.srs = params.crs;
  }
  while (++i < len) {
    param = requiredParams[i];
    if (!params[param]) {
      return makeError(`missing required parameter: ${param}`, 'MissingParameterValue', param);
    }
  }
  var srs = params.srs || params.crs;
  srs = srs.toLowerCase();
  if (['epsg:900913', 'epsg:3857', 'epsg:4326'].indexOf(srs) === -1) {
    return makeError(`invalid srs: ${srs}`, 'InvalidSRS');
  }
  var scale;
  if (params.dpi || params.map_resolution) {
    scale = Math.round(72 / parseInt(params.dpi || params.map_resolution, 10)) || 1;
  } else {
    scale = 1;
  }
  if (scale !== scale) {
    scale = 1;
  }
  var format = mime.extension(params.format);
  var bgcolor = params.bgcolor || '0xffffff';
  bgcolor = bgcolor.toLowerCase();
  if (params.transparent && params.transparent.toLowerCase() === 'true' && format === 'png') {
    bgcolor = false;
  }
  var abort = layer.abort || new EE();
  try {
    layer = makeLayer(layer, params.layers, bgcolor, format, abort);
  } catch (e) {
    if (e.layerLengthError) {
      return makeError(e.message, 'InvalidParameterValue', 'LAYER');
    }
    return makeError(e.message);
  }
  if (!layer) {
    return makeError(`No such layer: ${params.layer}`, 'InvalidParameterValue', 'LAYER');
  }
  if (layer.viewable === false) {
    return {
      headers: {},
      data: new Buffer('not authorized'),
      code: 401
    };
  }
  if (typeof layer.getTile !== 'function') {
    throw new TypeError('must include getTile function');
  }
  var bbox = params.bbox.split(',').map(function(num) {
    return parseFloat(num);
  });
  if (['epsg:900913', 'epsg:3857'].indexOf(srs) > -1) {
    bbox = merc.inverse([bbox[0], bbox[1]]).concat(merc.inverse([bbox[2], bbox[3]]));
  }
  var width = parseInt(params.width, 10);
  if (width < 1) {
    return makeError('width must be greater then 0', 'InvalidParameterValue', 'WIDTH');
  }
  var height = parseInt(params.height, 10);
  if (height < 1) {
    return makeError('height must be greater then 1', 'InvalidParameterValue', 'HEIGHT');
  }
  var zoom = getZoom(bbox, [width, height], layer.range[0], layer.range[1]);

  var opts = {
    scale: scale,
    zoom: zoom,
    bbox: bbox,
    getTile: makeGetTile(layer, bgcolor, format),
    format: format
  };
  try {
    _abaculus.coordsFromBbox(zoom, scale, bbox, MAX_SIZE);
  } catch (e) {
    return makeError(e.message, 'InvalidDimensionValue');
  }
  var image, resizedImage;
  try {
    image = await abaculus(opts);
  } catch (e) {
    return makeUnknownError(e);
  }
  if (abort.aborted) {
    return makeUnknownError(new Error('aborted'));
  }
  try {
    resizedImage = await resize(image, format, width, height);
  } catch (e) {
    return makeError(e && e.message || 'error resizing image, please check dimensions');
  }
  if (abort.aborted) {
    return makeUnknownError(new Error('aborted'));
  }
  var headers = {
    'content-type': mime.lookup(format),
    'content-length': resizedImage.length,
    etag: getEtag(resizedImage)
  };
  return {
    data: resizedImage,
    headers: headers,
    code: 200
  };

}

function getZoom(bounds, dimensions, minzoom, maxzoom) {
  minzoom = (minzoom === undefined) ? 0 : minzoom;
  maxzoom = (maxzoom === undefined) ? 20 : maxzoom;

  var bl = merc.px([bounds[0], bounds[1]], maxzoom);
  var tr = merc.px([bounds[2], bounds[3]], maxzoom);
  var width = tr[0] - bl[0];
  var height = bl[1] - tr[1];
  var ratios = [width / dimensions[0], height / dimensions[1]];
  var adjusted = Math.ceil(Math.min(
    maxzoom - (Math.log(ratios[0]) / Math.log(2)),
    maxzoom - (Math.log(ratios[1]) / Math.log(2))));
  return Math.max(minzoom, Math.min(maxzoom, adjusted));

}
module.exports = function(layer, params, cache, callback) {
  if (typeof cache === 'function') {
    callback = cache;
    cache = undefined;
  }
  if (typeof cache === 'undefined') {
    cache = defaultCache;
  }
  return Promise.resolve(getMap(layer, params, cache)).asCallback(callback);
};
var blankPNG = new Buffer('iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABmJLR0QA/wD/AP+gvaeTAAABFUlEQVR42u3BMQEAAADCoPVP7WsIoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAMBPAAB2ClDBAAAAABJRU5ErkJggg==', 'base64');
var blanks = new Map();

function callBlankBack(tile, format, callback) {
  var headers = {
    'content-type': mime.lookup(format),
    'content-length': tile.length
  };
  callback(null, tile, headers);
}

function sendBlank(bgcolor, format, callback) {
  if (!format) {
    return callback(new Error('not found'));
  }
  if (bgcolor === false) {
    return callBlankBack(blankPNG, format, callback);
  }
  if (bgcolor.slice(0, 2) === '0x') {
    bgcolor = bgcolor.slice(2);
  }
  if (bgcolor.length === 3) {
    bgcolor = bgcolor[0] + bgcolor[0] + bgcolor[1] + bgcolor[1] + bgcolor[2] + bgcolor[2];
  }
  if (bgcolor.length !== 6) {
    bgcolor = 'ffffff';
  }
  var key = bgcolor + format;
  if (blanks.has(key)) {
    return callBlankBack(blanks.get(key), format, callback);
  }
  makeTile(bgcolor, format, function(err, image) {
    if (err) {
      return callback(err);
    }
    if (!blanks.has(key)) {
      blanks.set(key, image);
    }
    callBlankBack(image, format, callback);
  });
}

function makeTile(bgcolor, format, cb) {
  var image = new Image(256, 256);
  image.fill(new Color('#' + bgcolor + 'ff'), function(err, resp) {
    if (err) {
      return cb(err);
    }
    resp.encode(format, cb);
  });
}

function makeGetTile(layer, bgcolor, format) {
  return getTile;

  function getTile(z, x, y, callback) {
    if (checkTile(layer, x, y, z)) {
      return sendBlank(bgcolor, format, callback);
    }
    var aborted = false;
    var req;
    actualGet(true);
    return {
      abort() {
        aborted = true;
        if (req) {
          req.abort();
        }
      }
    }

    function actualGet(retry) {
      req = layer.getTile(z, x, y, function(err, tile, headers) {
        req = null;
        if (err) {
          if (retry && err.message === 'timeout' && !aborted) {
            return actualGet();
          }
          return sendBlank(bgcolor, format, callback);
        }
        callback(null, tile, headers);
      });
    }
  }
}

function makeLayer(layerArray, layerParam, bgcolor, format, abort) {
  if (layerParam.indexOf(',') === -1) {
    return find(layerArray, layerParam);
  }
  var layers = layerParam.split(',');
  if (typeof layerArray.layerLimit === 'number' && layers.length > layerArray.layerLimit) {
    var e = new Error(`LayerLimit is ${layerArray.layerLimit} but ${layers.length} layers were requested`);
    e.layerLengthError = true;
    throw e;
  }
  var layerObjects = layers.map(function(item) {
    return find(layerArray, item);
  });
  if (layerObjects.some(function(layer) {
    return !layer || layer.viewable === false;
  })) {
    return false;
  }
  return layerObjects.reduce(function(acc, item) {
    acc.range = [Math.min(acc.range[0], item.range[0]), Math.max(acc.range[1], item.range[1])];
    acc.bbox = [Math.min(acc.bbox[0], item.bbox[0]), Math.min(acc.bbox[1], item.bbox[1]),
      Math.max(acc.bbox[2], item.bbox[2]), Math.max(acc.bbox[3], item.bbox[3])
    ];
    return acc;
  }, {
    range: [Infinity, -Infinity],
    bbox: [Infinity, Infinity, -Infinity, -Infinity],
    getTile: makeGetTiles(layerObjects, bgcolor, format, abort)
  });
}
var getFuncMap = new WeakMap();

function noop() {}
async function parallel (list, fun) {
  var i = list.length;
  var out = [];
  while (i--) {
    let result = await fun(list[i]);
    if (!result) {
      continue;
    }
    out.push(result);
    if (imageType(result.tile) === 'image/jpeg') {
      break;
    }
  }
  out.reverse();
  return out;
}

function makeGetTiles(layerObjects, bgcolor, format, abort) {
  var aborts = new Set();

  function cancelAll() {
    aborts.forEach(function(f) {
      f();
    });
  }
  abort.on('abort', cancelAll);
  return getTile;

  function getTile(z, x, y, callback) {
    parallel(layerObjects, function(layer) {
      return new Promise(function(resolve) {
        var getTile;
        if (getFuncMap.has(layer)) {
          getTile = getFuncMap.get(layer);
        } else {
          getTile = makeGetTile(layer);
          getFuncMap.set(layer, getTile);
        }
        var cancel;
        var out = getTile(z, x, y, function(err, tile, headers) {
          aborts.delete(cancel);
          if (err) {
            return resolve();
          }
          resolve({
            tile: tile,
            headers: headers
          });
        });
        cancel = out.abort || noop;
        aborts.add(cancel);
      });
    }).then(function(things) {
      abort.removeListener('abort', cancelAll);
      var filtered = things.filter(function(item) {
        return item;
      });
      if (!filtered.length) {
        return sendBlank(bgcolor, format, callback);
      }
      if (filtered.length === 1) {
        return callback(null, filtered[0].tile, filtered[0].headers);
      }
      blend(filtered.map(function(item) {
        return item.tile;
      }), {
        format: 'png',
        width: 256,
        height: 256
      }, function(err, resp) {
        if (err || abort.aborted) {
          return sendBlank(bgcolor, format, callback);
        }

        var headers = {
          etag: getEtag(resp),
          'Content-Type': 'image/png'
        };
        callback(null, resp, headers);
      });
    });
  }
}
<commit_msg>better size limits, curently you can get a bit stuck<commit_after>'use strict';

var Promise = require('./promise');
var normalizeObj = require('./normalizeObj');
var makeError = require('./makeError');
var checkTile = require('./checkTile');
var merc = require('./merc');
var mime = require('mime');
var mapnik = require('mapnik');
var Image = mapnik.Image;
var blend = mapnik.blend;
var Color = mapnik.Color;
var defaultCache = require('./memCache');
var EE = require('events').EventEmitter;
var util = require('util')
var makeUnknownError = require('./makeUnknownError');
var _abaculus = require('@mapbox/abaculus');
var abaculus = util.promisify(_abaculus);
var getEtag = require('./getEtag');
var find = require('./find');
var imageType = require('./image-type');

var requiredParams = [
  'layers',
  'bbox',
  'width',
  'height',
  'format',
  'srs'
];
const MAX_SIZE4 = 19008;
const MAX_SIZE = 4752
var fromBytes = util.promisify(Image.fromBytes);

function mapnikResize(img, width, height) {
  return new Promise((yes, no) => {
    img.resize(width, height, {
      scaling_method: mapnik.imageScaling.sinc
    }, (err, resp) => {
      if (err) {
        no(err);
      } else {
        yes(resp);
      }
    });
  });
}

function mapnikEncode(img, format) {
  return new Promise((yes, no) => {
    img.encode(format, (err, resp) => {
      if (err) {
        no(err);
      } else {
        yes(resp);
      }
    });
  });
}

function maybePremultiply(img) {
  if (img.premultiplied()) {
    return Promise.resolve(img);
  }
  return new Promise((yes, no) => {
    img.premultiply((err, buf) => {
      if (err) {
        return no(err);
      }
      yes(buf);
    });
  });
}

async function resize(image, format, width, height) {
  image = Array.isArray(image) ? image[0] : image;
  let mapnikImage = await fromBytes(image, {max_size: MAX_SIZE});
  let maybePremultiplied = await maybePremultiply(mapnikImage);
  let resized = await mapnikResize(maybePremultiplied, width, height);
  let output = await mapnikEncode(resized, format);
  return output;
}

async function getMap(layer, rawParams) {
  try {
    layer = await layer;
  } catch (e) {
    return makeUnknownError(e);
  }
  if (!layer) {
    throw new TypeError('must include layer');
  }
  var params = normalizeObj(rawParams);
  var i = -1;
  var len = requiredParams.length;
  var param;
  if (params.crs && !params.srs) {
    params.srs = params.crs;
  }
  while (++i < len) {
    param = requiredParams[i];
    if (!params[param]) {
      return makeError(`missing required parameter: ${param}`, 'MissingParameterValue', param);
    }
  }
  var srs = params.srs || params.crs;
  srs = srs.toLowerCase();
  if (['epsg:900913', 'epsg:3857', 'epsg:4326'].indexOf(srs) === -1) {
    return makeError(`invalid srs: ${srs}`, 'InvalidSRS');
  }
  var scale;
  if (params.dpi || params.map_resolution) {
    scale = Math.round(72 / parseInt(params.dpi || params.map_resolution, 10)) || 1;
  } else {
    scale = 1;
  }
  if (scale !== scale) {
    scale = 1;
  }
  var format = mime.extension(params.format);
  var bgcolor = params.bgcolor || '0xffffff';
  bgcolor = bgcolor.toLowerCase();
  if (params.transparent && params.transparent.toLowerCase() === 'true' && format === 'png') {
    bgcolor = false;
  }
  var abort = layer.abort || new EE();
  try {
    layer = makeLayer(layer, params.layers, bgcolor, format, abort);
  } catch (e) {
    if (e.layerLengthError) {
      return makeError(e.message, 'InvalidParameterValue', 'LAYER');
    }
    return makeError(e.message);
  }
  if (!layer) {
    return makeError(`No such layer: ${params.layer}`, 'InvalidParameterValue', 'LAYER');
  }
  if (layer.viewable === false) {
    return {
      headers: {},
      data: new Buffer('not authorized'),
      code: 401
    };
  }
  if (typeof layer.getTile !== 'function') {
    throw new TypeError('must include getTile function');
  }
  var bbox = params.bbox.split(',').map(function(num) {
    return parseFloat(num);
  });
  if (['epsg:900913', 'epsg:3857'].indexOf(srs) > -1) {
    bbox = merc.inverse([bbox[0], bbox[1]]).concat(merc.inverse([bbox[2], bbox[3]]));
  }
  var width = parseInt(params.width, 10);
  if (width < 1) {
    return makeError('width must be greater then 0', 'InvalidParameterValue', 'WIDTH');
  }
  var height = parseInt(params.height, 10);
  if (height < 1) {
    return makeError('height must be greater then 1', 'InvalidParameterValue', 'HEIGHT');
  }
  var zoom = getZoom(bbox, [width, height], layer.range[0], layer.range[1]);

  var opts = {
    scale: scale,
    zoom: zoom,
    bbox: bbox,
    getTile: makeGetTile(layer, bgcolor, format),
    format: format
  };
  try {
    let dimensions = _abaculus.coordsFromBbox(opts.zoom, opts.scale, opts.bbox, MAX_SIZE4)
    while (dimensions.w > MAX_SIZE || dimensions.h > MAX_SIZE) {
      opts.zoom--;
      dimensions =  _abaculus.coordsFromBbox(opts.zoom, opts.scale, opts.bbox, MAX_SIZE4);
    }
  } catch (e) {
    return makeError(e.message, 'InvalidDimensionValue');
  }

  var image, resizedImage;
  try {
    image = await abaculus(opts);
  } catch (e) {
    return makeUnknownError(e);
  }
  if (abort.aborted) {
    return makeUnknownError(new Error('aborted'));
  }
  try {
    resizedImage = await resize(image, format, width, height);
  } catch (e) {
    return makeError(e && e.message || 'error resizing image, please check dimensions');
  }
  if (abort.aborted) {
    return makeUnknownError(new Error('aborted'));
  }
  var headers = {
    'content-type': mime.lookup(format),
    'content-length': resizedImage.length,
    etag: getEtag(resizedImage)
  };
  return {
    data: resizedImage,
    headers: headers,
    code: 200
  };

}

function getZoom(bounds, dimensions, minzoom, maxzoom) {
  minzoom = (minzoom === undefined) ? 0 : minzoom;
  maxzoom = (maxzoom === undefined) ? 20 : maxzoom;

  var bl = merc.px([bounds[0], bounds[1]], maxzoom);
  var tr = merc.px([bounds[2], bounds[3]], maxzoom);
  var width = tr[0] - bl[0];
  var height = bl[1] - tr[1];
  var ratios = [width / dimensions[0], height / dimensions[1]];
  var adjusted = Math.ceil(Math.min(
    maxzoom - (Math.log(ratios[0]) / Math.log(2)),
    maxzoom - (Math.log(ratios[1]) / Math.log(2))));
  return Math.max(minzoom, Math.min(maxzoom, adjusted));

}
module.exports = function(layer, params, cache, callback) {
  if (typeof cache === 'function') {
    callback = cache;
    cache = undefined;
  }
  if (typeof cache === 'undefined') {
    cache = defaultCache;
  }
  return Promise.resolve(getMap(layer, params, cache)).asCallback(callback);
};
var blankPNG = new Buffer('iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABmJLR0QA/wD/AP+gvaeTAAABFUlEQVR42u3BMQEAAADCoPVP7WsIoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAMBPAAB2ClDBAAAAABJRU5ErkJggg==', 'base64');
var blanks = new Map();

function callBlankBack(tile, format, callback) {
  var headers = {
    'content-type': mime.lookup(format),
    'content-length': tile.length
  };
  callback(null, tile, headers);
}

function sendBlank(bgcolor, format, callback) {
  if (!format) {
    return callback(new Error('not found'));
  }
  if (bgcolor === false) {
    return callBlankBack(blankPNG, format, callback);
  }
  if (bgcolor.slice(0, 2) === '0x') {
    bgcolor = bgcolor.slice(2);
  }
  if (bgcolor.length === 3) {
    bgcolor = bgcolor[0] + bgcolor[0] + bgcolor[1] + bgcolor[1] + bgcolor[2] + bgcolor[2];
  }
  if (bgcolor.length !== 6) {
    bgcolor = 'ffffff';
  }
  var key = bgcolor + format;
  if (blanks.has(key)) {
    return callBlankBack(blanks.get(key), format, callback);
  }
  makeTile(bgcolor, format, function(err, image) {
    if (err) {
      return callback(err);
    }
    if (!blanks.has(key)) {
      blanks.set(key, image);
    }
    callBlankBack(image, format, callback);
  });
}

function makeTile(bgcolor, format, cb) {
  var image = new Image(256, 256);
  image.fill(new Color('#' + bgcolor + 'ff'), function(err, resp) {
    if (err) {
      return cb(err);
    }
    resp.encode(format, cb);
  });
}

function makeGetTile(layer, bgcolor, format) {
  return getTile;

  function getTile(z, x, y, callback) {
    if (checkTile(layer, x, y, z)) {
      return sendBlank(bgcolor, format, callback);
    }
    var aborted = false;
    var req;
    actualGet(true);
    return {
      abort() {
        aborted = true;
        if (req) {
          req.abort();
        }
      }
    }

    function actualGet(retry) {
      req = layer.getTile(z, x, y, function(err, tile, headers) {
        req = null;
        if (err) {
          if (retry && err.message === 'timeout' && !aborted) {
            return actualGet();
          }
          return sendBlank(bgcolor, format, callback);
        }
        callback(null, tile, headers);
      });
    }
  }
}

function makeLayer(layerArray, layerParam, bgcolor, format, abort) {
  if (layerParam.indexOf(',') === -1) {
    return find(layerArray, layerParam);
  }
  var layers = layerParam.split(',');
  if (typeof layerArray.layerLimit === 'number' && layers.length > layerArray.layerLimit) {
    var e = new Error(`LayerLimit is ${layerArray.layerLimit} but ${layers.length} layers were requested`);
    e.layerLengthError = true;
    throw e;
  }
  var layerObjects = layers.map(function(item) {
    return find(layerArray, item);
  });
  if (layerObjects.some(function(layer) {
    return !layer || layer.viewable === false;
  })) {
    return false;
  }
  return layerObjects.reduce(function(acc, item) {
    acc.range = [Math.min(acc.range[0], item.range[0]), Math.max(acc.range[1], item.range[1])];
    acc.bbox = [Math.min(acc.bbox[0], item.bbox[0]), Math.min(acc.bbox[1], item.bbox[1]),
      Math.max(acc.bbox[2], item.bbox[2]), Math.max(acc.bbox[3], item.bbox[3])
    ];
    return acc;
  }, {
    range: [Infinity, -Infinity],
    bbox: [Infinity, Infinity, -Infinity, -Infinity],
    getTile: makeGetTiles(layerObjects, bgcolor, format, abort)
  });
}
var getFuncMap = new WeakMap();

function noop() {}
async function parallel (list, fun) {
  var i = list.length;
  var out = [];
  while (i--) {
    let result = await fun(list[i]);
    if (!result) {
      continue;
    }
    out.push(result);
    if (imageType(result.tile) === 'image/jpeg') {
      break;
    }
  }
  out.reverse();
  return out;
}

function makeGetTiles(layerObjects, bgcolor, format, abort) {
  var aborts = new Set();

  function cancelAll() {
    aborts.forEach(function(f) {
      f();
    });
  }
  abort.on('abort', cancelAll);
  return getTile;

  function getTile(z, x, y, callback) {
    parallel(layerObjects, function(layer) {
      return new Promise(function(resolve) {
        var getTile;
        if (getFuncMap.has(layer)) {
          getTile = getFuncMap.get(layer);
        } else {
          getTile = makeGetTile(layer);
          getFuncMap.set(layer, getTile);
        }
        var cancel;
        var out = getTile(z, x, y, function(err, tile, headers) {
          aborts.delete(cancel);
          if (err) {
            return resolve();
          }
          resolve({
            tile: tile,
            headers: headers
          });
        });
        cancel = out.abort || noop;
        aborts.add(cancel);
      });
    }).then(function(things) {
      abort.removeListener('abort', cancelAll);
      var filtered = things.filter(function(item) {
        return item;
      });
      if (!filtered.length) {
        return sendBlank(bgcolor, format, callback);
      }
      if (filtered.length === 1) {
        return callback(null, filtered[0].tile, filtered[0].headers);
      }
      blend(filtered.map(function(item) {
        return item.tile;
      }), {
        format: 'png',
        width: 256,
        height: 256
      }, function(err, resp) {
        if (err || abort.aborted) {
          return sendBlank(bgcolor, format, callback);
        }

        var headers = {
          etag: getEtag(resp),
          'Content-Type': 'image/png'
        };
        callback(null, resp, headers);
      });
    });
  }
}
<|endoftext|>


<commit_before>
'use strict';

const assert = require('assert');
const debug = require('debug')('moo');

const esprima = require('esprima');
const toValue = require('esprima-to-value');
const getObject = require('esprima-get-object');

function moo (code) {
  let ret;
  const root = esprima.parse(code);

  // assert the root's type is program
  assert.equal(root.type, 'Program');

  // access to model setup function
  const setup = root.body[0].expression.right;
  assert.equal(setup.type, 'FunctionExpression');
  assert.equal(setup.params.length, 1, setup.params);

  const model = setup.params[0].name;
  const blocks = setup.body.body;

  blocks.forEach(function (b) {
    if (b.type === 'ExpressionStatement') {
      if (b.expression.type === 'CallExpression') {
        if (b.expression.callee.object.name === model) {
          if (b.expression.callee.property.name === 'remoteMethod') {
            console.log(JSON.stingify(b.expression.arguments, null, 2));
            ret = toValue(b.expression.arguments);
          }
        }
      }
    }
  });

  return ret;
}

module.exports = moo;
<commit_msg>debug<commit_after>
'use strict';

const assert = require('assert');
const debug = require('debug')('moo');

const esprima = require('esprima');
const toValue = require('esprima-to-value');
const getObject = require('esprima-get-object');

function moo (code) {
  let ret;
  const root = esprima.parse(code);

  // assert the root's type is program
  assert.equal(root.type, 'Program');

  // access to model setup function
  const setup = root.body[0].expression.right;
  assert.equal(setup.type, 'FunctionExpression');
  assert.equal(setup.params.length, 1, setup.params);

  const model = setup.params[0].name;
  const blocks = setup.body.body;

  blocks.forEach(function (b) {
    if (b.type === 'ExpressionStatement') {
      if (b.expression.type === 'CallExpression') {
        if (b.expression.callee.object.name === model) {
          if (b.expression.callee.property.name === 'remoteMethod') {
            console.log(JSON.stringify(b.expression.arguments, null, 2));
            ret = toValue(b.expression.arguments);
          }
        }
      }
    }
  });

  return ret;
}

module.exports = moo;
<|endoftext|>