<commit_before>// @ts-check
"use strict"
const { spawnSync } = require("child_process")
const updatePlatfromChangeLog = require("./generatePlatformChangelog").updatePlatfromChangeLog
const Octokit = require("@octokit/rest")
const ora = require("ora")

const DEFAULT_CHANGELOG_BRANCH = "update-changelog"

const octokit = new Octokit({ auth: process.env.CHANGELOG_GITHUB_TOKEN_KEY })

/**
 * @param {string} command
 */
const exec = (command) => {
  const task = spawnSync(command, { shell: true })
  if (task.status != 0) {
    console.log(task.stderr.toString())
  }
  return task.stdout.toString()
}

/**
 * Checks out the branch, creating it if it doesn't already exist
 */
const forceCheckout = () => {
  const logger = ora("force checkout").start()
  try {
    exec(`git checkout ${DEFAULT_CHANGELOG_BRANCH}`)
    exec(`git reset master --hard`)
  } catch (_) {
    exec(`git checkout -b ${DEFAULT_CHANGELOG_BRANCH}`)
  } finally {
    logger.succeed()
  }
}

/**
 * Checks if no file is changed
 */
const hasNoChanges = () => {
  // @ts-ignore
  return exec("git status --porcelain") === ""
}

/**
 * Commit and push changes
 */
const commitAndPushChanges = () => {
  const logger = ora("commiting and pushing changes").start()
  exec(`git add CHANGELOG/android-changelog.md`)
  exec(`git add CHANGELOG/ios-changelog.md`)
  const result = spawnSync("git", ["commit", "-m", "Update Changelog"])
  if (result.status !== 0) {
    logger.fail()
    process.exit(1)
  }
  exec(`git push origin ${DEFAULT_CHANGELOG_BRANCH} --force --no-verify`)
  logger.succeed()
}

/**
 * Check if an open pull request already exists
 */
const pullRequestAlreadyExists = async () => {
  const res = await octokit.pulls.list({
    repo: "eigen",
    state: "open",
    owner: "artsy",
  })
  return res.data.some((pr) => pr.head.ref === DEFAULT_CHANGELOG_BRANCH)
}

const createAndMergePullRequest = async () => {
  const logger = ora("creating pull request").start()

  // Create the PR
  const res = await octokit.pulls.create({
    repo: "eigen",
    head: DEFAULT_CHANGELOG_BRANCH,
    owner: "artsy",
    base: "master",
    title: "Update Changelog ✍",
    body: "This is an automatic PR to update the changelog ✍",
  })

  // Add Label to the PR
  await octokit.issues.addLabels({
    repo: "eigen",
    issue_number: res.data.number,
    owner: "artsy",
    labels: ["Changelog Updater", "Merge On Green"],
  })

  logger.succeed()
}

const main = async () => {
  // Make sure we are on a clean branch and checkout to it
  forceCheckout()
  // Run the changelog updater
  await Promise.all([updatePlatfromChangeLog("android", "beta"), updatePlatfromChangeLog("ios", "beta")])

  // Check if we have any changes in the changelog
  // If no changes were found, no further action needed, quit
  if (hasNoChanges()) {
    ora("no changes were made, no further action needed")
    return
  }
  // Otherwise, Commit and push changes to the update changelog branch
  commitAndPushChanges()
  // Check if there is an open PR already
  // If yes, no further action needed, quit
  if (await pullRequestAlreadyExists()) {
    ora("there is already an open pull request, no further action needed")
    return
  }
  // Otherwise, Create a pull request and merge it
  await createAndMergePullRequest
}

main()
<commit_msg>fix: typo to call function (#5299)<commit_after>// @ts-check
"use strict"
const { spawnSync } = require("child_process")
const updatePlatfromChangeLog = require("./generatePlatformChangelog").updatePlatfromChangeLog
const Octokit = require("@octokit/rest")
const ora = require("ora")

const DEFAULT_CHANGELOG_BRANCH = "update-changelog"

const octokit = new Octokit({ auth: process.env.CHANGELOG_GITHUB_TOKEN_KEY })

/**
 * @param {string} command
 */
const exec = (command) => {
  const task = spawnSync(command, { shell: true })
  if (task.status != 0) {
    console.log(task.stderr.toString())
  }
  return task.stdout.toString()
}

/**
 * Checks out the branch, creating it if it doesn't already exist
 */
const forceCheckout = () => {
  const logger = ora("force checkout").start()
  try {
    exec(`git checkout ${DEFAULT_CHANGELOG_BRANCH}`)
    exec(`git reset master --hard`)
  } catch (_) {
    exec(`git checkout -b ${DEFAULT_CHANGELOG_BRANCH}`)
  } finally {
    logger.succeed()
  }
}

/**
 * Checks if no file is changed
 */
const hasNoChanges = () => {
  // @ts-ignore
  return exec("git status --porcelain") === ""
}

/**
 * Commit and push changes
 */
const commitAndPushChanges = () => {
  const logger = ora("commiting and pushing changes").start()
  exec(`git add CHANGELOG/android-changelog.md`)
  exec(`git add CHANGELOG/ios-changelog.md`)
  const result = spawnSync("git", ["commit", "-m", "Update Changelog"])
  if (result.status !== 0) {
    logger.fail()
    process.exit(1)
  }
  exec(`git push origin ${DEFAULT_CHANGELOG_BRANCH} --force --no-verify`)
  logger.succeed()
}

/**
 * Check if an open pull request already exists
 */
const pullRequestAlreadyExists = async () => {
  const res = await octokit.pulls.list({
    repo: "eigen",
    state: "open",
    owner: "artsy",
  })
  return res.data.some((pr) => pr.head.ref === DEFAULT_CHANGELOG_BRANCH)
}

const createAndMergePullRequest = async () => {
  const logger = ora("creating pull request").start()

  // Create the PR
  const res = await octokit.pulls.create({
    repo: "eigen",
    head: DEFAULT_CHANGELOG_BRANCH,
    owner: "artsy",
    base: "master",
    title: "Update Changelog ✍",
    body: "This is an automatic PR to update the changelog ✍",
  })

  // Add Label to the PR
  await octokit.issues.addLabels({
    repo: "eigen",
    issue_number: res.data.number,
    owner: "artsy",
    labels: ["Changelog Updater", "Merge On Green"],
  })

  logger.succeed()
}

const main = async () => {
  // Make sure we are on a clean branch and checkout to it
  forceCheckout()
  // Run the changelog updater
  await Promise.all([updatePlatfromChangeLog("android", "beta"), updatePlatfromChangeLog("ios", "beta")])

  // Check if we have any changes in the changelog
  // If no changes were found, no further action needed, quit
  if (hasNoChanges()) {
    ora("no changes were made, no further action needed")
    return
  }
  // Otherwise, Commit and push changes to the update changelog branch
  commitAndPushChanges()
  // Check if there is an open PR already
  // If yes, no further action needed, quit
  if (await pullRequestAlreadyExists()) {
    ora("there is already an open pull request, no further action needed")
    return
  }
  // Otherwise, Create a pull request and merge it
  await createAndMergePullRequest()
}

main()
<|endoftext|>


<commit_before>/**
 * Copyright 2015-2016, Google, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const fetch = require('node-fetch');
const jsrsasign = require('jsrsasign');
const {URL} = require('url');
const mime = require('mime-types');
const punycode = require('punycode');

const CACHES_JSON_URL = 'https://cdn.ampproject.org/caches.json';

class CacheRefresh {
  constructor(privateKey) {
    this._privateKey = privateKey;
    this._sig = new jsrsasign.Signature({'alg': 'SHA256withRSA'});
    this._sig.init(this._privateKey);
  }

  createCacheUpdateUrls(originUrl) {
    return this._getCaches()
      .then(caches => {
        return caches.map(cache => {
          const cacheUrl = this.createCacheUrl(originUrl, cache);
          const refreshUrl = this.createRefreshUrl(cacheUrl);
          return {id: cache.id, name: cache.name, refreshUrl: refreshUrl}
        });
      });
  }

  /**
   * Translates an url from the origin to the AMP Cache URL format, as documented here:
   *  https://developers.google.com/amp/cache/overview
   *
   * @param {String} originUrl the URL to be transformed.
   * @param {Object} cache the cache Object containing the suffix configuration.
   * @return {String} the transformed URL.
   */
  createCacheUrl(originUrl, cache) {
    const url = new URL(originUrl);
    const originalHostname = url.hostname;
    let unicodeHostname = punycode.toUnicode(originalHostname);
    unicodeHostname = unicodeHostname.replace(/-/g, '--');
    unicodeHostname = unicodeHostname.replace(/\./g, '-');

    let pathSegment = this._getResourcePath(url.pathname);
    pathSegment += url.protocol === 'https:' ? '/s/' : '/';

    url.hostname = punycode.toASCII(unicodeHostname) + '.' + cache.updateCacheApiDomainSuffix;
    url.pathname = pathSegment + originalHostname + url.pathname;
    return url.toString();
  }

  _getResourcePath(pathname) {
    const mimetype = mime.lookup(pathname);
    if (!mimetype) {
      return '/c';
    }

    console.log(mimetype);
    if (mimetype.indexOf('image/') === 0) {
      return '/i';
    }

    if (mimetype.indexOf('font') >= 0) {
      return '/r';
    }

    // Default to document
    return '/c';
  }

  /**
   * Generates a signed update-cache request URL from an the AMP Cache URL, as documented here:
   * https://developers.google.com/amp/cache/update-ping#update-cache-request
   *
   * @param {String} cacheUrl
   * @return {String}
   */
  createRefreshUrl(cacheUrl) {
    const url = new URL(cacheUrl);
    // API accepts timestamp as a UNIX Epoch in seconds.
    const timestamp = (Date.now() / 1000) | 0;

    // Create the Cache Refresh URL to be signed.
    url.pathname = '/update-cache' + url.pathname;
    url.searchParams.append('amp_action', 'flush');
    url.searchParams.append('amp_ts', timestamp);

    // Append the signature to the Cache Refresh Url.
    const urlSignature = this._createSignature(url.pathname + url.search);
    url.searchParams.append('amp_url_signature', urlSignature);
    return url.toString();
  };

  /**
   * Fetches AMP Caches information, as documented here:
   * https://github.com/ampproject/amphtml/issues/7259
   */
  _getCaches() {
    if (this._caches instanceof Array) {
      return Promise.resolve(this._caches);
    }

    return fetch(CACHES_JSON_URL)
      .then(response => response.json())
      .then(json => {
        this._caches = json.caches;
        return this._caches;
      });
  }

  _createSignature(url) {
    const signed = this._sig.signString(url);
    // Signature is returned as hex. Convert to Base64Url.
    const base64UrlSigned = jsrsasign.hextob64u(signed);
    return base64UrlSigned;
  }
}

module.exports = CacheRefresh;<commit_msg>Fix feedback `this._caches`<commit_after>/**
 * Copyright 2015-2016, Google, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const fetch = require('node-fetch');
const jsrsasign = require('jsrsasign');
const {URL} = require('url');
const mime = require('mime-types');
const punycode = require('punycode');

const CACHES_JSON_URL = 'https://cdn.ampproject.org/caches.json';

class CacheRefresh {
  constructor(privateKey) {
    this._caches = null;
    this._privateKey = privateKey;
    this._sig = new jsrsasign.Signature({'alg': 'SHA256withRSA'});
    this._sig.init(this._privateKey);
  }

  createCacheUpdateUrls(originUrl) {
    return this._getCaches()
      .then(caches => {
        return caches.map(cache => {
          const cacheUrl = this.createCacheUrl(originUrl, cache);
          const refreshUrl = this.createRefreshUrl(cacheUrl);
          return {id: cache.id, name: cache.name, refreshUrl: refreshUrl}
        });
      });
  }

  /**
   * Translates an url from the origin to the AMP Cache URL format, as documented here:
   *  https://developers.google.com/amp/cache/overview
   *
   * @param {String} originUrl the URL to be transformed.
   * @param {Object} cache the cache Object containing the suffix configuration.
   * @return {String} the transformed URL.
   */
  createCacheUrl(originUrl, cache) {
    const url = new URL(originUrl);
    const originalHostname = url.hostname;
    let unicodeHostname = punycode.toUnicode(originalHostname);
    unicodeHostname = unicodeHostname.replace(/-/g, '--');
    unicodeHostname = unicodeHostname.replace(/\./g, '-');

    let pathSegment = this._getResourcePath(url.pathname);
    pathSegment += url.protocol === 'https:' ? '/s/' : '/';

    url.hostname = punycode.toASCII(unicodeHostname) + '.' + cache.updateCacheApiDomainSuffix;
    url.pathname = pathSegment + originalHostname + url.pathname;
    return url.toString();
  }

  _getResourcePath(pathname) {
    const mimetype = mime.lookup(pathname);
    if (!mimetype) {
      return '/c';
    }

    console.log(mimetype);
    if (mimetype.indexOf('image/') === 0) {
      return '/i';
    }

    if (mimetype.indexOf('font') >= 0) {
      return '/r';
    }

    // Default to document
    return '/c';
  }

  /**
   * Generates a signed update-cache request URL from an the AMP Cache URL, as documented here:
   * https://developers.google.com/amp/cache/update-ping#update-cache-request
   *
   * @param {String} cacheUrl
   * @return {String}
   */
  createRefreshUrl(cacheUrl) {
    const url = new URL(cacheUrl);
    // API accepts timestamp as a UNIX Epoch in seconds.
    const timestamp = (Date.now() / 1000) | 0;

    // Create the Cache Refresh URL to be signed.
    url.pathname = '/update-cache' + url.pathname;
    url.searchParams.append('amp_action', 'flush');
    url.searchParams.append('amp_ts', timestamp);

    // Append the signature to the Cache Refresh Url.
    const urlSignature = this._createSignature(url.pathname + url.search);
    url.searchParams.append('amp_url_signature', urlSignature);
    return url.toString();
  };

  /**
   * Fetches AMP Caches information, as documented here:
   * https://github.com/ampproject/amphtml/issues/7259
   */
  _getCaches() {
    if (this._caches) {
      return Promise.resolve(this._caches);
    }

    return fetch(CACHES_JSON_URL)
      .then(response => response.json())
      .then(json => {
        this._caches = json.caches;
        return this._caches;
      });
  }

  _createSignature(url) {
    const signed = this._sig.signString(url);
    // Signature is returned as hex. Convert to Base64Url.
    const base64UrlSigned = jsrsasign.hextob64u(signed);
    return base64UrlSigned;
  }
}

module.exports = CacheRefresh;<|endoftext|>


<commit_before>import errors from '../../../lib/errors';

export function editTiers(_, args, req) {
  let collective;
  if (!req.remoteUser) {
    throw new errors.Unauthorized('You need to be logged in to edit tiers');
  }

  return req.loaders.collective.findById
    .load(args.id)
    .then(c => {
      if (!c) throw new Error(`Collective with id ${args.id} not found`);
      collective = c;
      return req.remoteUser.isAdmin(collective.id);
    })
    .then(canEdit => {
      if (!canEdit)
        throw new errors.Unauthorized(
          `You need to be logged in as a core contributor or as a host of the ${collective.name} collective`,
        );
    })
    .then(() => collective.editTiers(args.tiers));
}
<commit_msg>fix(graphql): handle editTiers when the value of minimumAmount is null<commit_after>import { map } from 'lodash';
import errors from '../../../lib/errors';

export function editTiers(_, args, req) {
  let collective;
  if (!req.remoteUser) {
    throw new errors.Unauthorized('You need to be logged in to edit tiers');
  }

  const tiers = map(args.tiers, tier => {
    if (!tier.minimumAmount) {
      if (tier.presets && tier.presets.length > 0 && tier.amount) {
        tier.minimumAmount = Math.min(tier.amount, ...tier.presets);
      } else if (tier.presets && tier.presets.length > 0 && !tier.amount) {
        tier.minimumAmount = Math.min(...tier.presets);
      } else if (!tier.presets && tier.amount) {
        tier.minimumAmount = tier.amount;
      } else if (tier.presets.length === 0 && tier.amount) {
        tier.minimumAmount = tier.amount;
      }
    }
    return tier;
  });

  return req.loaders.collective.findById
    .load(args.id)
    .then(c => {
      if (!c) throw new Error(`Collective with id ${args.id} not found`);
      collective = c;
      return req.remoteUser.isAdmin(collective.id);
    })
    .then(canEdit => {
      if (!canEdit)
        throw new errors.Unauthorized(
          `You need to be logged in as a core contributor or as a host of the ${collective.name} collective`,
        );
    })
    .then(() => collective.editTiers(tiers));
}
<|endoftext|>


<commit_before>'use strict'

const { expect } = require('chai')
const { getShieldsIcon } = require('../../lib/logos')
const t = (module.exports = require('../tester').createServiceTester())

t.create('Valid schema')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
      })
  )
  .expectBadge({ label: '', message: 'yo' })

t.create('color and labelColor')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        color: '#f0dcc3',
        labelColor: '#e6e6fa',
      })
  )
  .expectBadge({
    label: 'hey',
    message: 'yo',
    color: '#f0dcc3',
    labelColor: '#e6e6fa',
  })

t.create('style')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        color: '#99c',
      })
  )
  .expectBadge({
    label: 'hey',
    message: 'yo',
    // `color` is being specified by the service, not the request.
    // If the color key is here we know this has worked.
    color: '#99c',
  })

t.create('named logo')
  .get('.svg?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        namedLogo: 'npm',
      })
  )
  .after((err, res, body) => {
    expect(err).not.to.be.ok
    expect(body).to.include(getShieldsIcon({ name: 'npm' }))
  })

t.create('named logo with color')
  .get('.svg?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        namedLogo: 'npm',
        logoColor: 'blue',
      })
  )
  .after((err, res, body) => {
    expect(err).not.to.be.ok
    expect(body).to.include(getShieldsIcon({ name: 'npm', color: 'blue' }))
  })

const logoSvg = Buffer.from(
  getShieldsIcon({ name: 'npm' }).replace('data:image/svg+xml;base64,', ''),
  'base64'
).toString('ascii')

t.create('custom svg logo')
  .get('.svg?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        logoSvg,
      })
  )
  .after((err, res, body) => {
    expect(err).not.to.be.ok
    expect(body).to.include(getShieldsIcon({ name: 'npm' }))
  })

t.create('logoWidth')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        logoSvg,
        logoWidth: 30,
      })
  )
  .expectBadge({
    label: 'hey',
    message: 'yo',
    logoWidth: 30,
  })

t.create('Invalid schema)')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: -1,
      })
  )
  .expectBadge({
    label: 'custom badge',
    message: 'invalid properties: schemaVersion, label, message',
  })

t.create('Invalid schema)')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        extra: 'keys',
        bogus: true,
      })
  )
  .expectBadge({
    label: 'custom badge',
    message: 'invalid properties: extra, bogus',
  })

t.create('User color overrides success color')
  .get('.json?url=https://example.com/badge&color=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        color: 'blue',
      })
  )
  .expectBadge({ label: '', message: 'yo', color: '#101010' })

t.create('User legacy color overrides success color')
  .get('.json?url=https://example.com/badge&colorB=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        color: 'blue',
      })
  )
  .expectBadge({ label: '', message: 'yo', color: '#101010' })

t.create('User color does not override error color')
  .get('.json?url=https://example.com/badge&color=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        isError: true,
        label: 'something is',
        message: 'not right',
        color: 'red',
      })
  )
  .expectBadge({ label: 'something is', message: 'not right', color: 'red' })

t.create('User legacy color does not override error color')
  .get('.json?url=https://example.com/badge&colorB=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        isError: true,
        label: 'something is',
        message: 'not right',
        color: 'red',
      })
  )
  .expectBadge({ label: 'something is', message: 'not right', color: 'red' })

t.create('cacheSeconds')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 500,
      })
  )
  .expectHeader('cache-control', 'max-age=500')

t.create('user can override service cacheSeconds')
  .get('.json?url=https://example.com/badge&cacheSeconds=1000')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 500,
      })
  )
  .expectHeader('cache-control', 'max-age=1000')

t.create('user does not override longer service cacheSeconds')
  .get('.json?url=https://example.com/badge&cacheSeconds=450')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 500,
      })
  )
  .expectHeader('cache-control', 'max-age=500')

t.create('cacheSeconds does not override longer Shields default')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 10,
      })
  )
  .expectHeader('cache-control', 'max-age=300')

t.create('Bad scheme')
  .get('.json?url=http://example.com/badge')
  .expectBadge({ label: 'custom badge', message: 'please use https' })

t.create('Blocked domain')
  .get('.json?url=https://img.shields.io/badge/foo-bar-blue.json')
  .expectBadge({ label: 'custom badge', message: 'domain is blocked' })
<commit_msg>tests: add endpoint test for #3780 (#4067)<commit_after>'use strict'

const { expect } = require('chai')
const { getShieldsIcon } = require('../../lib/logos')
const t = (module.exports = require('../tester').createServiceTester())

t.create('Valid schema')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
      })
  )
  .expectBadge({ label: '', message: 'yo' })

t.create('color and labelColor')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        color: '#f0dcc3',
        labelColor: '#e6e6fa',
      })
  )
  .expectBadge({
    label: 'hey',
    message: 'yo',
    color: '#f0dcc3',
    labelColor: '#e6e6fa',
  })

t.create('style')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        color: '#99c',
      })
  )
  .expectBadge({
    label: 'hey',
    message: 'yo',
    // `color` is being specified by the service, not the request.
    // If the color key is here we know this has worked.
    color: '#99c',
  })

t.create('named logo')
  .get('.svg?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        namedLogo: 'npm',
      })
  )
  .after((err, res, body) => {
    expect(err).not.to.be.ok
    expect(body).to.include(getShieldsIcon({ name: 'npm' }))
  })

t.create('named logo with color')
  .get('.svg?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        namedLogo: 'npm',
        logoColor: 'blue',
      })
  )
  .after((err, res, body) => {
    expect(err).not.to.be.ok
    expect(body).to.include(getShieldsIcon({ name: 'npm', color: 'blue' }))
  })

const logoSvg = Buffer.from(
  getShieldsIcon({ name: 'npm' }).replace('data:image/svg+xml;base64,', ''),
  'base64'
).toString('ascii')

t.create('custom svg logo')
  .get('.svg?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        logoSvg,
      })
  )
  .after((err, res, body) => {
    expect(err).not.to.be.ok
    expect(body).to.include(getShieldsIcon({ name: 'npm' }))
  })

t.create('logoWidth')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        logoSvg,
        logoWidth: 30,
      })
  )
  .expectBadge({
    label: 'hey',
    message: 'yo',
    logoWidth: 30,
  })

t.create('Invalid schema)')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: -1,
      })
  )
  .expectBadge({
    label: 'custom badge',
    message: 'invalid properties: schemaVersion, label, message',
  })

t.create('Invalid schema)')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: 'hey',
        message: 'yo',
        extra: 'keys',
        bogus: true,
      })
  )
  .expectBadge({
    label: 'custom badge',
    message: 'invalid properties: extra, bogus',
  })

t.create('User color overrides success color')
  .get('.json?url=https://example.com/badge&color=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        color: 'blue',
      })
  )
  .expectBadge({ label: '', message: 'yo', color: '#101010' })

t.create('User legacy color overrides success color')
  .get('.json?url=https://example.com/badge&colorB=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        color: 'blue',
      })
  )
  .expectBadge({ label: '', message: 'yo', color: '#101010' })

t.create('User color does not override error color')
  .get('.json?url=https://example.com/badge&color=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        isError: true,
        label: 'something is',
        message: 'not right',
        color: 'red',
      })
  )
  .expectBadge({ label: 'something is', message: 'not right', color: 'red' })

t.create('User legacy color does not override error color')
  .get('.json?url=https://example.com/badge&colorB=101010')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        isError: true,
        label: 'something is',
        message: 'not right',
        color: 'red',
      })
  )
  .expectBadge({ label: 'something is', message: 'not right', color: 'red' })

t.create('cacheSeconds')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 500,
      })
  )
  .expectHeader('cache-control', 'max-age=500')

t.create('user can override service cacheSeconds')
  .get('.json?url=https://example.com/badge&cacheSeconds=1000')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 500,
      })
  )
  .expectHeader('cache-control', 'max-age=1000')

t.create('user does not override longer service cacheSeconds')
  .get('.json?url=https://example.com/badge&cacheSeconds=450')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 500,
      })
  )
  .expectHeader('cache-control', 'max-age=500')

t.create('cacheSeconds does not override longer Shields default')
  .get('.json?url=https://example.com/badge')
  .intercept(nock =>
    nock('https://example.com/')
      .get('/badge')
      .reply(200, {
        schemaVersion: 1,
        label: '',
        message: 'yo',
        cacheSeconds: 10,
      })
  )
  .expectHeader('cache-control', 'max-age=300')

t.create('Bad scheme')
  .get('.json?url=http://example.com/badge')
  .expectBadge({ label: 'custom badge', message: 'please use https' })

t.create('Blocked domain')
  .get('.json?url=https://img.shields.io/badge/foo-bar-blue.json')
  .expectBadge({ label: 'custom badge', message: 'domain is blocked' })

// https://github.com/badges/shields/issues/3780
t.create('Invalid url')
  .get('.json?url=https:/')
  .expectBadge({
    label: 'custom badge',
    message: 'invalid query parameter: url',
  })
<|endoftext|>


<commit_before>var fs = require('fs')
    , path = require('path');

parse( path.join( __dirname, "../src/verb/geom/NurbsCurve.hx") );

function parse(srcfn){

    var input = fs.readFileSync( srcfn, "utf8" );

    console.log("being parse");

//    var input = "// ok please do \n public class Foo extends Bar implements Bong, Bing, Bop {";

    var tokenStream = new TokenStream( input );
    var parser = new Parser( tokenStream );

    return parser.parse();
}
function Parser( tokenStream ){

    var currentToken, lastComment, types = [];

    function read(){
        currentToken = tokenStream.read();
         // console.log("current token is" + JSON.stringify(currentToken));
        return currentToken;
    }

    function peak(){
        return tokenStream.peak();
    }

    function parseExtends(){
        // consume "extends"
        read();

        // get the type name
        var r = read();
        return r.contents;
    }

    function parseImplements(){

        // consume "implements"
        read();

        var typeNames = [];

        while ( currentToken.type != "{" ){

            read();

            if ( currentToken.type === "identifier" ){
                typeNames.push( currentToken.contents );
            }
        }

        return typeNames;
    }

    function parseClass( visibility ){

        // get visibility from current token or default
        visibility = visibility || "public";

        // consume "class"
        read();

        // get the type name for the class
        var typeName = read().contents;

        // build the class type
        var classDef = new Class( typeName, visibility );

        // set the description
        if (lastComment){
            classDef.description = lastComment

            // don't reuse the lastComment
            lastComment = undefined;
        }

        var peaked = peak();

        // parent class
        if ( peaked.type === "extends" ){

            classDef.parentClass = parseExtends();

            // look further ahead
            peaked = peak();
        }

        // implements
        if ( peaked.type === "implements" ){
            classDef.interfaces = parseImplements();
        }

        parseClassBody( classDef );

        console.log(classDef);

        return classDef;
    }

    function parseClassBody( classDef ){

    }

    function parseTypeDefinition(){
        var visibility = read().contents;

        var peaked = peak();

        if (peaked.contents === "class"){
           return parseClass();
        }

        // throw new Error("Not implemented");
    }

    function parseComment() {
        var squashed = read();

        while ( peak().type === "comment" ){
            currentToken = tokenStream.read();

            squashed.contents += "\n";
            squashed.contents += currentToken.contents;
        }

        return lastComment = squashed;
    }

    this.parse = () => {

        var peaked;

        while ( (peaked = peak()) ){
            if (peaked.type === "class"){
                types.push( parseClass() );
            } else if ( peaked.type === "visibility" ){
                types.push( parseTypeDefinition() );
            } else if (peaked.type === "comment"){
                parseComment();
            } else {
                read();
            }
        }

        return types;
    }
}

function TokenStream( input ){

    // token state
    var i = 0;

    // helpers
    var isNumeric = (c) => c === "." || c=== "+" || c === "-" || (c <= '9' && c >= '0');
    var isInnerNumeric = (c) => isNumeric(c) || c === "e" || c === "E";
    var isWhitespace = (c) => c === '\n' || c === '\t' || c === ' ';
    var isComment = (c) => c === '/';
    var isSeparator = (c) => c === "(" || c === ")" || c === "{" || c === "}" || c === "," || c === ":" || c === "=";
    var isLineEnd = (c) => c === '\n';
    var isAlpha = (c) => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    var make = (type, contents) => ({ type : type, contents : contents || type });
    var categorizeId = (s) => {

        if (s === "class"){
            return make(s);
        } else if (s === "private"){
            return make("visibility", s);
        } else if (s === "public"){
            return make("visibility", s);
        } else if (s === "extends"){
            return make(s);
        } else if (s === "implements"){
            return make(s);
        } else if (s === "typedef"){
            return make(s);
        } else if (s === "function"){
            return make(s);
        } else if (s === "new"){
            return make(s);
        }

        return make("identifier", s);

    }

    // functions
    this.empty = () => i >= input.length;

    this.peak = () => {
        var m = i;
        var t = this.read();
        i = m;
        return t;
    };

    this.read = () => {

        var c = input.charAt(i);
        var s;

        while ( c ){

            s = "";
            c = input.charAt(i);

            // Separators
            if ( isSeparator( c ) ){

                i++;
                return make(c);

            }
            // Numbers
            else if ( isNumeric( c ) ){

                while ( c && isNumeric(c) ){
                    s += c;
                    c = input.charAt(++i);
                }

                return make("number", s);
            }
            // Name
            else if ( isAlpha(c) ){

                while ( c && !isWhitespace(c) && !isSeparator(c)){
                    s += c;
                    c = input.charAt(++i);
                }

                return categorizeId(s);

            // Comment
            } else if (isComment(c) && isComment(input.charAt(i+1))) {

                // trim comments
                i += 2;
                c = input.charAt(i);

                // trim starting whitespace
                while ( c && isWhitespace(c) ){
                    c = input.charAt(++i);
                }

                // read comments
                while ( c && !isLineEnd(c) ){
                    s += c;
                    c = input.charAt(++i);
                }

                return make("comment", s);

            }

            i++;
        }

        return null;
    }
}

function Method(name, args, returnType, description){
    this.name = name;
    this.description = "";
    this.args = args || [];
    this.returnType = returnType;
}

function MethodArgument(name, type, description){
    this.name = name;
    this.type = type;
    this.description = description;
}

function Typedef(name){
    this.name = name;
}

function Enum(name, fields){
    this.name = name;
    this.fields = fields;
}

function Interface(name){
    this.name = name;
    this.description = "";
    this.methods = [];
}

function Class(name, visibility){
    this.visibility = visibility;
    this.name = name;
    this.description = "";
    this.methods = [];
    this.parentClass = undefined;
    this.interfaces = [];
    this.properties = [];
}

<commit_msg>Parser works well for NurbsCurve<commit_after>var fs = require('fs')
    , path = require('path');

parse( path.join( __dirname, "../src/verb/geom/NurbsCurve.hx") );

function parse(srcfn){

    var input = fs.readFileSync( srcfn, "utf8" );

    var tokenStream = new TokenStream( input );
    var parser = new Parser( tokenStream );

    return parser.parse();
}

function Parser( tokenStream ){

    var debug = false;

    var currentToken, lastComment, types = [];

    function tokenMatchesAny( possibleTypes ){

        for(var i = 0; i < possibleTypes.length; i++) {
            if ( possibleTypes[i] === currentToken.type){
                return true;
            }
        }

        return false;
    }

    function consume( expectedType ){
        currentToken = tokenStream.consume();

        if (debug) console.log("currentToken", currentToken);

        if ( expectedType && !tokenMatchesAny( Array.prototype.slice.call(arguments) )){
            console.log(tokenStream.neighborhood());
            throw new Error("Syntax Error - expectedType \"" + expectedType + "\", but got \"" + currentToken.type + "\"");
        }

        return currentToken;
    }

    function peak(){
        return tokenStream.peak();
    }

    function parseExtends(){

        consume("extends");

        // get the type name
        var r = consume();
        return r.contents;
    }

    function parseIdList(){

        var idlist = []
            , peaked;

        do {
            consume();

            if ( currentToken.type === "id" ){
                idlist.push( currentToken.contents );
            }
        } while ( (peaked = peak()) && (peaked.type === "id" || peaked.type === ",") )

        return idlist;
    }

    function parseImplements(){

        consume("implements");
        return parseIdList();

    }

    function parseClass( visibility ){

        // get visibility from current token or default
        visibility = visibility || "public";

        consume("class");

        // get the type name for the class
        var typeName = consume().contents;

        // build the class type
        var classDef = new Class( typeName, visibility );

        // set the description
        if (lastComment){
            classDef.description = lastComment

            // don't reuse the lastComment
            lastComment = undefined;
        }

        var peaked = peak();

        // parent class
        if ( peaked.type === "extends" ){

            classDef.parentClass = parseExtends();

            // look further ahead
            peaked = peak();
        }

        // parse interfaces
        if ( peaked.type === "implements" ){
            classDef.interfaces = parseImplements();
        }

        parseClassBody( classDef );

        // console.log(classDef);

        return classDef;
    }

    function consumeBlock(){

        consume("{");
        var parenCount = 1;

        while ( parenCount != 0 ){
            consume();

            if (currentToken.type === "{") {
                parenCount++;
            } else if (currentToken.type === "}"){
                parenCount--;
            }
        }
    }

    function consumeIf(char){
        var peaked = peak();
        if (peaked.type === char) consume();
    }

    function consumeUntil(char){

        var peaked;
        while ( (peaked = peak()) && peaked.type != char ){
            consume();
        }

    }

    function consumeUntilInclusive(char){
        consumeUntil(char);
        consume(char);
    }

    function parseProperty( isStatic ){

        consume("var");

        var name = consume().contents;
        var type;

        var peaked = peak();

        if (peaked.type === ":"){

            consume(":");
            type = consume("id").contents;
            peaked = peak();

        }

        consumeUntilInclusive(";");

        return new Property( name, type, isStatic );
    }

    function parseMethodArgument(){

        // id : Type = expression
        var name = consume("id").contents;

        var peaked = peak();

        var type;
        if (peaked.type === ":"){
            type = parseTypeAnnotation();
            peaked = peak();
        }

        var defaultVal;
        if (peaked.type === "="){
            consume("=");
            defaultVal = consume("number", "string", "null").contents;
        }

        return new MethodArgument(name, type, defaultVal);
    }

    function parseMethodArguments(){

        // ( methodArgument, methodArgument )
        consume("(");

        var peaked, args = [];

        while ( (peaked = peak()) && peaked.type != ")"){

            if (peaked.type === "id"){
                args.push( parseMethodArgument() );
            } else if (peaked.type === ","){
                consume(","); // consume the ","
            }

        }

        consume(")");
        return args;
    }

    function getLastComment(){

        var lc = lastComment;
        lastComment = undefined;
        return lc;

    }

    function parseTypeAnnotation(){

        consume(":");
        return consume("id").contents;

    }

    function parseMethod( isStatic ){

        // function MethodName( methodArgument, methodArgument ) : ExpectedType { ... }
        consume("function");

        var name = consume("id", "new").contents;

        var args = parseMethodArguments();

        peaked = peak();

        var type;
        if (peaked.type === ":"){
           type = parseTypeAnnotation();
        }

        consumeBlock();

        return new Method( name, args, type, getLastComment() );
    }

    function parseClassMember( classDef, visibility ){

        // parse "public" or "private"
        var visibility = visibility ? visibility : consume("visibility").contents;

        // hack to ignore private members
        if ( visibility === "private"){
            classDef = new Class();
        }

        var peaked = peak();
        var isStatic = false;

        if ( peaked.type === "static" ){
            isStatic = true;

            consume("static");
            peaked = peak();
        }

        if ( peaked.type === "var" ){
            return classDef.properties.push( parseProperty( isStatic ));
        } else if (peaked.type === "function"){
            return classDef.properties.push( parseMethod( isStatic ));
        }

        throw new Error("Unknown member type encountered" + JSON.stringify( peaked ));
    }

    function parseClassBody( classDef ){

        consume("{");

        var peaked;

        while ( (peaked = peak()) && peaked.type != "}"){
            if (peaked.type === "comment"){
                parseComment();
                continue;
            } else if (peaked.type === "visibility"){
                parseClassMember( classDef );
                continue;
            } else if (peaked.type === "function"){
                parseClassMember( classDef, "private" );
                continue;
            } else if (peaked.type === "var"){
                parseClassMember( classDef, "private" );
                continue;
            } else if (peaked.type === "static"){
                parseClassMember( classDef, "private" );
                continue;
            }

            consume();
        }

        consume("}");
    }

    function parseTypeDefinition(){
        var visibility = consume("visibility").contents;

        var peaked = peak();

        if (peaked.contents === "class"){
           return parseClass();
        }

        throw new Error("Not implemented" + JSON.stringify( peaked ));
    }

    function parseComment() {
        var squashed = consume("comment");

        while ( peak().type === "comment" ){
            currentToken = consume();

            squashed.contents += "\n";
            squashed.contents += currentToken.contents;
        }

        return lastComment = squashed;
    }

    this.parse = () => {

        var peaked;

        while ( (peaked = peak()) ){
            if (peaked.type === "class"){
                types.push( parseClass() );
            } else if ( peaked.type === "visibility" ){
                types.push( parseTypeDefinition() );
            } else if (peaked.type === "comment"){
                parseComment();
            } else {
                consume();
            }
        }

        return types;
    }
}

function TokenStream( input ){

    // token state
    var i = 0;
    var peaking = false;
    var line = 1;
    var col = 0;

    // helpers
    var isNumeric = (c) => c === "." || c=== "+" || c === "-" || (c <= '9' && c >= '0');
    var isInnerNumeric = (c) => isNumeric(c) || c === "e" || c === "E";
    var isWhitespace = (c) => c === '\n' || c === '\t' || c === ' ';
    var isComment = (c) => c === '/';
    var isSeparator = (c) => c === ";" || c === "(" || c === ")" || c === "{" || c === "}" || c === "," || c === ":" || c === "=";
    var isLineEnd = (c) => c === '\n';
    var isAlpha = (c) => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    var make = (type, contents) => ({ type : type, contents : contents || type, line: line, col: col });
    var categorizeId = (s) => {

        if (s === "class"){
            return make(s);
        } else if (s === "private"){
            return make("visibility", s);
        } else if (s === "public"){
            return make("visibility", s);
        } else if (s === "extends"){
            return make(s);
        } else if (s === "implements"){
            return make(s);
        } else if (s === "typedef"){
            return make(s);
        } else if (s === "function"){
            return make(s);
        } else if (s === "static"){
            return make(s);
        } else if (s === "new"){
            return make(s);
        } else if (s === "null"){
            return make(s);
        } else if (s === "var"){
            return make(s);
        }

        return make("id", s);

    }

    // functions
    this.empty = () => i >= input.length;
    this.peak = () => {
        peaking = true;
        var m = i;
        var t = this.consume();
        i = m;
        peaking = false;
        return t;
    };
    this.neighborhood = () => {
        return input.slice(i-10, i+10);
    }

    var inc = () => {
        if (!peaking){
            col++;

            if (input.charAt(i) === '\n'){
                line++;
                col = 0;
            }
        }
        i++;
        return i;
    };

    this.consume = () => {

        var c = input.charAt(i);
        var s;

        while ( c ){

            s = "";
            c = input.charAt(i);

            // Separators
            if ( isSeparator( c ) ){

                inc();
                return make(c);

            }
            // Numbers
            else if ( isNumeric( c ) ){

                while ( c && isNumeric(c) ){
                    s += c;
                    c = input.charAt(inc());
                }

                return make("number", s);
            }
            // Name
            else if ( isAlpha(c) ){

                while ( c && !isWhitespace(c) && !isSeparator(c)){
                    s += c;
                    c = input.charAt(inc());
                }

                return categorizeId(s);

            // Comment
            } else if (isComment(c) && isComment(input.charAt(i+1))) {

                // trim comments
                inc(); inc();
                c = input.charAt(i);

                // trim starting whitespace
                while ( c && isWhitespace(c) ){
                    c = input.charAt(inc());
                }

                // consume comments
                while ( c && !isLineEnd(c) ){
                    s += c;
                    c = input.charAt(inc());
                }

                return make("comment", s);

            }

            inc();
        }

        return null;
    }
}

function Method(name, args, returnType, description){
    this.name = name;
    this.description = "";
    this.args = args || [];
    this.returnType = returnType;
}

function MethodArgument(name, type, defaultValue){
    this.name = name;
    this.type = type;
    this.defaultValue = defaultValue;
}

function Property(name, type){
    this.name = name;
    this.type = type;
}

function Typedef(name){
    this.name = name;
}

function Enum(name, fields){
    this.name = name;
    this.fields = fields;
}

function Interface(name){
    this.name = name;
    this.description = "";
    this.methods = [];
}

function Class(name, visibility){
    this.visibility = visibility;
    this.name = name;
    this.description = "";
    this.methods = [];
    this.parentClass = undefined;
    this.interfaces = [];
    this.properties = [];
}

<|endoftext|>


<commit_before>'use strict'

var path          = require('path')
var ndarray       = require('ndarray')
var GifReader     = require('omggif').GifReader
var pack          = require('ndarray-pack')
var through       = require('through')
var parseDataURI  = require('data-uri-to-buffer')

function defaultImage(url, cb) {
  var img = new Image()
  img.onload = function() {
    var canvas = document.createElement('canvas')
    canvas.width = img.width
    canvas.height = img.height
    var context = canvas.getContext('2d')
    context.drawImage(img, 0, 0)
    var pixels = context.getImageData(0, 0, img.width, img.height)
    cb(null, ndarray(new Uint8Array(pixels.data), [img.width, img.height, 4], [4, 4*img.width, 1], 0))
  }
  img.onerror = function(err) {
    cb(err)
  }
  img.src = url
}

//Animated gif loading
function handleGif(data, cb) {
  var reader
  try {
    reader = new GifReader(data)
  } catch(err) {
    cb(err)
    return
  }
  if(reader.numFrames() > 0) {
    var nshape = [reader.numFrames(), reader.height, reader.width, 4]
    var ndata = new Uint8Array(nshape[0] * nshape[1] * nshape[2] * nshape[3])
    var result = ndarray(ndata, nshape)
    try {
      for(var i=0; i<reader.numFrames(); ++i) {
        reader.decodeAndBlitFrameRGBA(i, ndata.subarray(
          result.index(i, 0, 0, 0),
          result.index(i+1, 0, 0, 0)))
      }
    } catch(err) {
      cb(err)
      return
    }
    cb(null, result.transpose(0,2,1))
  } else {
    var nshape = [reader.height, reader.width, 4]
    var ndata = new Uint8Array(nshape[0] * nshape[1] * nshape[2])
    var result = ndarray(ndata, nshape)
    try {
      reader.decodeAndBlitFrameRGBA(0, ndata)
    } catch(err) {
      cb(err)
      return
    }
    cb(null, result.transpose(1,0))
  }
}

function httpGif(url, cb) {
  var xhr          = new XMLHttpRequest()
  xhr.responseType = 'arraybuffer'
  xhr.overrideMimeType('application/binary')
  xhr.onerror = function(err) {
    cb(err)
  }
  xhr.onload = function() {
    if(xhr.readyState !== 4) {
      return
    }
    var data = new Uint8Array(xhr.response)
    handleGif(data, cb)
    return
  }
  xhr.open('GET', url, true)
  xhr.send()
}

function copyBuffer(buffer) {
  var n = buffer.length
  var result = new Uint8Array(n)
  for(var i=0; i<n; ++i) {
    result[i] = buffer.get(i)
  }
  return result
}

function dataGif(url, cb) {
  process.nextTick(function() {
    try {
      var buffer = parseDataURI(url)
      if(buffer) {
        handleGif(copyBuffer(buffer), cb)
      } else {
        cb(new Error('Error parsing data URI'))
      }
    } catch(err) {
      cb(err)
    }
  })
}

module.exports = function getPixels(url, type, cb) {
  if(!cb) {
    cb = type
    type = ''
  }
  var ext = path.extname(url)
  switch(ext.toUpperCase()) {
    case '.GIF':
      httpGif(url, cb)
    break
    default:
      if(url.indexOf('data:image/gif;') === 0) {
        dataGif(url, cb)
      } else {
        defaultImage(url, cb)
      }
  }
}<commit_msg>use array access when possible to speed up buffer conversion<commit_after>'use strict'

var path          = require('path')
var ndarray       = require('ndarray')
var GifReader     = require('omggif').GifReader
var pack          = require('ndarray-pack')
var through       = require('through')
var parseDataURI  = require('data-uri-to-buffer')

function defaultImage(url, cb) {
  var img = new Image()
  img.onload = function() {
    var canvas = document.createElement('canvas')
    canvas.width = img.width
    canvas.height = img.height
    var context = canvas.getContext('2d')
    context.drawImage(img, 0, 0)
    var pixels = context.getImageData(0, 0, img.width, img.height)
    cb(null, ndarray(new Uint8Array(pixels.data), [img.width, img.height, 4], [4, 4*img.width, 1], 0))
  }
  img.onerror = function(err) {
    cb(err)
  }
  img.src = url
}

//Animated gif loading
function handleGif(data, cb) {
  var reader
  try {
    reader = new GifReader(data)
  } catch(err) {
    cb(err)
    return
  }
  if(reader.numFrames() > 0) {
    var nshape = [reader.numFrames(), reader.height, reader.width, 4]
    var ndata = new Uint8Array(nshape[0] * nshape[1] * nshape[2] * nshape[3])
    var result = ndarray(ndata, nshape)
    try {
      for(var i=0; i<reader.numFrames(); ++i) {
        reader.decodeAndBlitFrameRGBA(i, ndata.subarray(
          result.index(i, 0, 0, 0),
          result.index(i+1, 0, 0, 0)))
      }
    } catch(err) {
      cb(err)
      return
    }
    cb(null, result.transpose(0,2,1))
  } else {
    var nshape = [reader.height, reader.width, 4]
    var ndata = new Uint8Array(nshape[0] * nshape[1] * nshape[2])
    var result = ndarray(ndata, nshape)
    try {
      reader.decodeAndBlitFrameRGBA(0, ndata)
    } catch(err) {
      cb(err)
      return
    }
    cb(null, result.transpose(1,0))
  }
}

function httpGif(url, cb) {
  var xhr          = new XMLHttpRequest()
  xhr.responseType = 'arraybuffer'
  xhr.overrideMimeType('application/binary')
  xhr.onerror = function(err) {
    cb(err)
  }
  xhr.onload = function() {
    if(xhr.readyState !== 4) {
      return
    }
    var data = new Uint8Array(xhr.response)
    handleGif(data, cb)
    return
  }
  xhr.open('GET', url, true)
  xhr.send()
}

function copyBuffer(buffer) {
  if(buffer[0] === undefined) {
    var n = buffer.length
    var result = new Uint8Array(n)
    for(var i=0; i<n; ++i) {
      result[i] = buffer.get(i)
    }
    return result
  } else {
    return new Uint8Array(buffer)
  }
}

function dataGif(url, cb) {
  process.nextTick(function() {
    try {
      var buffer = parseDataURI(url)
      if(buffer) {
        handleGif(copyBuffer(buffer), cb)
      } else {
        cb(new Error('Error parsing data URI'))
      }
    } catch(err) {
      cb(err)
    }
  })
}

module.exports = function getPixels(url, type, cb) {
  if(!cb) {
    cb = type
    type = ''
  }
  var ext = path.extname(url)
  switch(type || ext.toUpperCase()) {
    case '.GIF':
      httpGif(url, cb)
    break
    default:
      if(url.indexOf('data:image/gif;') === 0) {
        dataGif(url, cb)
      } else {
        defaultImage(url, cb)
      }
  }
}<|endoftext|>


<commit_before>

var zip = [];
var subDomainList = ["la","aa","ba"];
var callPerServer = 2;
var onworking = "";
var countajaxthread = 0;

$(document).ready(function() {
    $('#getData').click(function() {
        download_get($('#input_url').val() , $('#input_fileName').val());
    });
});

function startajax()
{
    countajaxthread = countajaxthread +1;
}

function endajax() {
    countajaxthread = countajaxthread -1;
    if(countajaxthread < 0)
    {
        alert("작가,압축파일 이름,그림파일 목록들을 불러오는데 에러가 있었습니다.");
        return false;
    }
    else if(countajaxthread == 0)
    {
        return true;
    }
    else
    {
        return false;
    }

}

function download_get(galleryhtml) {
    if(onworking == "")
    {
        printwithTime("start------------");
    }
    else
    {
        printwithTime("add download url-----------");
    }

    var ziplength = zip.length;
    var readyhtml = galleryhtml.split("https://");
    readyhtml.shift();

    getfiledata(readyhtml);

    //getimagedata(ziplength);

}

function getfiledata(readyhtml){
    var pushnumber = zip.length;
    var linkid = 0;
    for(var zipnumber = 0; zipnumber < readyhtml.length ; zipnumber++) {
        initzipnumber(zipnumber+ pushnumber);

        var galleryid = readyhtml[zipnumber].split("/");

        if(galleryid[0] == "e-hentai.org" || galleryid[0] == "exhentai.org")
        {
            if(galleryid[1] == "g")
            {
                linkid = galleryid[galleryid.length-3];
            }
            else if(galleryid == "s")
            {
                linkid = galleryid[galleryid.length-1].split("-")[0];
            }
        }
        else if(galleryid[0] == "hitomi.la")
        {
            linkid = galleryid[galleryid.length-1].split(".")[0];
        }

        setzipnumber(zipnumber+ pushnumber , 1 , linkid);
        setzipnumber(zipnumber+ pushnumber , 2 , linkid);
        setzipnumber(zipnumber+ pushnumber , 3 , readyhtml[zipnumber]);

        download_request(zipnumber+ pushnumber);
        download_gallery(zipnumber+ pushnumber);

    }

    //download_request(pushnumber);
    //download_gallery(pushnumber);

}

function  initzipnumber(zipnumber) {
    zip[zipnumber] = [];
    zip[zipnumber][0] = new JSZip();
    zip[zipnumber][1] = "";//gallery number
    zip[zipnumber][2] = "";//file name
    zip[zipnumber][3] = ""//eval galleries or reader
    zip[zipnumber][4] = [];//imageURL list
    zip[zipnumber][5] = [];//js liat
    zip[zipnumber][6] = 0;//count finish download
}

function setzipnumber(zipnumber , number , data)
{
    zip[zipnumber][number] = data;
}

function isworking()
{
    var zipnumber = -1;
    if(onworking == "")
    {
        for(i = zip.length -1 ; i > -1 ; i --)
        {
            if(zip[i][6] == 0)
            {
                zipnumber = i;
            }
        }
        onworking = "working now";
        if(zipnumber != -1)
        {
            getimagedata(zipnumber);
        }
        else
        {
            printwithTime("add more download------------");
            getimagedata(zipnumber);
        }
    }
}

function getimagedata(zipnumber) {
    if(zipnumber < zip.length)
    {
        for(var i = 0 ; (i < subDomainList.length * callPerServer) && (i < zip[zipnumber][4].length) ; i ++)
        {
            download_next_image(i , zipnumber);
        }
    }
    else
    {
        onworking = "";
        printwithTime("finish--------");
    }
}

function download_request(zipnumber) {

    var galleryid = zip[zipnumber][3].split("/");

    hitomicall(zipnumber);

}

function hitomicall(zipnumber)
{
        startajax();
        $.ajax({
            url: 'http://localhost:443/https://hitomi.la/galleries/' + zip[zipnumber][1] + '.html',
            //async:false,
            success: function (data) {
                var text1 = textsplit(data , "-gallery" , "gallery-info");

                var datatext = textsplit(text1 , "h1>" , "</h1");
                datatext = textsplit(datatext , ".html\">" , "</a");

                var creatertext = textsplit(text1 , "h2>" , "</h2");
                creatertext = textsplit(creatertext , ".html\">" , "</a");

                if(datatext == "")
                {
                    datatext = galleryid[galleryid.length - 1];
                }

                if(creatertext == "")
                {
                    creatertext = "N_A";
                }

                setzipnumber(zipnumber , 2 , creatertext + "__" + datatext);
                setzipnumber(zipnumber , 3 , "");
                if(endajax())
                {
                    isworking();
                }
            },
            error: function()
            {
                setzipnumber(zipnumber , 3 , "");
                // if(zipnumber != zip.length -1)
                //{
                //    download_request(zipnumber+1);
                // }
                if(endajax())
                {
                    isworking();
                }
            }
        });
}

function textsplit(data , sp1 , sp2)
{
    if(data.indexOf(sp1) != -1 && data.indexOf(sp2) != -1)
    {
        var text = data.split(sp1)[1].split(sp2)[0];
        return text;
    }
    else
    {
        return "";
    }

}

    function download_gallery(zipnumber) {
        startajax();
        $.ajax({
            url: 'http://localhost:443/https://hitomi.la/galleries/'+ zip[zipnumber][1] +'.js',
            //async:false,
            success: function() {
                $.each(galleryinfo, function(i, image) {
                    zip[zipnumber][4].push(url_from_url(zip[zipnumber][1] + "/" +image.name , i));
                    zip[zipnumber][5].push(image.name);
                });
                //if(zipnumber != zip.length -1)
               // {
                //    download_gallery(zipnumber+1);
                //}
                if(endajax())
                {
                    isworking();
                }
            }
        });

    }

    function subdomain_from_url(i) {
        var retval = subDomainList[i%subDomainList.length];
        return retval;
    }
    function url_from_url(url , i) {
        return "http://localhost:443/https://" + subdomain_from_url(i) + ".hitomi.la/galleries/"+ url;
    }

    function download_next_image(index , zipnumber) {
                ajax_download_blob(index, zipnumber , 0);
    }

    function ajax_download_blob(index, zipnumber , count) {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (this.readyState == 4) {
                if( this.status == 200 || this.status == 304)
                {
                    image_downloaded(this.response , index, zipnumber);
                }
                else
                {
                    if(count < 10) {
                        ajax_download_blob(index, zipnumber, count + 1);
                    }
                    else
                    {
                        alert("error on picture number" + index +"-- error " + this.status);
                    }
                }
            }
        }

        xhr.open('GET', zip[zipnumber][4][index]);
        xhr.responseType = 'arraybuffer';
        xhr.send();
    }

    function image_downloaded(imgData , index, zipnumber) {
        zip[zipnumber][0].file(zip[zipnumber][5][index], imgData, {base64: true});
        setzipnumber(zipnumber , 6 , zip[zipnumber][6] + 1);

        if (zip[zipnumber][6] >= zip[zipnumber][4].length) {
            var content = zip[zipnumber][0].generateAsync({type:"blob"}).then(function (blob) {
                saveAs(blob, zip[zipnumber][2]+".zip").then(freecontent(blob , zipnumber) , thenerror())
            } , thenerror());
            printwithTime(zip[zipnumber][2]+".zip");
            getimagedata(zipnumber+1);
        }
        else if (index + subDomainList.length * callPerServer < zip[zipnumber][4].length){
            download_next_image(index + subDomainList.length * callPerServer , zipnumber);
        }
    }

    function thenerror()
    {}

    function resetziparray(zipnumber)
    {
        setzipnumber(zipnumber , 4 , "");
        setzipnumber(zipnumber , 5 , "");
    }

    function freecontent(blob , zipnumber)
    {
        setzipnumber(zipnumber , 0 , "");
        resetziparray(zipnumber);
    }

    function printwithTime(str) {
        $('#finished_list').val( new Date().toLocaleTimeString() + ":\n " + str + "\n\n" + $('#finished_list').val());
    }

<commit_msg>set function fix<commit_after>

var zip = [];
var subDomainList = ["la","aa","ba"];
var callPerServer = 2;
var onworking = "";//lock
var countajaxthread = 0;

$(document).ready(function() {
    $('#getData').click(function() {
        download_get($('#input_url').val() , $('#input_fileName').val());
    });
});

function startajax(){
    countajaxthread = countajaxthread +1;
}

function endajax() {
    countajaxthread = countajaxthread -1;

    if(countajaxthread < 0) {
        alert("작가,압축파일 이름,그림파일 목록들을 불러오는데 에러가 있었습니다.");
        return false;
    }
    else if(countajaxthread == 0){
        return true;
    }
    else{
        return false;
    }
}

function download_get(galleryhtml) {
    if(onworking == ""){
        printwithTime("start------------");
    }
    else {
        printwithTime("add download url-----------");
    }

    var ziplength = zip.length;
    var readyhtml = galleryhtml.split("https://");
    readyhtml.shift();

    getfiledata(readyhtml);
}

function getfiledata(readyhtml){
    var pushnumber = zip.length;
    var linkid = 0;
    countajaxthread = countajaxthread + readyhtml.length;

    for(var zipnumber = 0; zipnumber < readyhtml.length ; zipnumber++) {
        initzipnumber(zipnumber+ pushnumber);
        var galleryid = readyhtml[zipnumber].split("/");

        if(galleryid[0] == "e-hentai.org" || galleryid[0] == "exhentai.org") {
            if(galleryid[1] == "g") {
                linkid = galleryid[galleryid.length-3];
            }
            else if(galleryid == "s") {
                linkid = galleryid[galleryid.length-1].split("-")[0];
            }
        }
        else if(galleryid[0] == "hitomi.la"){
            linkid = galleryid[galleryid.length-1].split(".")[0];
        }

        setzipnumber(linkid , zipnumber+ pushnumber , 1 );
        setzipnumber(linkid , zipnumber+ pushnumber , 2 );
        setzipnumber(readyhtml[zipnumber] , zipnumber+ pushnumber , 3 );

        download_request(zipnumber+ pushnumber);
        download_gallery(zipnumber+ pushnumber);

    }
}

function  initzipnumber(zipnumber) {
    zip[zipnumber] = [];
    zip[zipnumber][0] = new JSZip();
    zip[zipnumber][1] = "";//gallery number
    zip[zipnumber][2] = "";//file name
    zip[zipnumber][3] = ""//save original url info.
    zip[zipnumber][4] = [];//imageURL list
    zip[zipnumber][5] = [];//js liat
    zip[zipnumber][6] = 0;//count finish download
}

function setzipnumber( data, zipnumber , number ,arraynumber){
    if(Array.isArray(zip[zipnumber][number]) && !(arraynumber === undefined)){
        zip[zipnumber][number][arraynumber] = data;
    }
    else//maybe danger
    {
        zip[zipnumber][number] = data;
    }
}

function isworking()
{
    var zipnumber = -1;
    if(onworking == ""){
        for(i = zip.length -1 ; i > -1 ; i --) {
            if(zip[i][6] == 0){
                zipnumber = i;
            }
        }
        onworking = "working now";
        if(zipnumber != -1){
            getimagedata(zipnumber);
        }
        else{
            printwithTime("add more download------------");
            getimagedata(zipnumber);
        }
    }
}

function getimagedata(zipnumber) {
    if(zipnumber < zip.length) {
        for(var i = 0 ; (i < subDomainList.length * callPerServer) && (i < zip[zipnumber][4].length) ; i ++){
            download_next_image(i , zipnumber);
        }
    }
    else{
        onworking = "";
        printwithTime("finish--------");
    }
}

function download_request(zipnumber) {
    var galleryid = zip[zipnumber][3].split("/");

    hitomicall(zipnumber);
}

function hitomicall(zipnumber)
{
        $.ajax({
            url: 'http://localhost:443/https://hitomi.la/galleries/' + zip[zipnumber][1] + '.html',
            //async:false,
            success: function (data) {
                var text1 = textsplit(data , "-gallery" , "gallery-info");

                var datatext = textsplit(text1 , "h1>" , "</h1");
                datatext = textsplit(datatext , ".html\">" , "</a");

                var creatertext = textsplit(text1 , "h2>" , "</h2");
                creatertext = textsplit(creatertext , ".html\">" , "</a");

                if(datatext == ""){
                    datatext = galleryid[galleryid.length - 1];
                }

                if(creatertext == ""){
                    creatertext = "N_A";
                }

                setzipnumber(creatertext + "__" + datatext , zipnumber , 2 );
                setzipnumber("" , zipnumber , 3);

                if(endajax()){
                    isworking();
                }
            },
            error: function() {
                setzipnumber("" , zipnumber , 3 );
                if(endajax()) {
                    isworking();
                }
            }
        });
}

function textsplit(data , sp1 , sp2)
{
    if(data.indexOf(sp1) != -1 && data.indexOf(sp2) != -1){
        var text = data.split(sp1)[1].split(sp2)[0];
        return text;
    }
    else{
        return "";
    }

}

    function download_gallery(zipnumber) {
        $.ajax({
            url: 'http://localhost:443/https://hitomi.la/galleries/'+ zip[zipnumber][1] +'.js',
            //async:false,
            success: function() {
                $.each(galleryinfo, function(i, image) {
                    setzipnumber( url_from_url(zip[zipnumber][1] + "/" +image.name , i) , zipnumber , 4 ,zip[zipnumber][4].length);
                    setzipnumber( image.name , zipnumber , 5 ,zip[zipnumber][5].length);
                });

                if(endajax()) {
                    isworking();
                }
            },
            error: function() {}
        });
    }

    function subdomain_from_url(i) {
        var retval = subDomainList[i%subDomainList.length];
        return retval;
    }
    function url_from_url(url , i) {
        return "http://localhost:443/https://" + subdomain_from_url(i) + ".hitomi.la/galleries/"+ url;
    }

    function download_next_image(index , zipnumber) {
                ajax_download_blob(index, zipnumber , 0);
    }

    function ajax_download_blob(index, zipnumber , count) {
        var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = function() {
            if (this.readyState == 4) {
                if( this.status == 200 || this.status == 304) {
                    image_downloaded(this.response , index, zipnumber);
                }

                else {
                    if(count < 10) {
                        ajax_download_blob(index, zipnumber, count + 1);
                    }
                    else {
                        alert("error on picture number" + index +"-- error " + this.status);
                        //need whar file
                    }
                }
            }
        }

        xhr.open('GET', zip[zipnumber][4][index]);
        xhr.responseType = 'arraybuffer';
        xhr.send();
    }

    function image_downloaded(imgData , index, zipnumber) {
        zip[zipnumber][0].file(zip[zipnumber][5][index], imgData, {base64: true});
        setzipnumber(zip[zipnumber][6] + 1 , zipnumber , 6 );
        //if big maybe wrong
        if (zip[zipnumber][6] >= zip[zipnumber][4].length) {
            var content = zip[zipnumber][0].generateAsync({type:"blob"})
                .then(function (blob) {
                    saveAs(blob, zip[zipnumber][2]+".zip")
                        .then(freecontent(blob , zipnumber) , thenerror())
            }  , thenerror());

            printwithTime(zip[zipnumber][2]+".zip");
            getimagedata(zipnumber+1);
        }
        else if (index + subDomainList.length * callPerServer < zip[zipnumber][4].length){
            download_next_image(index + subDomainList.length * callPerServer , zipnumber);
        }
    }

    function thenerror(){}

    function freecontent(blob , zipnumber){
        setzipnumber("" , zipnumber , 0 );
        setzipnumber("" , zipnumber , 4 );
        setzipnumber("" , zipnumber , 5 );
    }

    function printwithTime(str) {
        $('#finished_list').val( new Date().toLocaleTimeString() + ":\n " + str + "\n\n" + $('#finished_list').val());
    }

<|endoftext|>


<commit_before>
    function log(s) {
        Array.prototype.forEach.call(arguments, function(s) {
           $('#console').text($('#console').text() + "\n" + s)
        })
        $('#console').scrollTop($('#console')[0].scrollHeight);
    }

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('https://livelykernel.github.io/lively4-core/serviceworker-loader.js', {
        scope: "https://livelykernel.github.io/lively4-core/draft/"
    }).then(function(registration) {
        // Registration was successful
        log('ServiceWorker registration successful with scope: ', registration.scope);
    }).catch(function(err) {
        // registration failed
        log('ServiceWorker registration failed: ', err);
    });

    navigator.serviceWorker.ready.then(function(registration) {
            log('READY');
            System.import("file-editor.js").then(function(module) {
                window.fileEditor = module
                log("fileEditor loaded")
            })
            // #TODO continue here... loadFile is not in global scope (yet)
    })

document.addEventListener('DOMContentLoaded', function () {
  if (Notification.permission !== "granted")
    Notification.requestPermission();
});

<commit_msg>SYNC  M draft/load.js;<commit_after>
    function log(s) {
        Array.prototype.forEach.call(arguments, function(s) {
           $('#console').text($('#console').text() + "\n" + s)
        })
        $('#console').scrollTop($('#console')[0].scrollHeight);
    }

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('https://livelykernel.github.io/lively4-core/serviceworker-loader.js', {
        scope: "https://livelykernel.github.io/lively4-core/draft/"
    }).then(function(registration) {
        // Registration was successful
        log('ServiceWorker registration successful with scope: ', registration.scope);
    }).catch(function(err) {
        // registration failed
        log('ServiceWorker registration failed: ', err);
    });

    navigator.serviceWorker.ready.then(function(registration) {
            log('READY');
            System.import("file-editor.js").then(function(module) {
                window.fileEditor = module
                log("fileEditor loaded")
            })
            // #TODO continue here... loadFile is not in global scope (yet)
    })
}

document.addEventListener('DOMContentLoaded', function () {
  if (Notification.permission !== "granted")
    Notification.requestPermission();
});

<|endoftext|>


<commit_before>//export { Same, Bool, Int } from "./ValueDesc/ValueDesc_Base.js";
export { channelCount1_pointwise1Before };
export { Pointwise_HigherHalfDifferent };
export { AvgMax_Or_ChannelMultiplier };
//export { ActivationFunction } from "./ValueDesc/ValueDesc_ActivationFunction.js";
export { WhetherShuffleChannel };

import { Int } from "./ValueDesc_Base.js";

/** Describe id, range, name of channelCount1_pointwise1Before.
 *
 * Convert number value into integer between [ -5, ( 10 * 1024 ) ] representing operation:
 *   - -5: ONE_INPUT_HALF_THROUGH
 *   - -4: ONE_INPUT_HALF_THROUGH_EXCEPT_DEPTHWISE1
 *   - -3: TWO_INPUTS_CONCAT_POINTWISE21_INPUT1
 *   - -2: ONE_INPUT_TWO_DEPTHWISE
 *   - -1: ONE_INPUT_ADD_TO_OUTPUT
 *   -  0: ONE_INPUT
 *   - [ 1, ( 10 * 1024 ) ]: TWO_INPUTS with the second input channel count between 1 and 10240 (inclusive). (without names defined.)
 */
class channelCount1_pointwise1Before extends Int {

  constructor() {
    super( -5, ( 10 * 1024 ), [
      "ONE_INPUT_HALF_THROUGH",                   // (-5) ShuffleNetV2_ByMobileNetV1's body/tail
      "ONE_INPUT_HALF_THROUGH_EXCEPT_DEPTHWISE1", // (-4) ShuffleNetV2_ByMobileNetV1's head
      "TWO_INPUTS_CONCAT_POINTWISE21_INPUT1",     // (-3) ShuffleNetV2's body/tail
      "ONE_INPUT_TWO_DEPTHWISE",                  // (-2) ShuffleNetV2's head (or ShuffleNetV2_ByPointwise22's head) (simplified)
      "ONE_INPUT_ADD_TO_OUTPUT",                  // (-1) MobileNetV2
      "ONE_INPUT",                                // ( 0) MobileNetV1 (General Pointwise1-Depthwise1-Pointwise2)

      // "TWO_INPUTS_1", "TWO_INPUTS_2", ..., "TWO_INPUTS_10240".
      //
      // ShuffleNetV2_ByPointwise22's body/tail
      //
      // (2021/07/13 Remarked) Do not define these names because they will occupy too many memory.
      //
      //... [ ... new Array( 10 * 1024 ).keys() ].map( x => "TWO_INPUTS_" + ( x + 1 ) )
    ] );
  }

}

/** The only one ValueDesc.channelCount1_pointwise1Before instance. */
channelCount1_pointwise1Before.Singleton = new channelCount1_pointwise1Before;

/** Describe id, range, name of the processing mode of pointwise convolution's higher half channels.
 *
 * Convert number value into integer between [ 0, 4 ] representing:
 *   - 0: NONE
 *   - 1: HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH
 *   - 2: HIGHER_HALF_COPY_LOWER_HALF
 *   - 3: HIGHER_HALF_POINTWISE22
 *   - 4: HIGHER_HALF_PASS_THROUGH
 */
class Pointwise_HigherHalfDifferent extends Int {

  constructor() {
    super( 0, 4, [
      "NONE",                                                 // (0) (for normal poitwise convolution. no higher half different.)
      "HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH", // (1) (for pointwise1 of ShuffleNetV2_ByMopbileNetV1's head)
      "HIGHER_HALF_COPY_LOWER_HALF",                          // (2) (for pointwise1 of ShuffleNetV2_ByMopbileNetV1's head)
      "HIGHER_HALF_POINTWISE22",                              // (3) (for pointwise2 of ShuffleNetV2_ByMopbileNetV1's head)
      "HIGHER_HALF_PASS_THROUGH",                             // (4) (for pointwise1/pointwise2 of ShuffleNetV2_ByMopbileNetV1's body/tail)
    ] );
  }

}

/** The only one ValueDesc.Pointwise_HigherHalfDifferent instance. */
Pointwise_HigherHalfDifferent.Singleton = new Pointwise_HigherHalfDifferent;

/** Describe depthwise operation's id, range, name.
 *
 * Convert number value into integer between [ -2, 32 ] representing depthwise operation:
 *   - -2: average pooling. (AVG)
 *   - -1: maximum pooling. (MAX)
 *   -  0: no depthwise operation. (NONE)
 *   - [ 1, 32 ]: depthwise convolution with channel multiplier between 1 and 32 (inclusive).
 */
class AvgMax_Or_ChannelMultiplier extends Int {

  constructor() {
    super( -2, 32, [ "AVG", "MAX", "NONE" ] );
  }

}

/** The only one ValueDesc.AvgMax_Or_ChannelMultiplier instance. */
AvgMax_Or_ChannelMultiplier.Singleton = new AvgMax_Or_ChannelMultiplier;

/** Describe id, range, name of WhetherShuffleChannel.
 *
 * Convert number value into integer between [ 0, 3 ] representing operation:
 *   - 0: NONE (i.e. NotShuffleNet_NotMobileNet, or MobileNetV2)
 *   - 1: BY_POINTWISE22      (i.e. ShuffleNetV2_ByPointwise22)
 *   - 2: BY_CHANNEL_SHUFFLER (i.e. ShuffleNetV2)
     - 3: BY_MOBILE_NET_V1    (i.e. ShuffleNetV2_ByMobileNetV1)
 */
class WhetherShuffleChannel extends Int {

  constructor() {
    super( 0, 2, [
      "NONE",                // (0)
      "BY_CHANNEL_SHUFFLER", // (1)
      "BY_POINTWISE22",      // (2)
      "BY_MOBILE_NET_V1",    // (3)
    ] );
  }

}

/** The only one ValueDesc.WhetherShuffleChannel instance. */
WhetherShuffleChannel.Singleton = new WhetherShuffleChannel;

<commit_msg>Update ValueDesc_Other.js<commit_after>export { channelCount1_pointwise1Before };
export { Pointwise_HigherHalfDifferent };
export { AvgMax_Or_ChannelMultiplier };
export { WhetherShuffleChannel };

import { Int } from "./ValueDesc_Base.js";

/** Describe id, range, name of channelCount1_pointwise1Before.
 *
 * Convert number value into integer between [ -5, ( 10 * 1024 ) ] representing operation:
 *   - -5: ONE_INPUT_HALF_THROUGH
 *   - -4: ONE_INPUT_HALF_THROUGH_EXCEPT_DEPTHWISE1
 *   - -3: TWO_INPUTS_CONCAT_POINTWISE21_INPUT1
 *   - -2: ONE_INPUT_TWO_DEPTHWISE
 *   - -1: ONE_INPUT_ADD_TO_OUTPUT
 *   -  0: ONE_INPUT
 *   - [ 1, ( 10 * 1024 ) ]: TWO_INPUTS with the second input channel count between 1 and 10240 (inclusive). (without names defined.)
 */
class channelCount1_pointwise1Before extends Int {

  constructor() {
    super( -5, ( 10 * 1024 ), [
      "ONE_INPUT_HALF_THROUGH",                   // (-5) ShuffleNetV2_ByMobileNetV1's body/tail
      "ONE_INPUT_HALF_THROUGH_EXCEPT_DEPTHWISE1", // (-4) ShuffleNetV2_ByMobileNetV1's head
      "TWO_INPUTS_CONCAT_POINTWISE21_INPUT1",     // (-3) ShuffleNetV2's body/tail
      "ONE_INPUT_TWO_DEPTHWISE",                  // (-2) ShuffleNetV2's head (or ShuffleNetV2_ByPointwise22's head) (simplified)
      "ONE_INPUT_ADD_TO_OUTPUT",                  // (-1) MobileNetV2
      "ONE_INPUT",                                // ( 0) MobileNetV1 (General Pointwise1-Depthwise1-Pointwise2)

      // "TWO_INPUTS_1", "TWO_INPUTS_2", ..., "TWO_INPUTS_10240".
      //
      // ShuffleNetV2_ByPointwise22's body/tail
      //
      // (2021/07/13 Remarked) Do not define these names because they will occupy too many memory.
      //
      //... [ ... new Array( 10 * 1024 ).keys() ].map( x => "TWO_INPUTS_" + ( x + 1 ) )
    ] );
  }

}

/** The only one ValueDesc.channelCount1_pointwise1Before instance. */
channelCount1_pointwise1Before.Singleton = new channelCount1_pointwise1Before;

/** Describe id, range, name of the processing mode of pointwise convolution's higher half channels.
 *
 * Convert number value into integer between [ 0, 4 ] representing:
 *   - 0: NONE
 *   - 1: HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH
 *   - 2: HIGHER_HALF_COPY_LOWER_HALF
 *   - 3: HIGHER_HALF_POINTWISE22
 *   - 4: HIGHER_HALF_PASS_THROUGH
 */
class Pointwise_HigherHalfDifferent extends Int {

  constructor() {
    super( 0, 4, [
      "NONE",                                                 // (0) (for normal poitwise convolution. no higher half different.)
      "HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH", // (1) (for pointwise1 of ShuffleNetV2_ByMopbileNetV1's head)
      "HIGHER_HALF_COPY_LOWER_HALF",                          // (2) (for pointwise1 of ShuffleNetV2_ByMopbileNetV1's head)
      "HIGHER_HALF_POINTWISE22",                              // (3) (for pointwise2 of ShuffleNetV2_ByMopbileNetV1's head)
      "HIGHER_HALF_PASS_THROUGH",                             // (4) (for pointwise1/pointwise2 of ShuffleNetV2_ByMopbileNetV1's body/tail)
    ] );
  }

}

/** The only one ValueDesc.Pointwise_HigherHalfDifferent instance. */
Pointwise_HigherHalfDifferent.Singleton = new Pointwise_HigherHalfDifferent;

/** Describe depthwise operation's id, range, name.
 *
 * Convert number value into integer between [ -2, 32 ] representing depthwise operation:
 *   - -2: average pooling. (AVG)
 *   - -1: maximum pooling. (MAX)
 *   -  0: no depthwise operation. (NONE)
 *   - [ 1, 32 ]: depthwise convolution with channel multiplier between 1 and 32 (inclusive).
 */
class AvgMax_Or_ChannelMultiplier extends Int {

  constructor() {
    super( -2, 32, [ "AVG", "MAX", "NONE" ] );
  }

}

/** The only one ValueDesc.AvgMax_Or_ChannelMultiplier instance. */
AvgMax_Or_ChannelMultiplier.Singleton = new AvgMax_Or_ChannelMultiplier;

/** Describe id, range, name of WhetherShuffleChannel.
 *
 * Convert number value into integer between [ 0, 3 ] representing operation:
 *   - 0: NONE (i.e. NotShuffleNet_NotMobileNet, or MobileNetV2)
 *   - 1: BY_POINTWISE22      (i.e. ShuffleNetV2_ByPointwise22)
 *   - 2: BY_CHANNEL_SHUFFLER (i.e. ShuffleNetV2)
     - 3: BY_MOBILE_NET_V1    (i.e. ShuffleNetV2_ByMobileNetV1)
 */
class WhetherShuffleChannel extends Int {

  constructor() {
    super( 0, 2, [
      "NONE",                // (0)
      "BY_CHANNEL_SHUFFLER", // (1)
      "BY_POINTWISE22",      // (2)
      "BY_MOBILE_NET_V1",    // (3)
    ] );
  }

}

/** The only one ValueDesc.WhetherShuffleChannel instance. */
WhetherShuffleChannel.Singleton = new WhetherShuffleChannel;

<|endoftext|>


<commit_before>import * as HeightWidthDepth from "./HeightWidthDepth.js";
import * as PartTime from "../PartTime.js";
import * as ValueMax from "../ValueMax.js";
//import * as TensorTools from "../util/TensorTools.js";

/**
 * Test different resize implementation for CNN.
 *
 * @see {@link https://jsperf.com/colorfulcakechen-cnn-height-width-resize}
 * @see {@link https://colorfulcakechen.github.io/query-submit-canvas/CNN/jsPerf/TestFilters2D.html}
 */

let testCase_Height = 101;
let testCase_Width = 101;
let testCase_Depth = 24;

//globalThis.testSet_101x101x24 = new HeightWidthDepth.Base( 101, 101, 24 ); // height, width, depth

/** Aggregate all progress about WebGL an CPU.  */
class Progress extends ValueMax.Percentage.Aggregate {
  constructor() {
    let children = [
      new ValueMax.Percentage.Concrete(), // Increased when executing by WebGL.
//      new ValueMax.Percentage.Concrete(), // Increased when executing by WASM.
      new ValueMax.Percentage.Concrete(), // Increased when executing by CPU.
    ];

    super(children);
//    [ this.WebGL, this.WASM, this.CPU ] = children;
    [ this.WebGL, this.CPU ] = children;
  }
}

/** Profile test case.  */
globalThis.testCaseLoader = async function () {

  let progress = new Progress();
  let progressReceiver = new ValueMax.Receiver.HTMLProgress.createByTitle_or_getDummy("TestProgressBar");

  let resultProfilesWebGL;
  {
    await tf.setBackend("webgl");  // WebGL seems crashed jsPerf.
    console.log("library WebGL ready.");

    console.log("library WebGL compiling...");  // For pre-compile tensorflow.js GPU codes. (and Test correctness.)

    globalThis.testCase = new HeightWidthDepth.Base(
      testCase_Height, testCase_Width, testCase_Depth, progress, progress.WebGL, progressReceiver );

    resultProfilesWebGL = await globalThis.testCase.generateProfiles();
    globalThis.testCase.disposeTensors();
    console.log("library WebGL compiling done.");
  }

  let resultProfilesWASM;
//!!! ...unfinished... Wait until tensorflow WASM mature.
//   {
//     await tf.setBackend("wasm")  // WASM seems no ResizeNearestNeighbor.
//     console.log("library WASM ready.");
//
//     console.log("library WASM compiling...");  // For pre-compile tensorflow.js WASM codes. (and Test correctness.)
//
//     globalThis.testCase = new HeightWidthDepth.Base(
//       testCase_Height, testCase_Width, testCase_Depth, progress, progress.WASM, progressReceiver );
//
//     resultProfilesWASM = await globalThis.testCase.generateProfiles();
//     globalThis.testCase.disposeTensors();
//     console.log("library WASM compiling done.");
//   }

  let resultProfilesCPU;
  {
    await tf.setBackend("cpu");
    //await tf.ready();
    console.log("library CPU ready.");

    console.log("library CPU compiling...");  // For pre-compile tensorflow.js CPU codes. (and Test correctness.)

    globalThis.testCase = new HeightWidthDepth.Base(
      testCase_Height, testCase_Width, testCase_Depth, progress, progress.CPU, progressReceiver );

    resultProfilesCPU = await globalThis.testCase.generateProfiles();
    // DO NOT dispose it so that jsPerf can use it.
    //globalThis.testCase.disposeTensors();
    console.log("library CPU compiling done.");
  }

  // Display to web page.
  publishProfiles( "profilesHTMLTable", resultProfilesWebGL, resultProfilesWASM, resultProfilesCPU );
}

/**
 * Publish the profiles to HTML table.
 *
 * @param {string}   strResultHTMLTableName  the HTML table name for display execution time.
 * @param {Object[]} profilesWebGL           the array of profiles for execution time of WebGL.
 * @param {Object[]} profilesWASM            the array of profiles for execution time of WASM.
 * @param {Object[]} profilesCPU             the array of profiles for execution time of CPU.
 */
function publishProfiles( strResultHTMLTableName, profilesWebGL, profilesWASM, profilesCPU ) {

  if ( !document )
    return;

  if ( !strResultHTMLTableName )
    return;

  let htmlTable = document.getElementById( strResultHTMLTableName );
  if ( !htmlTable )
    return;

  /**
   * @param {HTMLNode}         htmlNode The HTML table (or thead, or tbody) as display target.
   * @param {string}            th_OR_td  "th" for table header, "td" for table body.
   * @param {string[]|number[]} dataArray The data to be displaye
   */
  function addOneLineCells( htmlNode, th_OR_td, dataArray ) {
    let cellElementName;
    let oneLine = document.createElement( "tr" );

    let count = dataArray.length;
    for ( let i = 0; i < count; ++i ) {
      let data = dataArray[ i ];

      if ( 0 == i )
        cellElementName = "th"; // First column always use
      else
        cellElementName = th_OR_td;

      let oneCell = document.createElement( cellElementName );
      oneCell.appendChild( document.createTextNode( data ) )
      oneLine.appendChild( oneCell );
    }
    htmlNode.appendChild( oneLine );
  }

  let thead = document.createElement( "thead" );
  let tbody = document.createElement( "tbody" );

  htmlTable.appendChild( thead );
  htmlTable.appendChild( tbody );

  // Table header (top line).
  addOneLineCells( thead, "th", [
    "TestName",
    "backend", "kernelMs", "wallMs",
//    "backend", "kernelMs", "wallMs",
    "backend", "kernelMs", "wallMs",
    "newBytes", "newTensors", "peakBytes" ] );

  let digitsCount = 4;

  let profileCount = profilesWebGL.length;
  for ( let i = 0; i < profileCount; ++i ) {

    let profileWebGL = profilesWebGL[ i ];
//    let profileWASM = profilesWASM[ i ];
    let profileCPU = profilesCPU[ i ];

    addOneLineCells( tbody, "td", [
      profileWebGL.title,
      profileWebGL.backendName, profileWebGL.kernelMs.toFixed( digitsCount ), profileWebGL.wallMs.toFixed( digitsCount ),
//      profileWASM.backendName, profileWASM.kernelMs.toFixed( digitsCount ), profileWASM.wallMs.toFixed( digitsCount ),
      profileCPU.backendName, profileCPU.kernelMs.toFixed( digitsCount ), profileCPU.wallMs.toFixed( digitsCount ),
      profileWebGL.newBytes, profileWebGL.newTensors, profileWebGL.peakBytes ] );
  }

}
<commit_msg>Update jsPerf_CNNHeightWidthResize.js<commit_after>import * as HeightWidthDepth from "./HeightWidthDepth.js";
import * as PartTime from "../PartTime.js";
import * as ValueMax from "../ValueMax.js";
//import * as TensorTools from "../util/TensorTools.js";

/**
 * Test different resize implementation for CNN.
 *
 * @see {@link https://jsperf.com/colorfulcakechen-cnn-height-width-resize}
 * @see {@link https://colorfulcakechen.github.io/query-submit-canvas/CNN/jsPerf/TestFilters2D.html}
 */

let testCase_Height = 101;
let testCase_Width = 101;
let testCase_Depth = 24;

//globalThis.testSet_101x101x24 = new HeightWidthDepth.Base( 101, 101, 24 ); // height, width, depth

/** Aggregate all progress about WebGL an CPU.  */
class Progress extends ValueMax.Percentage.Aggregate {
  constructor() {
    let children = [
      new ValueMax.Percentage.Concrete(), // Increased when executing by WebGL.
//      new ValueMax.Percentage.Concrete(), // Increased when executing by WASM.
      new ValueMax.Percentage.Concrete(), // Increased when executing by CPU.
    ];

    super(children);
//    [ this.WebGL, this.WASM, this.CPU ] = children;
    [ this.WebGL, this.CPU ] = children;
  }
}

/** Profile test case.  */
globalThis.testCaseLoader = async function () {

  let progress = new Progress();
  let progressReceiver = new ValueMax.Receiver.HTMLProgress.createByTitle_or_getDummy("TestProgressBar");

  let resultProfilesWebGL;
  {
    await tf.setBackend("webgl");  // WebGL seems crashed jsPerf.
    console.log("library WebGL ready.");

    console.log("library WebGL compiling...");  // For pre-compile tensorflow.js GPU codes. (and Test correctness.)

    globalThis.testCase = new HeightWidthDepth.Base(
      testCase_Height, testCase_Width, testCase_Depth, progress, progress.WebGL, progressReceiver );

    resultProfilesWebGL = await globalThis.testCase.generateProfiles();
    globalThis.testCase.disposeTensors();
    console.log("library WebGL compiling done.");
  }

  let resultProfilesWASM;
//!!! ...unfinished... Wait until tensorflow WASM mature.
//   {
//     await tf.setBackend("wasm")  // WASM seems no ResizeNearestNeighbor.
//     console.log("library WASM ready.");
//
//     console.log("library WASM compiling...");  // For pre-compile tensorflow.js WASM codes. (and Test correctness.)
//
//     globalThis.testCase = new HeightWidthDepth.Base(
//       testCase_Height, testCase_Width, testCase_Depth, progress, progress.WASM, progressReceiver );
//
//     resultProfilesWASM = await globalThis.testCase.generateProfiles();
//     globalThis.testCase.disposeTensors();
//     console.log("library WASM compiling done.");
//   }

  let resultProfilesCPU;
  {
    await tf.setBackend("cpu");
    //await tf.ready();
    console.log("library CPU ready.");

    console.log("library CPU compiling...");  // For pre-compile tensorflow.js CPU codes. (and Test correctness.)

    globalThis.testCase = new HeightWidthDepth.Base(
      testCase_Height, testCase_Width, testCase_Depth, progress, progress.CPU, progressReceiver );

    resultProfilesCPU = await globalThis.testCase.generateProfiles();
    // DO NOT dispose it so that jsPerf can use it.
    //globalThis.testCase.disposeTensors();
    console.log("library CPU compiling done.");
  }

  // Display to web page.
  publishProfiles( "profilesHTMLTable", resultProfilesWebGL, resultProfilesWASM, resultProfilesCPU );
}

/**
 * Publish the profiles to HTML table.
 *
 * @param {string}   strResultHTMLTableName  the HTML table name for display execution time.
 * @param {Object[]} profilesWebGL           the array of profiles for execution time of WebGL.
 * @param {Object[]} profilesWASM            the array of profiles for execution time of WASM.
 * @param {Object[]} profilesCPU             the array of profiles for execution time of CPU.
 */
function publishProfiles( strResultHTMLTableName, profilesWebGL, profilesWASM, profilesCPU ) {

  if ( !document )
    return;

  if ( !strResultHTMLTableName )
    return;

  let htmlTable = document.getElementById( strResultHTMLTableName );
  if ( !htmlTable )
    return;

  /**
   * @param {HTMLNode}         htmlNode The HTML table (or thead, or tbody) as display target.
   * @param {string}            th_OR_td  "th" for table header, "td" for table body.
   * @param {string[]|number[]} dataArray The data to be displaye
   */
  function addOneLineCells( htmlNode, th_OR_td, dataArray ) {
    let cellElementName;
    let oneLine = document.createElement( "tr" );

    let count = dataArray.length;
    for ( let i = 0; i < count; ++i ) {
      let data = dataArray[ i ];

      if ( 0 == i )
        cellElementName = "th"; // First column always use
      else
        cellElementName = th_OR_td;

      let oneCell = document.createElement( cellElementName );
      oneCell.appendChild( document.createTextNode( data ) )
      oneLine.appendChild( oneCell );
    }
    htmlNode.appendChild( oneLine );
  }

  let thead = document.createElement( "thead" );
  let tbody = document.createElement( "tbody" );

  htmlTable.appendChild( thead );
  htmlTable.appendChild( tbody );

  // Table header (top line).
  addOneLineCells( thead, "th", [
    "TestName",
    `kernelMs (${profileWebGL.backendName})`, `kernelMs (${profileCPU.backendName})`,
    `wallMs (${profileWebGL.backendName})`, `wallMs (${profileCPU.backendName})`,

//     "backend", "kernelMs", "wallMs",
// //    "backend", "kernelMs", "wallMs",
//     "backend", "kernelMs", "wallMs",

    "newBytes", "newTensors", "peakBytes" ] );

  let digitsCount = 4;

  let profileCount = profilesWebGL.length;
  for ( let i = 0; i < profileCount; ++i ) {

    let profileWebGL = profilesWebGL[ i ];
//    let profileWASM = profilesWASM[ i ];
    let profileCPU = profilesCPU[ i ];

    addOneLineCells( tbody, "td", [
      profileWebGL.title,

      profileWebGL.kernelMs.toFixed( digitsCount ), profileCPU.kernelMs.toFixed( digitsCount ),
      profileWebGL.wallMs.toFixed( digitsCount ), profileCPU.wallMs.toFixed( digitsCount ),

//       profileWebGL.backendName, profileWebGL.kernelMs.toFixed( digitsCount ), profileWebGL.wallMs.toFixed( digitsCount ),
// //      profileWASM.backendName, profileWASM.kernelMs.toFixed( digitsCount ), profileWASM.wallMs.toFixed( digitsCount ),
//       profileCPU.backendName, profileCPU.kernelMs.toFixed( digitsCount ), profileCPU.wallMs.toFixed( digitsCount ),

      profileWebGL.newBytes, profileWebGL.newTensors, profileWebGL.peakBytes ] );
  }

}
<|endoftext|>