<commit_before>/**
 * Copyright 2018 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.
 */

import { resolve } from 'path';
import resolveModule from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import typescript from 'rollup-plugin-typescript2';
import uglify from 'rollup-plugin-uglify';
import pkg from './package.json';

import appPkg from './app/package.json';
import authPkg from './auth/package.json';
import databasePkg from './database/package.json';
import firestorePkg from './firestore/package.json';
import functionsPkg from './functions/package.json';
import messagingPkg from './messaging/package.json';
import storagePkg from './storage/package.json';

const pkgsByName = {
  app: appPkg,
  auth: authPkg,
  database: databasePkg,
  firestore: firestorePkg,
  functions: functionsPkg,
  messaging: messagingPkg,
  storage: storagePkg
};

const plugins = [
  resolveModule(),
  typescript({
    typescript: require('typescript')
  }),
  commonjs()
];

const external = Object.keys(pkg.dependencies || {});

/**
 * Global UMD Build
 */
const GLOBAL_NAME = 'firebase';

/**
 * Individual Component Builds
 */
const appBuilds = [
  /**
   * App Browser Builds
   */
  {
    input: 'app/index.ts',
    output: [
      { file: resolve('app', appPkg.main), format: 'cjs' },
      { file: resolve('app', appPkg.module), format: 'es' }
    ],
    plugins,
    external
  },
  /**
   * App UMD Builds
   */
  {
    input: 'app/index.ts',
    output: {
      file: 'firebase-app.js',
      sourcemap: true,
      format: 'umd',
      name: GLOBAL_NAME
    },
    plugins: [...plugins, uglify()]
  }
];

const components = [
  'auth',
  'database',
  'firestore',
  'functions',
  'messaging',
  'storage'
];
const componentBuilds = components
  .map(component => {
    const pkg = pkgsByName[component];
    return [
      {
        input: `${component}/index.ts`,
        output: [
          { file: resolve(component, pkg.main), format: 'cjs' },
          { file: resolve(component, pkg.module), format: 'es' }
        ],
        plugins,
        external
      },
      {
        input: `${component}/index.ts`,
        output: {
          file: `firebase-${component}.js`,
          format: 'iife',
          sourcemap: true,
          extend: true,
          name: GLOBAL_NAME,
          globals: {
            '@firebase/app': GLOBAL_NAME
          },
          intro: `try  {`,
          outro: `} catch(err) {
              console.error(err);
              throw new Error(
                'Cannot instantiate firebase-${component} - ' +
                'be sure to load firebase-app.js first.'
              );
            }`
        },
        plugins: [...plugins, uglify()],
        external: ['@firebase/app']
      }
    ];
  })
  .reduce((a, b) => a.concat(b), []);

/**
 * Complete Package Builds
 */
const completeBuilds = [
  /**
   * App Browser Builds
   */
  {
    input: 'src/index.ts',
    output: [
      { file: pkg.browser, format: 'cjs' },
      { file: pkg.module, format: 'es' }
    ],
    plugins,
    external
  },
  {
    input: 'src/index.cdn.ts',
    output: {
      file: 'firebase.js',
      format: 'umd',
      name: GLOBAL_NAME
    },
    plugins: [...plugins, uglify()]
  },
  /**
   * App Node.js Builds
   */
  {
    input: 'src/index.node.ts',
    output: { file: pkg.main, format: 'cjs' },
    plugins,
    external
  },
  /**
   * App React Native Builds
   */
  {
    input: 'src/index.rn.ts',
    output: { file: pkg['react-native'], format: 'cjs' },
    plugins,
    external
  }
];

export default [...appBuilds, ...componentBuilds, ...completeBuilds];
<commit_msg>wrap component with try catch outside of iife for old browser compatibility (#1239)<commit_after>/**
 * Copyright 2018 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.
 */

import { resolve } from 'path';
import resolveModule from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import typescript from 'rollup-plugin-typescript2';
import uglify from 'rollup-plugin-uglify';
import pkg from './package.json';

import appPkg from './app/package.json';
import authPkg from './auth/package.json';
import databasePkg from './database/package.json';
import firestorePkg from './firestore/package.json';
import functionsPkg from './functions/package.json';
import messagingPkg from './messaging/package.json';
import storagePkg from './storage/package.json';

const pkgsByName = {
  app: appPkg,
  auth: authPkg,
  database: databasePkg,
  firestore: firestorePkg,
  functions: functionsPkg,
  messaging: messagingPkg,
  storage: storagePkg
};

const plugins = [
  resolveModule(),
  typescript({
    typescript: require('typescript')
  }),
  commonjs()
];

const external = Object.keys(pkg.dependencies || {});

/**
 * Global UMD Build
 */
const GLOBAL_NAME = 'firebase';

/**
 * Individual Component Builds
 */
const appBuilds = [
  /**
   * App Browser Builds
   */
  {
    input: 'app/index.ts',
    output: [
      { file: resolve('app', appPkg.main), format: 'cjs' },
      { file: resolve('app', appPkg.module), format: 'es' }
    ],
    plugins,
    external
  },
  /**
   * App UMD Builds
   */
  {
    input: 'app/index.ts',
    output: {
      file: 'firebase-app.js',
      sourcemap: true,
      format: 'umd',
      name: GLOBAL_NAME
    },
    plugins: [...plugins, uglify()]
  }
];

const components = [
  'auth',
  'database',
  'firestore',
  'functions',
  'messaging',
  'storage'
];
const componentBuilds = components
  .map(component => {
    const pkg = pkgsByName[component];
    return [
      {
        input: `${component}/index.ts`,
        output: [
          { file: resolve(component, pkg.main), format: 'cjs' },
          { file: resolve(component, pkg.module), format: 'es' }
        ],
        plugins,
        external
      },
      {
        input: `${component}/index.ts`,
        output: {
          file: `firebase-${component}.js`,
          format: 'iife',
          sourcemap: true,
          extend: true,
          name: GLOBAL_NAME,
          globals: {
            '@firebase/app': GLOBAL_NAME
          },
          banner: `try  {`,
          footer: `} catch(err) {
              console.error(err);
              throw new Error(
                'Cannot instantiate firebase-${component} - ' +
                'be sure to load firebase-app.js first.'
              );
            }`
        },
        plugins: [...plugins, uglify()],
        external: ['@firebase/app']
      }
    ];
  })
  .reduce((a, b) => a.concat(b), []);

/**
 * Complete Package Builds
 */
const completeBuilds = [
  /**
   * App Browser Builds
   */
  {
    input: 'src/index.ts',
    output: [
      { file: pkg.browser, format: 'cjs' },
      { file: pkg.module, format: 'es' }
    ],
    plugins,
    external
  },
  {
    input: 'src/index.cdn.ts',
    output: {
      file: 'firebase.js',
      format: 'umd',
      name: GLOBAL_NAME
    },
    plugins: [...plugins, uglify()]
  },
  /**
   * App Node.js Builds
   */
  {
    input: 'src/index.node.ts',
    output: { file: pkg.main, format: 'cjs' },
    plugins,
    external
  },
  /**
   * App React Native Builds
   */
  {
    input: 'src/index.rn.ts',
    output: { file: pkg['react-native'], format: 'cjs' },
    plugins,
    external
  }
];

export default [...appBuilds, ...componentBuilds, ...completeBuilds];
<|endoftext|>


<commit_before>import path from 'path';
import fs from 'fs';
import core from 'babel-runtime/core-js';
const { lpad } = core.String.prototype;
import { promisify, promisifyAll, fromNode as promiseFromNode } from 'bluebird';
import nunjucks from 'nunjucks';
import permalinks from 'permalinks';
import MkMeta from 'marked-metadata';
import mkdirp from 'mkdirp';
import { ncp } from 'ncp';
import rimraf from 'rimraf';
import stylus from 'stylus';
import less from 'less';
import { rootdir, postspath, pagespath } from './config';
import { cliColor, getConfig, getFileName, getStructure } from './helpers';
import Theme from './theme';
promisifyAll(fs);
const mkdirpAsync = promisify(mkdirp);
const ncpAsync = promisify(ncp);
const rimrafAsync = promisify(rimraf);

const clc = cliColor();
const rMarkdownExt = /\.(?:md|markdown)$/;

const Helper = {

    sort(a, b) {
        return new Date(b.date) - new Date(a.date);
    },

    sortPosts(posts) {
        Object.values(posts).forEach((postsArray) => postsArray.sort(Helper.sort));
        return posts;
    },

    normalizeMetaData(data, defaults) {
        data.categories = (data.categories || '').split(',').map((category) => category.trim());

        if (data.date) {
            data.date = new Date(data.date);
        }

        data.layout = data.layout || defaults.layout;

        // FIXME why is this here? The template should do the escaping, not `normalizeMetaData`
        data.title = data.title.replace(/\"/g, '');

        return data;
    }
};

export default class Harmonic {
    /*eslint-disable camelcase*/

    constructor(sitePath, { quiet = true } = {}) {
        this.sitePath = path.resolve(sitePath);
        this.quiet = !!quiet;

        const config = Object.assign({
            index_posts: 10
        }, getConfig(this.sitePath));
        this.theme = new Theme(config.theme, this.sitePath);

        if (fs.existsSync(path.join(this.theme.themePath, 'config.json'))) {
            Object.assign(config, JSON.parse(this.theme.getFileContents('config.json')));
        }

        this.config = config;
        this.nunjucksEnv = nunjucks.configure(this.theme.themePath, { watch: false });
        this.templates = {};
    }

    async clean() {
        console.log(clc.warn('Cleaning up...'));
        await rimrafAsync(path.join(this.sitePath, 'public'), { maxBusyTries: 20 });
    }

    async compileCSS() {
        const currentCSSCompiler = this.config.preprocessor;
        if (!currentCSSCompiler) {
            return;
        }

        const compiler = {

            less: async () => {
                const lessIndexPath = path.join(this.theme.themePath, 'resources/_less/index.less');
                const cssDir = path.join(this.sitePath, 'public/css');

                const lessInput = await fs.readFileAsync(lessIndexPath, { encoding: 'utf8' });
                const { css } = await less.render(lessInput, { filename: lessIndexPath });

                await mkdirpAsync(cssDir);
                await fs.writeFileAsync(path.join(cssDir, 'main.css'), css);

                console.log(clc.info('Successfully generated CSS with LESS preprocessor'));
            },

            stylus: async () => {
                const stylDir = path.join(this.theme.themePath, 'resources/_stylus');
                const stylIndexPath = path.join(stylDir, 'index.styl');
                const cssDir = path.join(this.sitePath, 'public/css');

                const stylInput = await fs.readFileAsync(stylIndexPath, { encoding: 'utf8' });
                const css = await promiseFromNode((cb) => {
                    stylus(stylInput)
                        .set('filename', stylIndexPath)
                        .set('paths', [path.join(stylDir, 'engine'), path.join(stylDir, 'partials')])
                        .render(cb);
                });

                await mkdirpAsync(cssDir);
                await fs.writeFileAsync(path.join(cssDir, 'main.css'), css);

                console.log(clc.info('Successfully generated CSS with Stylus preprocessor'));
            }
        };

        if (!compiler.hasOwnProperty(currentCSSCompiler)) {
            throw new Error(`Unsupported CSS preprocessor: ${currentCSSCompiler}`);
        }

        await compiler[currentCSSCompiler]();
    }

    async compileJS(postsMetadata, pagesMetadata) {
        const harmonicClient = (await fs.readFileAsync(`${rootdir}/bin/client/harmonic-client.js`, { encoding: 'utf8' }))
            .replace(/__HARMONIC\.POSTS__/g, JSON.stringify(postsMetadata))
            .replace(/__HARMONIC\.PAGES__/g, JSON.stringify(pagesMetadata))
            .replace(/__HARMONIC\.CONFIG__/g, JSON.stringify(this.config));

        await fs.writeFileAsync(path.join(this.sitePath, 'public/harmonic.js'), harmonicClient);
    }

    async generateTagsPages(postsMetadata) {
        const tagTemplateNJ = nunjucks.compile(this.theme.getFileContents('index.html'), this.nunjucksEnv);
        const config = this.config;

        await* [].concat(...Object.entries(postsMetadata).map(([lang, langPosts]) => {
            const postsByTag = {};
            langPosts.forEach((post) => {
                post.categories.forEach((category) => {
                    // TODO replace with kebabCase?
                    const tag = category.toLowerCase().trim().split(' ').join('-');
                    postsByTag[tag] = postsByTag[tag] || [];
                    postsByTag[tag].push(post);
                });
            });

            return Object.entries(postsByTag).map(async ([tag, tagPosts]) => {
                const tagContent = tagTemplateNJ.render({
                    posts: tagPosts,
                    config,
                    category: tag,
                    lang
                });

                const tagPath = path.join(this.sitePath, 'public/categories', ...(config.i18n.default === lang ? [] : [lang]), tag);
                await mkdirpAsync(tagPath);
                await fs.writeFileAsync(path.join(tagPath, 'index.html'), tagContent);
                console.log(clc.info(`Successfully generated tag[${tag}] archive html file`));
            });
        }));
    }

    async generateIndex(postsMetadata, pagesMetadata) {
        const indexTemplateNJ = nunjucks.compile(this.theme.getFileContents('index.html'), this.nunjucksEnv);
        const config = this.config;

        await* Object.entries(postsMetadata).map(async ([lang, langPosts]) => {
            const posts = langPosts.slice(0, config.index_posts);
            const pages = pagesMetadata[lang] || [];

            const indexContent = indexTemplateNJ.render({
                posts,
                pages,
                config,
                lang
            });

            const indexPath = path.join(this.sitePath, 'public', ...(config.i18n.default === lang ? [] : [lang]));
            await mkdirpAsync(indexPath);
            await fs.writeFileAsync(path.join(indexPath, 'index.html'), indexContent);
            console.log(clc.info(`${lang}/index file successfully created`));
        });
    }

    async copyThemeResources() {
        await ncpAsync(path.join(this.theme.themePath, 'resources'), path.join(this.sitePath, 'public'), { stopOnErr: true });
        console.log(clc.info('Theme resources copied'));
    }

    async copyUserResources() {
        const userResourcesPath = path.join(this.sitePath, 'resources');
        await mkdirpAsync(userResourcesPath);
        await ncpAsync(userResourcesPath, path.join(this.sitePath, 'public'), { stopOnErr: true });
        console.log(clc.info(`User resources copied`));
    }

    getTemplate(layout) {
        if(!this.templates[layout]) {
            const templateContents = this.theme.getFileContents(`${layout}.html`);
            this.templates[layout] = nunjucks.compile(templateContents, this.nunjucksEnv);
        }
        return this.templates[layout];
    }

    async generateFiles(files, filesType) {
        const langs = Object.keys(files);
        const config = this.config;
        const generatedFiles = {};
        const currentDate = new Date();
        const tokens = config.header_tokens || ['<!--', '-->'];
        const metadataDefaults = {
            layout: filesType
        };

        const filesPath = filesType === 'post' ? postspath : pagespath;

        await* [].concat(...langs.map((lang) => files[lang].map(async (file) => {
            const md = new MkMeta(path.join(this.sitePath, filesPath, lang, file));
            md.defineTokens(tokens[0], tokens[1]);

            const metadata = Helper.normalizeMetaData(md.metadata(), metadataDefaults);
            metadata.content = md.markdown({
                crop: '<!--more-->'
            });

            const template = this.getTemplate(metadata.layout);
            const filename = getFileName(file);
            const permalink = filesType === 'post' ? config.posts_permalink : config.pages_permalink;

            const filePath = permalinks({
                replacements: [{
                    pattern: ':year',
                    replacement: metadata.date.getFullYear()
                },
                {
                    pattern: ':month',
                    replacement: (metadata.date.getMonth() + 1)::lpad(2, '0')
                },
                {
                    pattern: ':title',
                    replacement: filename
                },
                {
                    pattern: ':language',
                    replacement: lang
                }],
                structure: getStructure(config.i18n.default, lang, permalink)
            });

            metadata.file = filesPath + file;
            metadata.filename = filename;
            metadata.link = filePath;
            metadata.lang = lang;
            metadata.default_lang = config.i18n.default !== lang; // FIXME https://github.com/JSRocksHQ/harmonic/issues/169

            const contentHTMLFile = template
                .render({
                    [filesType]: {
                        content: md.markdown(),
                        metadata: metadata
                    },
                    config: config
                })
                .replace(/<!--[\s\S]*?-->/g, '');

            if(filesType === 'page') {
                metadata.content = contentHTMLFile;
            }

            if (metadata.published && metadata.published === 'false') {
                return;
            }

            if (metadata.date && metadata.date > currentDate) {
                console.log(clc.info(`Skipping future post ${metadata.filename}`));
                return;
            }

            const postDirPath = path.join(this.sitePath, 'public', filePath);
            const postFilePath = path.join(postDirPath, 'index.html');
            await mkdirpAsync(postDirPath);

            await fs.writeFileAsync(postFilePath, contentHTMLFile);
            console.log(clc.info(`Successfully generated post ${filePath}`));

            generatedFiles[lang] = generatedFiles[lang] || [];
            generatedFiles[lang].push(metadata);
        })));
        return Helper.sortPosts(generatedFiles);
    }

    async getPostFiles() {
        const files = {};

        await* this.config.i18n.languages.map(async (lang) => {
            files[lang] = (await fs.readdirAsync(path.join(this.sitePath, postspath, lang)))
                .filter((p) => rMarkdownExt.test(p));
        });

        return files;
    }

    async getPageFiles() {
        const files = {};

        await* this.config.i18n.languages.map(async (lang) => {
            const langPath = path.join(this.sitePath, pagespath, lang);
            await mkdirpAsync(langPath);
            files[lang] = (await fs.readdirAsync(langPath)).filter((p) => rMarkdownExt.test(p));
        });

        return files;
    }

    async generateRSS(postsMetadata, pagesMetadata) {
        const rssTemplate = await fs.readFileAsync(path.join(__dirname, 'resources/rss.xml'), { encoding: 'utf8' });
        const rssTemplateNJ = nunjucks.compile(rssTemplate, this.nunjucksEnv);
        const config = this.config;
        const rssAuthor = config.author_email ? `${config.author_email} ( ${config.author} )` : config.author;

        await* Object.entries(postsMetadata).map(async ([lang, langPosts]) => {
            const posts = langPosts.slice(0, config.index_posts);
            const isDefaultLang = config.i18n.default === lang;
            const rssPath = path.join(this.sitePath, 'public', ...(isDefaultLang ? [] : [lang]));
            const rssLink = `${config.domain}${isDefaultLang ? '' : '/' + lang}/rss.xml`;

            const rssContent = rssTemplateNJ.render({
                rss: {
                    date: new Date().toUTCString(),
                    link: rssLink,
                    author: rssAuthor,
                    lang: lang
                },
                posts,
                config,
                pages: pagesMetadata
            });

            await mkdirpAsync(rssPath);
            await fs.writeFileAsync(`${rssPath}/rss.xml`, rssContent);
            console.log(clc.info(`${lang}/rss.xml file successfully created`));
        });
    }
}
<commit_msg>fixed console message<commit_after>import path from 'path';
import fs from 'fs';
import core from 'babel-runtime/core-js';
const { lpad } = core.String.prototype;
import { promisify, promisifyAll, fromNode as promiseFromNode } from 'bluebird';
import nunjucks from 'nunjucks';
import permalinks from 'permalinks';
import MkMeta from 'marked-metadata';
import mkdirp from 'mkdirp';
import { ncp } from 'ncp';
import rimraf from 'rimraf';
import stylus from 'stylus';
import less from 'less';
import { rootdir, postspath, pagespath } from './config';
import { cliColor, getConfig, getFileName, getStructure } from './helpers';
import Theme from './theme';
promisifyAll(fs);
const mkdirpAsync = promisify(mkdirp);
const ncpAsync = promisify(ncp);
const rimrafAsync = promisify(rimraf);

const clc = cliColor();
const rMarkdownExt = /\.(?:md|markdown)$/;

const Helper = {

    sort(a, b) {
        return new Date(b.date) - new Date(a.date);
    },

    sortPosts(posts) {
        Object.values(posts).forEach((postsArray) => postsArray.sort(Helper.sort));
        return posts;
    },

    normalizeMetaData(data, defaults) {
        data.categories = (data.categories || '').split(',').map((category) => category.trim());

        if (data.date) {
            data.date = new Date(data.date);
        }

        data.layout = data.layout || defaults.layout;

        // FIXME why is this here? The template should do the escaping, not `normalizeMetaData`
        data.title = data.title.replace(/\"/g, '');

        return data;
    }
};

export default class Harmonic {
    /*eslint-disable camelcase*/

    constructor(sitePath, { quiet = true } = {}) {
        this.sitePath = path.resolve(sitePath);
        this.quiet = !!quiet;

        const config = Object.assign({
            index_posts: 10
        }, getConfig(this.sitePath));
        this.theme = new Theme(config.theme, this.sitePath);

        if (fs.existsSync(path.join(this.theme.themePath, 'config.json'))) {
            Object.assign(config, JSON.parse(this.theme.getFileContents('config.json')));
        }

        this.config = config;
        this.nunjucksEnv = nunjucks.configure(this.theme.themePath, { watch: false });
        this.templates = {};
    }

    async clean() {
        console.log(clc.warn('Cleaning up...'));
        await rimrafAsync(path.join(this.sitePath, 'public'), { maxBusyTries: 20 });
    }

    async compileCSS() {
        const currentCSSCompiler = this.config.preprocessor;
        if (!currentCSSCompiler) {
            return;
        }

        const compiler = {

            less: async () => {
                const lessIndexPath = path.join(this.theme.themePath, 'resources/_less/index.less');
                const cssDir = path.join(this.sitePath, 'public/css');

                const lessInput = await fs.readFileAsync(lessIndexPath, { encoding: 'utf8' });
                const { css } = await less.render(lessInput, { filename: lessIndexPath });

                await mkdirpAsync(cssDir);
                await fs.writeFileAsync(path.join(cssDir, 'main.css'), css);

                console.log(clc.info('Successfully generated CSS with LESS preprocessor'));
            },

            stylus: async () => {
                const stylDir = path.join(this.theme.themePath, 'resources/_stylus');
                const stylIndexPath = path.join(stylDir, 'index.styl');
                const cssDir = path.join(this.sitePath, 'public/css');

                const stylInput = await fs.readFileAsync(stylIndexPath, { encoding: 'utf8' });
                const css = await promiseFromNode((cb) => {
                    stylus(stylInput)
                        .set('filename', stylIndexPath)
                        .set('paths', [path.join(stylDir, 'engine'), path.join(stylDir, 'partials')])
                        .render(cb);
                });

                await mkdirpAsync(cssDir);
                await fs.writeFileAsync(path.join(cssDir, 'main.css'), css);

                console.log(clc.info('Successfully generated CSS with Stylus preprocessor'));
            }
        };

        if (!compiler.hasOwnProperty(currentCSSCompiler)) {
            throw new Error(`Unsupported CSS preprocessor: ${currentCSSCompiler}`);
        }

        await compiler[currentCSSCompiler]();
    }

    async compileJS(postsMetadata, pagesMetadata) {
        const harmonicClient = (await fs.readFileAsync(`${rootdir}/bin/client/harmonic-client.js`, { encoding: 'utf8' }))
            .replace(/__HARMONIC\.POSTS__/g, JSON.stringify(postsMetadata))
            .replace(/__HARMONIC\.PAGES__/g, JSON.stringify(pagesMetadata))
            .replace(/__HARMONIC\.CONFIG__/g, JSON.stringify(this.config));

        await fs.writeFileAsync(path.join(this.sitePath, 'public/harmonic.js'), harmonicClient);
    }

    async generateTagsPages(postsMetadata) {
        const tagTemplateNJ = nunjucks.compile(this.theme.getFileContents('index.html'), this.nunjucksEnv);
        const config = this.config;

        await* [].concat(...Object.entries(postsMetadata).map(([lang, langPosts]) => {
            const postsByTag = {};
            langPosts.forEach((post) => {
                post.categories.forEach((category) => {
                    // TODO replace with kebabCase?
                    const tag = category.toLowerCase().trim().split(' ').join('-');
                    postsByTag[tag] = postsByTag[tag] || [];
                    postsByTag[tag].push(post);
                });
            });

            return Object.entries(postsByTag).map(async ([tag, tagPosts]) => {
                const tagContent = tagTemplateNJ.render({
                    posts: tagPosts,
                    config,
                    category: tag,
                    lang
                });

                const tagPath = path.join(this.sitePath, 'public/categories', ...(config.i18n.default === lang ? [] : [lang]), tag);
                await mkdirpAsync(tagPath);
                await fs.writeFileAsync(path.join(tagPath, 'index.html'), tagContent);
                console.log(clc.info(`Successfully generated tag[${tag}] archive html file`));
            });
        }));
    }

    async generateIndex(postsMetadata, pagesMetadata) {
        const indexTemplateNJ = nunjucks.compile(this.theme.getFileContents('index.html'), this.nunjucksEnv);
        const config = this.config;

        await* Object.entries(postsMetadata).map(async ([lang, langPosts]) => {
            const posts = langPosts.slice(0, config.index_posts);
            const pages = pagesMetadata[lang] || [];

            const indexContent = indexTemplateNJ.render({
                posts,
                pages,
                config,
                lang
            });

            const indexPath = path.join(this.sitePath, 'public', ...(config.i18n.default === lang ? [] : [lang]));
            await mkdirpAsync(indexPath);
            await fs.writeFileAsync(path.join(indexPath, 'index.html'), indexContent);
            console.log(clc.info(`${lang}/index file successfully created`));
        });
    }

    async copyThemeResources() {
        await ncpAsync(path.join(this.theme.themePath, 'resources'), path.join(this.sitePath, 'public'), { stopOnErr: true });
        console.log(clc.info('Theme resources copied'));
    }

    async copyUserResources() {
        const userResourcesPath = path.join(this.sitePath, 'resources');
        await mkdirpAsync(userResourcesPath);
        await ncpAsync(userResourcesPath, path.join(this.sitePath, 'public'), { stopOnErr: true });
        console.log(clc.info(`User resources copied`));
    }

    getTemplate(layout) {
        if(!this.templates[layout]) {
            const templateContents = this.theme.getFileContents(`${layout}.html`);
            this.templates[layout] = nunjucks.compile(templateContents, this.nunjucksEnv);
        }
        return this.templates[layout];
    }

    async generateFiles(files, filesType) {
        const langs = Object.keys(files);
        const config = this.config;
        const generatedFiles = {};
        const currentDate = new Date();
        const tokens = config.header_tokens || ['<!--', '-->'];
        const metadataDefaults = {
            layout: filesType
        };

        const filesPath = filesType === 'post' ? postspath : pagespath;

        await* [].concat(...langs.map((lang) => files[lang].map(async (file) => {
            const md = new MkMeta(path.join(this.sitePath, filesPath, lang, file));
            md.defineTokens(tokens[0], tokens[1]);

            const metadata = Helper.normalizeMetaData(md.metadata(), metadataDefaults);
            metadata.content = md.markdown({
                crop: '<!--more-->'
            });

            const template = this.getTemplate(metadata.layout);
            const filename = getFileName(file);
            const permalink = filesType === 'post' ? config.posts_permalink : config.pages_permalink;

            const filePath = permalinks({
                replacements: [{
                    pattern: ':year',
                    replacement: metadata.date.getFullYear()
                },
                {
                    pattern: ':month',
                    replacement: (metadata.date.getMonth() + 1)::lpad(2, '0')
                },
                {
                    pattern: ':title',
                    replacement: filename
                },
                {
                    pattern: ':language',
                    replacement: lang
                }],
                structure: getStructure(config.i18n.default, lang, permalink)
            });

            metadata.file = filesPath + file;
            metadata.filename = filename;
            metadata.link = filePath;
            metadata.lang = lang;
            metadata.default_lang = config.i18n.default !== lang; // FIXME https://github.com/JSRocksHQ/harmonic/issues/169

            const contentHTMLFile = template
                .render({
                    [filesType]: {
                        content: md.markdown(),
                        metadata: metadata
                    },
                    config: config
                })
                .replace(/<!--[\s\S]*?-->/g, '');

            if(filesType === 'page') {
                metadata.content = contentHTMLFile;
            }

            if (metadata.published && metadata.published === 'false') {
                return;
            }

            if (metadata.date && metadata.date > currentDate) {
                console.log(clc.info(`Skipping future ${filesType} ${metadata.filename}`));
                return;
            }

            const postDirPath = path.join(this.sitePath, 'public', filePath);
            const postFilePath = path.join(postDirPath, 'index.html');
            await mkdirpAsync(postDirPath);

            await fs.writeFileAsync(postFilePath, contentHTMLFile);
            console.log(clc.info(`Successfully generated ${filesType} ${filePath}`));

            generatedFiles[lang] = generatedFiles[lang] || [];
            generatedFiles[lang].push(metadata);
        })));
        return Helper.sortPosts(generatedFiles);
    }

    async getPostFiles() {
        const files = {};

        await* this.config.i18n.languages.map(async (lang) => {
            files[lang] = (await fs.readdirAsync(path.join(this.sitePath, postspath, lang)))
                .filter((p) => rMarkdownExt.test(p));
        });

        return files;
    }

    async getPageFiles() {
        const files = {};

        await* this.config.i18n.languages.map(async (lang) => {
            const langPath = path.join(this.sitePath, pagespath, lang);
            await mkdirpAsync(langPath);
            files[lang] = (await fs.readdirAsync(langPath)).filter((p) => rMarkdownExt.test(p));
        });

        return files;
    }

    async generateRSS(postsMetadata, pagesMetadata) {
        const rssTemplate = await fs.readFileAsync(path.join(__dirname, 'resources/rss.xml'), { encoding: 'utf8' });
        const rssTemplateNJ = nunjucks.compile(rssTemplate, this.nunjucksEnv);
        const config = this.config;
        const rssAuthor = config.author_email ? `${config.author_email} ( ${config.author} )` : config.author;

        await* Object.entries(postsMetadata).map(async ([lang, langPosts]) => {
            const posts = langPosts.slice(0, config.index_posts);
            const isDefaultLang = config.i18n.default === lang;
            const rssPath = path.join(this.sitePath, 'public', ...(isDefaultLang ? [] : [lang]));
            const rssLink = `${config.domain}${isDefaultLang ? '' : '/' + lang}/rss.xml`;

            const rssContent = rssTemplateNJ.render({
                rss: {
                    date: new Date().toUTCString(),
                    link: rssLink,
                    author: rssAuthor,
                    lang: lang
                },
                posts,
                config,
                pages: pagesMetadata
            });

            await mkdirpAsync(rssPath);
            await fs.writeFileAsync(`${rssPath}/rss.xml`, rssContent);
            console.log(clc.info(`${lang}/rss.xml file successfully created`));
        });
    }
}
<|endoftext|>


<commit_before>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-karma');

  // Default task.
  grunt.registerTask('default', ['jshint','build','karma:unit']);
  grunt.registerTask('build', ['clean','concat','sass:build','copy:assets']);
  grunt.registerTask('release', ['clean','uglify','jshint','karma:unit','concat:index', 'sass:min','copy:assets']);
  grunt.registerTask('test-watch', ['karma:watch']);

  // Print a timestamp (useful for when watching)
  grunt.registerTask('timestamp', function() {
    grunt.log.subhead(Date());
  });

  // Project configuration.
  grunt.initConfig({
    distdir: 'dist',
    pkg: grunt.file.readJSON('package.json'),
    banner:
    '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
    '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
    ' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
    src: {
        js: ['src/**/*.js', 'test/**/*.spec.js'],
        html: ['src/index.html'],
        sass: ['src/sass/main.scss'],
        sassWatch: ['src/sass/**.css'],
        bootstrapSass: ['vendor/bootstrap/**/*.scss']

    },
    dest: {
        css: '<%= distdir %>/<%= pkg.name %>.css'
    },
    clean: ['<%= distdir %>/*'],
    copy: {
      assets: {
        files: [{ dest: '<%= distdir %>', src : '**', expand: true, cwd: 'src/assets/' },
                { dest: '<%= distdir %>/fonts', src : '**', expand: true, cwd: 'vendor/bootstrap/fonts' }]
      }
    },
    karma: {
      options: {
          configFile: 'test/config/karma.conf.js'
      },
      unit: {
          browsers: ['Firefox']
      },
      watch: {
          singleRun: false,
          autoWatch: true
      }
    },
    concat:{
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      index: {
        src: ['src/index.html'],
        dest: '<%= distdir %>/index.html',
        options: {
          process: true
        }
      },
      angular: {
        src:['vendor/angular/angular.js', 'vendor/angular/angular-*.js'],
        dest: '<%= distdir %>/angular.js'
      },
      angularui: {
        src:['vendor/angular-ui/utils/*.js', 'vendor/angular-ui/router/*.js', 'vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/angular-ui.js'
      }
    },
    uglify: {
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>' ,'<%= src.jsTpl %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      angular: {
        src:['<%= concat.angular.src %>'],
        dest: '<%= distdir %>/angular.js'
      },
      bootstrap: {
        src:['vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/bootstrap.js'
      }
    },
    sass: {
        build: {
            options: {
                style: 'expanded'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        },
        min: {
            options: {
                style: 'compressed'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        }
    },
    watch:{
      all: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['default','timestamp']
      },
      build: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['build','timestamp']
      }
    },
    jshint:{
      files:['gruntFile.js', '<%= src.js %>'],
      options:{
        curly:true,
        eqeqeq:true,
        immed:true,
        latedef:true,
        newcap:true,
        noarg:true,
        sub:true,
        boss:true,
        eqnull:true,
        globals:{}
      }
    }
  });

};
<commit_msg>keeping the grunt build file up to date with all of the changes i'm making<commit_after>module.exports = function (grunt) {

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-karma');

  // Default task.
  grunt.registerTask('default', ['jshint','build','karma:unit']);
  grunt.registerTask('build', ['clean','concat','sass:build','copy:assets']);
  grunt.registerTask('release', ['clean','uglify','jshint','karma:unit','concat:index', 'sass:min','copy:assets']);
  grunt.registerTask('test-watch', ['karma:watch']);

  // Print a timestamp (useful for when watching)
  grunt.registerTask('timestamp', function() {
    grunt.log.subhead(Date());
  });

  // Project configuration.
  grunt.initConfig({
    distdir: 'dist',
    pkg: grunt.file.readJSON('package.json'),
    banner:
    '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
    '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
    ' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
    src: {
        mb: ['src/app/mb-main.js', 'src/app/modules/*.js'],
        test: ['test/**/*.spec.js'],
        html: ['src/index.html'],
        sass: ['src/sass/main.scss'],
        sassWatch: ['src/sass/**.css'],
        bootstrapSass: ['vendor/bootstrap/**/*.scss']

    },
    dest: {
        css: '<%= distdir %>/<%= pkg.name %>.css'
    },
    clean: ['<%= distdir %>/*'],
    copy: {
      assets: {
        files: [{ dest: '<%= distdir %>', src : '**', expand: true, cwd: 'src/assets/' },
                { dest: '<%= distdir %>/fonts', src : '**', expand: true, cwd: 'vendor/bootstrap/fonts' }]
      }
    },
    karma: {
      options: {
          configFile: 'test/config/karma.conf.js'
      },
      unit: {
          browsers: ['Firefox']
      },
      watch: {
          singleRun: false,
          autoWatch: true
      }
    },
    concat:{
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.mb %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      index: {
        src: ['src/index.html'],
        dest: '<%= distdir %>/index.html',
        options: {
          process: true
        }
      },
      angular: {
        src:['vendor/angular/angular.js', 'vendor/angular/angular-*.js'],
        dest: '<%= distdir %>/angular.js'
      },
      angularui: {
        src:['vendor/angular-ui/utils/*.js', 'vendor/angular-ui/router/*.js', 'vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/angular-ui.js'
      }
    },
    uglify: {
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>' ,'<%= src.jsTpl %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      angular: {
        src:['<%= concat.angular.src %>'],
        dest: '<%= distdir %>/angular.js'
      },
      bootstrap: {
        src:['vendor/angular-ui/bootstrap/*.js'],
        dest: '<%= distdir %>/bootstrap.js'
      }
    },
    sass: {
        build: {
            options: {
                style: 'expanded'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        },
        min: {
            options: {
                style: 'compressed'
            },
            files: {
                '<%= dest.css %>': '<%= src.sass %>',
                '<%= distdir %>/bootstrap.css': '<%= src.bootstrapSass %>'
            }
        }
    },
    watch:{
      all: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['default','timestamp']
      },
      build: {
        files:['<%= src.js %>', '<%= src.html %>', '<%= src.sassWatch %>'],
        tasks:['build','timestamp']
      }
    },
    jshint:{
      files:['gruntFile.js', '<%= src.mb %>', '<%= src.test %>'],
      options:{
        curly:true,
        eqeqeq:true,
        immed:true,
        latedef:true,
        newcap:true,
        noarg:true,
        sub:true,
        boss:true,
        eqnull:true,
        globals:{}
      }
    }
  });

};
<|endoftext|>


<commit_before>var child = require('child_process');
var path = require('path');
var os = require('os');
var fs = require('fs');
var Heroku = require('heroku-client');
var request = require('request');
var agent = require('superagent');
var cli = require('heroku-cli-util');
var _ = require('lodash');
var ProgressBar = require('progress');

var directory = require('../lib/directory');
var docker = require('../lib/docker');
var safely = require('../lib/safely');

const ADDONS = require('../lib/addons');

module.exports = function(topic) {
  return {
    topic: topic,
    command: 'release',
    description: 'create and release slug to app',
    help: 'Create slug tarball from Docker image and release it to Heroku app',
    needsApp: true,
    needsAuth: true,
    run: safely(release)
  };
};

function release(context) {
  var procfile = directory.readProcfile(context.cwd);
  var mountDir = directory.determineMountDir(context.cwd);
  var modifiedProc = _.mapValues(procfile, prependMountDir(mountDir));
  var heroku = context.heroku || new Heroku({ token: context.auth.password });
  var app = context.heroku ? context.app : heroku.apps(context.app);
  var appJSONLocation = path.join(context.cwd, 'app.json');
  var appJSON = JSON.parse(fs.readFileSync(appJSONLocation, { encoding: 'utf8' }));

  request = context.request || request;

  if (!procfile) throw new Error('Procfile required. Aborting');

  return app.info()
    .then(readRemoteAddons)
    .then(compareLocalAddons)
    .then(addMissingAddons)
    .then(createLocalSlug)
    .then(createRemoteSlug)
    .then(uploadSlug)
    .then(releaseSlug)
    .then(showMessage);

  function prependMountDir(mountDir) {
    return function(cmd) {
      return `cd ${ mountDir } && ${ cmd }`
    }
  }

  function readRemoteAddons() {
    return app.addons().list();
  }

  function compareLocalAddons(remoteAddons) {
    var remoteNames = _.map(remoteAddons, getServiceName);
    var localNames = appJSON.addons || [];
    var missingAddons = _.filter(localNames, isMissingFrom.bind(this, remoteNames));

    console.log(`Remote addons: ${ remoteNames.join(', ')} (${ remoteNames.length })`);
    console.log(`Local addons: ${ localNames.join(', ') } (${ localNames.length })`);
    console.log(`Missing addons: ${ missingAddons.join(', ') } (${ missingAddons.length })`);

    return Promise.resolve(missingAddons);

    function getServiceName(addon) {
      return addon.addon_service.name;
    }

    function isMissingFrom(list, addon) {
      var name = addon.split(':')[0];
      return list.indexOf(name) === -1;
    }
  }

  function addMissingAddons(addons) {
    return Promise.all(addons.map(createAddon));

    function createAddon(name) {
      console.log(`Provisioning ${ name }...`)
      return app.addons().create({
        plan: name
      });
    }
  }

  function createLocalSlug() {
    cli.log('Creating local slug...');

    return new Promise(function(resolve, reject) {
      var slugPath = os.tmpdir();
      var output = '';
      var build = child.spawn('docker-compose', ['build', 'web']);

      build.stdout.pipe(process.stdout);
      build.stderr.pipe(process.stderr);
      build.stdout.on('data', saveOutput);
      build.on('exit', onBuildExit);

      function saveOutput(data) {
        output += data;
      }

      function onBuildExit(code) {
        if (code !== 0) {
          cli.log('Build failed. Make sure `docker-compose build web` returns a 0 exit status.');
          return;
        }

        var tokens = output.match(/\S+/g);
        var fromMatch = output.match(/FROM ([^\s]+)/) || [];
        var imageName = fromMatch[1];
        var imageId = tokens[tokens.length - 1];
        tar(imageName, imageId);
      }

      function tar(imageName, imageId) {
        cli.log('extracting slug from container...');
        var containerId = child.execSync(`docker run -d ${imageId} tar cfvz /tmp/slug.tgz -C / --exclude=.git --exclude=.cache --exclude=.buildpack ./app`, {
          encoding: 'utf8'
        }).trim();
        child.execSync(`docker wait ${containerId}`);
        child.execSync(`docker cp ${containerId}:/tmp/slug.tgz ${slugPath}`);
        child.execSync(`docker rm -f ${containerId}`);
        resolve({
          path: path.join(slugPath, 'slug.tgz'),
          name: imageName
        });
      }
    });
  }

  function createRemoteSlug(slug) {
    var lang = `heroku-docker (${ slug.name || 'unknown'})`;
    cli.log(`creating remote slug...`);
    cli.log(`language-pack: ${ lang }`);
    cli.log('remote process types:', modifiedProc);
    var slugInfo = app.slugs().create({
      process_types: modifiedProc,
      buildpack_provided_description: lang
    });
    return Promise.all([slug.path, slugInfo])
  }

  function uploadSlug(slug) {
    var slugPath = slug[0];
    var slugInfo = slug[1];
    var size = fs.statSync(slugPath).size;
    var mbs = Math.round(size / 1024 / 1024)
    var bar = new ProgressBar(`uploading slug [:bar] :percent of ${ mbs } MB, :etas`, {
      width: 20,
      total: size
    });

    return new Promise(function(resolve, reject) {
      var outStream = request({
        method: 'PUT',
        url: slugInfo.blob.url,
        headers: {
          'content-type': '',
          'content-length': size
        }
      });

      fs.createReadStream(slugPath)
        .on('error', reject)
        .on('data', updateProgress)
        .pipe(outStream)
        .on('error', reject)
        .on('response', resolve.bind(this, slugInfo.id));

      function updateProgress(chunk) {
        bar.tick(chunk.length);
      }
    });
  }

  function releaseSlug(id) {
    cli.log('releasing slug...');

    return heroku.request({
      method: 'POST',
      path: `${ app.path }/releases`,
      headers: {
        'Heroku-Deploy-Type': 'heroku-docker'
      },
      body: {
        slug: id
      }
    });
  }

  function showMessage(results) {
    console.log(`Successfully released ${ results.app.name }!`);
  }
}
<commit_msg>send a non-zero exit status when the build failed<commit_after>var child = require('child_process');
var path = require('path');
var os = require('os');
var fs = require('fs');
var Heroku = require('heroku-client');
var request = require('request');
var agent = require('superagent');
var cli = require('heroku-cli-util');
var _ = require('lodash');
var ProgressBar = require('progress');

var directory = require('../lib/directory');
var docker = require('../lib/docker');
var safely = require('../lib/safely');

const ADDONS = require('../lib/addons');

module.exports = function(topic) {
  return {
    topic: topic,
    command: 'release',
    description: 'create and release slug to app',
    help: 'Create slug tarball from Docker image and release it to Heroku app',
    needsApp: true,
    needsAuth: true,
    run: safely(release)
  };
};

function release(context) {
  var procfile = directory.readProcfile(context.cwd);
  var mountDir = directory.determineMountDir(context.cwd);
  var modifiedProc = _.mapValues(procfile, prependMountDir(mountDir));
  var heroku = context.heroku || new Heroku({ token: context.auth.password });
  var app = context.heroku ? context.app : heroku.apps(context.app);
  var appJSONLocation = path.join(context.cwd, 'app.json');
  var appJSON = JSON.parse(fs.readFileSync(appJSONLocation, { encoding: 'utf8' }));

  request = context.request || request;

  if (!procfile) throw new Error('Procfile required. Aborting');

  return app.info()
    .then(readRemoteAddons)
    .then(compareLocalAddons)
    .then(addMissingAddons)
    .then(createLocalSlug)
    .then(createRemoteSlug)
    .then(uploadSlug)
    .then(releaseSlug)
    .then(showMessage);

  function prependMountDir(mountDir) {
    return function(cmd) {
      return `cd ${ mountDir } && ${ cmd }`
    }
  }

  function readRemoteAddons() {
    return app.addons().list();
  }

  function compareLocalAddons(remoteAddons) {
    var remoteNames = _.map(remoteAddons, getServiceName);
    var localNames = appJSON.addons || [];
    var missingAddons = _.filter(localNames, isMissingFrom.bind(this, remoteNames));

    console.log(`Remote addons: ${ remoteNames.join(', ')} (${ remoteNames.length })`);
    console.log(`Local addons: ${ localNames.join(', ') } (${ localNames.length })`);
    console.log(`Missing addons: ${ missingAddons.join(', ') } (${ missingAddons.length })`);

    return Promise.resolve(missingAddons);

    function getServiceName(addon) {
      return addon.addon_service.name;
    }

    function isMissingFrom(list, addon) {
      var name = addon.split(':')[0];
      return list.indexOf(name) === -1;
    }
  }

  function addMissingAddons(addons) {
    return Promise.all(addons.map(createAddon));

    function createAddon(name) {
      console.log(`Provisioning ${ name }...`)
      return app.addons().create({
        plan: name
      });
    }
  }

  function createLocalSlug() {
    cli.log('Creating local slug...');

    return new Promise(function(resolve, reject) {
      var slugPath = os.tmpdir();
      var output = '';
      var build = child.spawn('docker-compose', ['build', 'web']);

      build.stdout.pipe(process.stdout);
      build.stderr.pipe(process.stderr);
      build.stdout.on('data', saveOutput);
      build.on('exit', onBuildExit);

      function saveOutput(data) {
        output += data;
      }

      function onBuildExit(code) {
        if (code !== 0) {
          cli.log('Build failed. Make sure `docker-compose build web` returns a 0 exit status.');
          process.exit(1);
        }

        var tokens = output.match(/\S+/g);
        var fromMatch = output.match(/FROM ([^\s]+)/) || [];
        var imageName = fromMatch[1];
        var imageId = tokens[tokens.length - 1];
        tar(imageName, imageId);
      }

      function tar(imageName, imageId) {
        cli.log('extracting slug from container...');
        var containerId = child.execSync(`docker run -d ${imageId} tar cfvz /tmp/slug.tgz -C / --exclude=.git --exclude=.cache --exclude=.buildpack ./app`, {
          encoding: 'utf8'
        }).trim();
        child.execSync(`docker wait ${containerId}`);
        child.execSync(`docker cp ${containerId}:/tmp/slug.tgz ${slugPath}`);
        child.execSync(`docker rm -f ${containerId}`);
        resolve({
          path: path.join(slugPath, 'slug.tgz'),
          name: imageName
        });
      }
    });
  }

  function createRemoteSlug(slug) {
    var lang = `heroku-docker (${ slug.name || 'unknown'})`;
    cli.log(`creating remote slug...`);
    cli.log(`language-pack: ${ lang }`);
    cli.log('remote process types:', modifiedProc);
    var slugInfo = app.slugs().create({
      process_types: modifiedProc,
      buildpack_provided_description: lang
    });
    return Promise.all([slug.path, slugInfo])
  }

  function uploadSlug(slug) {
    var slugPath = slug[0];
    var slugInfo = slug[1];
    var size = fs.statSync(slugPath).size;
    var mbs = Math.round(size / 1024 / 1024)
    var bar = new ProgressBar(`uploading slug [:bar] :percent of ${ mbs } MB, :etas`, {
      width: 20,
      total: size
    });

    return new Promise(function(resolve, reject) {
      var outStream = request({
        method: 'PUT',
        url: slugInfo.blob.url,
        headers: {
          'content-type': '',
          'content-length': size
        }
      });

      fs.createReadStream(slugPath)
        .on('error', reject)
        .on('data', updateProgress)
        .pipe(outStream)
        .on('error', reject)
        .on('response', resolve.bind(this, slugInfo.id));

      function updateProgress(chunk) {
        bar.tick(chunk.length);
      }
    });
  }

  function releaseSlug(id) {
    cli.log('releasing slug...');

    return heroku.request({
      method: 'POST',
      path: `${ app.path }/releases`,
      headers: {
        'Heroku-Deploy-Type': 'heroku-docker'
      },
      body: {
        slug: id
      }
    });
  }

  function showMessage(results) {
    console.log(`Successfully released ${ results.app.name }!`);
  }
}
<|endoftext|>


<commit_before>/*
* Cepat Sembuh v1.0
* Copyright 2016 Cepat Sembuh
*/

document.addEventListener('deviceready', function () {
    Firebase.goOnline();
});

// Example faskes action
$('#not-available').on('click', function() {
	alert('Faskes is not available.')
})

function getNoAntri(tipe, username, name) {
  grease = '../poli/' + username + '.html';
  window.location.href = grease;
}

function tempatTidur(tipe, username) {
  // Firebase URL
  brea = new Firebase('http://cepatsembuh.firebaseio.com/' + tipe + '/faskes/' + username + '/tempat_tidur');

  // Waiting message
  wait = 'Getting data..';
  console.log(wait);
  alert(wait);

  // Get the data
  brea.on('value', function(snapshot) {
    satu = snapshot.val().satu;
    dua = snapshot.val().dua;
    tiga = snapshot.val().tiga;

    alert('Kelas I: ' + Number(satu) + '\n' + 'Kelas II: ' + Number(dua) + '\n' + 'Kelas III: ' + Number(tiga)); // Show user the data's
  })
}

function doctorProfile(nama, lulusan, tahun) {
  giant = 'Lulusan: ' + lulusan + '\n' + 'Tahun: ' + tahun; // Doctor content
  name = 'dr. ' + nama; // Doctor name

  alert(name + '\n' + giant); // Pop-up
}

function pilihPoli(username) {
  breanna = new Firebase('http://cepatsembuh.firebaseio.com/' + tipe + '/faskes/' + username),
 antri = new Firebase('http://cepatsembuh.firebaseio.com/' + tipe + '/faskes/' + username + '/antrian');
 pasien = breanna.child('pasien'),

 // Date
 date = new Date(),
 year = date.getFullYear(),
 month = date.getMonth() + 1,
 day = date.getDate(),
 right_now = year + '-' + month + '-' + day,
 today = breanna.child(right_now),

 // Get data
 get = 'Getting data..';
 console.log(get);

 alert('Mohon konfirmasi ulang');

 // Prompt
 var nama = prompt('Nama: '),
     nik = prompt('NIK: ');

 if (nama === '' || nik.length != 16 || typeof Number(nik) !== 'number' || Number(nik) == 'NaN') {
   alert('Input tidak valid');
 } else {
   antri.transaction(function(currentRank) {
       currentData = currentRank + 1;

       return currentData;
   }, function(error, committed, snapshot) {
       if (error) {
           // Error message
           alert('Koneksi anda tidak stabil' + error);
       } else {
           // Send the Data
           alert('Nomor Antrian: ' + snapshot.val() + '\n' + '*Harap screenshot ini dan tunjukan ke faskes anda');

           // Push the prompt data
           today.push().set({
             nama: nama,
             nik: nik,
             no_antri: snapshot.val()
           })
       }
   });
 }
 console.log('Data is ready');
}
<commit_msg>Space this shit<commit_after>/*
* Cepat Sembuh v1.0
* Copyright 2016 Cepat Sembuh
*/

document.addEventListener('deviceready', function () {
    Firebase.goOnline();
});

// Example faskes action
$('#not-available').on('click', function() {
	alert('Faskes is not available.')
})

function getNoAntri(tipe, username, name) {
  grease = '../poli/' + username + '.html';
  window.location.href = grease;
}

function tempatTidur(tipe, username) {
  // Firebase URL
  brea = new Firebase('http://cepatsembuh.firebaseio.com/' + tipe + '/faskes/' + username + '/tempat_tidur');

  // Waiting message
  wait = 'Getting data..';
  console.log(wait);
  alert(wait);

  // Get the data
  brea.on('value', function(snapshot) {
    satu = snapshot.val().satu;
    dua = snapshot.val().dua;
    tiga = snapshot.val().tiga;

    alert('Kelas I: ' + Number(satu) + '\n' + 'Kelas II: ' + Number(dua) + '\n' + 'Kelas III: ' + Number(tiga)); // Show user the data's
  })
}

function doctorProfile(nama, lulusan, tahun) {
  giant = 'Lulusan: ' + lulusan + '\n' + 'Tahun: ' + tahun; // Doctor content
  name = 'dr. ' + nama; // Doctor name

  alert(name + '\n' + giant); // Pop-up
}

function pilihPoli(username) {
 breanna = new Firebase('http://cepatsembuh.firebaseio.com/' + tipe + '/faskes/' + username),
 antri = new Firebase('http://cepatsembuh.firebaseio.com/' + tipe + '/faskes/' + username + '/antrian');
 pasien = breanna.child('pasien'),

 // Date
 date = new Date(),
 year = date.getFullYear(),
 month = date.getMonth() + 1,
 day = date.getDate(),
 right_now = year + '-' + month + '-' + day,
 today = breanna.child(right_now),

 // Get data
 get = 'Getting data..';
 console.log(get);

 alert('Mohon konfirmasi ulang');

 // Prompt
 var nama = prompt('Nama: '),
     nik = prompt('NIK: ');

 if (nama === '' || nik.length != 16 || typeof Number(nik) !== 'number' || Number(nik) == 'NaN') {
   alert('Input tidak valid');
 } else {
   antri.transaction(function(currentRank) {
       currentData = currentRank + 1;

       return currentData;
   }, function(error, committed, snapshot) {
       if (error) {
           // Error message
           alert('Koneksi anda tidak stabil' + error);
       } else {
           // Send the Data
           alert('Nomor Antrian: ' + snapshot.val() + '\n' + '*Harap screenshot ini dan tunjukan ke faskes anda');

           // Push the prompt data
           today.push().set({
             nama: nama,
             nik: nik,
             no_antri: snapshot.val()
           })
       }
   });
 }
 console.log('Data is ready');
}
<|endoftext|>


<commit_before><commit_msg>fix(gatsby-image): check if imageRef is still available (#22255)<commit_after><|endoftext|>


<commit_before>//for application

var BiwaScheme = {
  // load library and execute proc after loading
  // also used by js-load
  require: function(src, check, proc) {
    var script = document.createElement('script')
    script.src = src;
    document.body.appendChild(script);

    var checker = new Function("return !!(" + check + ")");

    if(checker()) proc();
    else          setTimeout(function(){ checker() ? proc() : setTimeout(arguments.callee, 10); }, 10);
  }
};

(function(){ //local namespace
  var require = BiwaScheme.require;

  // taken from prototype.js 1.6.0
  var readAttribute = function(element, name) {
    if (/*Prototype.Browser.IE*/ !!(window.attachEvent && !window.opera)){
      var t = {
        names: {
          'class': 'className',
          'for':   'htmlFor'
        },
        values: {
          _getAttr: function(element, attribute) {
            return element.getAttribute(attribute, 2);
          },
          _getAttrNode: function(element, attribute) {
            var node = element.getAttributeNode(attribute);
            return node ? node.value : "";
          },
          _getEv: function(element, attribute) {
            var attribute = element.getAttribute(attribute);
            return attribute ? attribute.toString().slice(23, -2) : null;
          },
          _flag: function(element, attribute) {
            return $(element).hasAttribute(attribute) ? attribute : null;
          },
          style: function(element) {
            return element.style.cssText.toLowerCase();
          },
          title: function(element) {
            return element.title;
          }
        }
      };
      if (t.values[name]) return t.values[name](element, name);
      if (t.names[name]) name = t.names[name];
      if (name.indexOf(':') > -1){
        return (!element.attributes || !element.attributes[name]) ? null :
         element.attributes[name].value;
      }
    }
    return element.getAttribute(name);
  }

  // main
  var script = (function(e){
    if(e.id == '_firebugConsole'){
      return arguments.callee(document.body);
    }
    else if(e.nodeName.toLowerCase() == 'script'){
      return e;
    }
    else{
      return arguments.callee(e.lastChild);
    }
  })(document);

  var src = readAttribute(script, 'src');
  var dir = src.match(/(.*)biwascheme.js/)[1];

  require(dir+'jquery.js',        'window.$', function(){
  require(dir+'underscore.js',    'window._', function(){
  require(dir+'underscore.string.js', 'window._.capitalize', function(){
  require(dir+'rename_underscore', 'window.underscore', function(){
  require(dir+'stackbase.js',     'window.BiwaScheme.CoreEnv', function(){
  require(dir+'r6rs_lib.js',      'window.BiwaScheme.CoreEnv["+"]', function(){
  require(dir+'js_interface.js',  'window.BiwaScheme.CoreEnv["js-eval"]', function(){
  require(dir+'webscheme_lib.js', 'window.BiwaScheme.CoreEnv["getelem"]', function(){
  require(dir+'extra_lib.js',     'window.BiwaScheme.CoreEnv["print"]', function(){
  require(dir+'dumper.js',        'window.BiwaScheme.Dumper', function(){
  require(dir+'io.js',            'window.JSIO', function(){
    var onError = function(e, state){
      puts(e.message);
      if($("biwascheme-debugger")){
        var dumper = new BiwaScheme.Dumper($("biwascheme-debugger"));
        dumper.dump(state);
        dumper.dump_move(1);
      }
      throw(e);
    };
    var intp = new BiwaScheme.Interpreter(onError);
    try{
      intp.evaluate(script.html(), function(){});
    }
    catch(e){
      onError(e);
    }
  })})})})})})})})})});
})();

//vim: set ft=javascript:
<commit_msg>Removed src/biwascheme.js.<commit_after><|endoftext|>


<commit_before>const minimist = require('minimist')
const { build, printCommands, printWtf, print } = require('gluegun')
const header = require('../brand/header')
const { isNil, isEmpty } = require('ramda')
const PrettyError = require('pretty-error')
const pe = new PrettyError()

const buildIgnite = () => {
  return build()
    .brand('ignite')
    .loadDefault(`${__dirname}/..`)
    .loadAll(`${process.cwd()}/ignite/plugins`)
    .loadAll(`${process.cwd()}/node_modules`, { matching: 'ignite-*', hidden: true })
    .token('commandName', 'cliCommand')
    .token('commandHidden', 'cliHidden')
    .token('commandAlias', 'cliAlias')
    .token('commandName', 'cliCommand')
    .token('commandDescription', 'cliDescription')
    .token('extensionName', 'contextExtension')
    .createRuntime()
}

/**
 * Kick off a run.
 *
 * @param  {array} argv An array of command line arguments.
 * @return {RunContext} The gluegun RunContext
 */
module.exports = async function run (argv) {
  // create a runtime
  let runtime
  try {
    runtime = buildIgnite()
  } catch (e) {
    console.log(pe.render(e))
    throw e // rethrow
  }

  // parse the commandLine line
  const commandLine = minimist(argv.slice(2))

  // should we show the version number & jet?
  const hasNoArguments = isEmpty(commandLine._)
  const hasVersionOption = commandLine.version || commandLine.v
  if (hasNoArguments && hasVersionOption) {
    await runtime.run({ rawCommand: 'version' })
    return
  }

  // wtf mode shows problems with plugins, commands, and extensions
  if (commandLine.wtf) {
    printWtf(runtime)
    return
  }

  // run the command
  let context
  try {
    context = await runtime.run()
  } catch (e) {
    console.log(pe.render(e))
    throw e // rethrow
  }

  if (commandLine.help || commandLine.h || isNil(context.plugin) || isNil(context.command)) {
    // no args, show help
    print.info('')
    header()
    printCommands(context)
    print.info('')
    print.info(print.colors.magenta('If you need additional help, join our Slack at http://community.infinite.red'))
    print.info('')
  }

  if (context.error) {
    print.debug(context.error)
  }

  // send it back to make testing easier
  return context
}
<commit_msg>Adds gluegun plugin detection.<commit_after>const minimist = require('minimist')
const { build, printCommands, printWtf, print } = require('gluegun')
const header = require('../brand/header')
const { isNil, isEmpty } = require('ramda')
const PrettyError = require('pretty-error')
const pe = new PrettyError()

const buildIgnite = () => {
  return build()
    .brand('ignite')
    .loadDefault(`${__dirname}/..`)
    .loadAll(`${process.cwd()}/ignite/plugins`)
    .loadAll(`${process.cwd()}/node_modules`, { matching: 'ignite-*', hidden: true })
    .loadAll(`${process.cwd()}/node_modules`, { matching: 'gluegun-*', hidden: true })
    .token('commandName', 'cliCommand')
    .token('commandHidden', 'cliHidden')
    .token('commandAlias', 'cliAlias')
    .token('commandName', 'cliCommand')
    .token('commandDescription', 'cliDescription')
    .token('extensionName', 'contextExtension')
    .createRuntime()
}

/**
 * Kick off a run.
 *
 * @param  {array} argv An array of command line arguments.
 * @return {RunContext} The gluegun RunContext
 */
module.exports = async function run (argv) {
  // create a runtime
  let runtime
  try {
    runtime = buildIgnite()
  } catch (e) {
    console.log(pe.render(e))
    throw e // rethrow
  }

  // parse the commandLine line
  const commandLine = minimist(argv.slice(2))

  // should we show the version number & jet?
  const hasNoArguments = isEmpty(commandLine._)
  const hasVersionOption = commandLine.version || commandLine.v
  if (hasNoArguments && hasVersionOption) {
    await runtime.run({ rawCommand: 'version' })
    return
  }

  // wtf mode shows problems with plugins, commands, and extensions
  if (commandLine.wtf) {
    printWtf(runtime)
    return
  }

  // run the command
  let context
  try {
    context = await runtime.run()
  } catch (e) {
    console.log(pe.render(e))
    throw e // rethrow
  }

  if (commandLine.help || commandLine.h || isNil(context.plugin) || isNil(context.command)) {
    // no args, show help
    print.info('')
    header()
    printCommands(context)
    print.info('')
    print.info(print.colors.magenta('If you need additional help, join our Slack at http://community.infinite.red'))
    print.info('')
  }

  if (context.error) {
    print.debug(context.error)
  }

  // send it back to make testing easier
  return context
}
<|endoftext|>


<commit_before>Object.extend(Date.prototype, {

  clone: function(func) {
    date = new Date(this);
    func && func(date);
    return date;
  },

  succ: function() {
    return this.clone(function(date) {
      date.setDate(date.getDate() + 1);
    });
  },

  startOfMonth: function() {
    return this.clone(function(date) {
      date.setDate(1);
    });
  },

  endOfMonth: function() {
    return this.clone(function(date) {
      date.setDate(1);
      date.setMonth(date.getMonth() + 1);
      date.setDate(0);
    });
  },

  setDayOfWeek: function(dayIdx) {
    date.setDate(date.getDate() - date.getDay() + dayIdx);
  },

  startOfWeek: function() {
    return this.clone(function(date) {
      date.setDayOfWeek(0);
    });
  },

  endOfWeek: function() {
    return this.clone(function(date) {
      date.setDayOfWeek(6);
    });
  },

  monthNames: $w('January February March April May June July August September October November December'),
  getMonthName: function() {
    return this.monthNames[this.getMonth()];
  },

  toShortString: function() {
    var dd = this.getDate().toPaddedString(2);
    var mm = (this.getMonth() + 1).toPaddedString(2);
    var yy = this.getFullYear().toString().substr(2,2);
    return [ mm, dd, yy ].join('/');
  },

  sameDateAs: function(other) {
    return ((other instanceof Date) && (this.toShortString() == other.toShortString()));
  },

  isToday: function() {
    return this.sameDateAs(new Date());
  }

});

var TableSectionMethods = {
  addRow: function(tHead) {
    return $(tHead.appendChild(document.createElement('tr')));
  }
};
Element.addMethods('THEAD', TableSectionMethods);
Element.addMethods('TBODY', TableSectionMethods);

var CalSelect = Class.create({

  initialize: function(dateField) {
    this.dateField = $(dateField);
    this.initCalWrapper();
    this.initObservers();
  },

  initCalWrapper: function() {
    this.calWrapper = $(document.createElement('div'));
    this.calWrapper.addClassName('calendar');
    this.calWrapper.hide();
    this.dateField.insert({after: this.calWrapper});
  },

  initObservers: function() {
    this.dateField.observe('focus', this.show.bind(this));
    this.dateField.observe('keydown', function(event) {
      if (event.keyCode == Event.KEY_TAB) { this.hide(); }
    }.bindAsEventListener(this));

    document.observe('click', this.hide.bind(this));

    this.dateField.observe('click', Event.stop);
    this.calWrapper.observe('click', Event.stop);
  },

  show: function() {
    this.dateField.select();
    var selectedDate = this.getDate();
    var pageDate = selectedDate ? selectedDate.clone() : new Date();
    var calPage = new CalPage(pageDate, selectedDate, this.setDate.bind(this));
    this.calWrapper.update(calPage);
    this.setPosition();
    this.calWrapper.show();
  },

  setPosition: function() {
    var offset = this.dateField.positionedOffset();
    offset.top += this.dateField.getHeight();
    this.calWrapper.setStyle({left: offset.left+'px', top: offset.top+'px'});
  },

  hide: function() {
    this.calWrapper.hide();
  },

  getDate: function() {
    var dateStr = $F(this.dateField);
    var dateMatch = dateStr.match(/^\s*(\d{1,2})\/(\d{1,2})\/(\d{2}(\d{2})?)\s*$/);
    if (dateMatch) {
      var month = dateMatch[1] - 1;
      var day   = dateMatch[2];
      var year  = dateMatch[3];
      if (!dateMatch[4]) { year = '20' + year; }
      return new Date(year, month, day);
    } else {
      return null;
    }
  },

  setDate: function(date) {
    this.dateField.setValue(date.toShortString());
    this.hide();
  }

});

var CalPage = Class.create({

  initialize: function(pageDate, selectedDate, dateSelectCallback) {
    this.pageDate = pageDate.startOfMonth();
    this.selectedDate = selectedDate;
    this.dateSelectCallback = dateSelectCallback;
  },

  monthIdx: function() {
    return this.pageDate.getMonth();
  },

  toElement: function() {
    this.calTable = $(document.createElement('table'));

    var tHead = $(document.createElement('thead'));
    this.calTable.insert(tHead);

    this.calTable.tHead.insert(new CalMonthHeader(this.pageDate, this.advance.bind(this)));
    this.calTable.tHead.insert(new CalDayHeader());
    this.calTable.insert(new CalMonth(this));

    return this.calTable;
  },

  advance: function(months) {
    this.pageDate.setMonth(this.pageDate.getMonth() + months);
    this.calTable.replace(this);
  },

});

var CalMonthHeader = Class.create({

  initialize: function(date, pagerCallback) {
    this.pageDate = date;
    this.pagerCallback = pagerCallback;
  },

  toElement: function() {
    var tr = document.createElement('tr');

    this.createLeftPager(tr);

    var month = $(document.createElement('th'));
    month.colSpan = 5;
    tr.insert(month);
    month.insert(this.pageDate.getMonthName() + ' ' + this.pageDate.getFullYear());

    this.createRightPager(tr);

    return tr;
  },

  createLeftPager: function(tr) {
    this.createPager(tr, '«', -1);
  },

  createRightPager: function(tr) {
    this.createPager(tr, '»', 1);
  },

  createPager: function(tr, text, months) {
    var th = $(document.createElement('th'));
    th.addClassName('pager');
    tr.insert(th);
    th.insert(text);
    th.observe('click', this.pagerCallback.curry(months));
  }

});

var CalDayHeader = Class.create({

  headers: $w('S M T W T F S'),

  toElement: function() {
    var tr = document.createElement('tr')
    this.headers.each(function(day) {
      var th = $(document.createElement('th'));
      tr.insert(th.insert(day));
    });
    return tr;
  }

});

var CalMonth = Class.create({

  initialize: function(calPage) {
    this.calPage = calPage;
  },

  dateRange: function() {
    return $R(this.calPage.pageDate.startOfMonth().startOfWeek(),
      this.calPage.pageDate.endOfMonth().endOfWeek());
  },

  toElement: function() {
    var calBody = $(document.createElement('tbody'));
    var calRow;
    var calPage = this.calPage;

    this.dateRange().each(function(date) {
      if (date.getDay() == 0) { calRow = calBody.addRow(); }
      calRow.insert(new CalDate(date, calPage));
    });

    return calBody;
  }

});

var CalDate = Class.create({

  initialize: function(date, calPage) {
    this.date = date;
    this.calPage = calPage;
    this.selectCallback = calPage.dateSelectCallback.curry(date);

    this.isOtherMonth = (date.getMonth() != calPage.monthIdx());
    this.isSelected   = (date.sameDateAs(calPage.selectedDate));
    this.isToday      = (this.date.isToday());
  },

  cssClassMap: $H({isOtherMonth: 'other', isSelected: 'selected', isToday: 'today'}),
  addConditionalClasses: function(element) {
    this.cssClassMap.each(function(pair) {
      if (this[pair.key]) { element.addClassName(pair.value); }
    }.bind(this));
  },

  toElement: function() {
    var calCell = $(document.createElement('td'));
    this.addConditionalClasses(calCell);
    calCell.insert(this.date.getDate());
    calCell.observe('click', this.selectCallback);
    return calCell;
  }

});<commit_msg>initial refactoring of pagers to CalPager class<commit_after>Object.extend(Date.prototype, {

  clone: function(func) {
    date = new Date(this);
    func && func(date);
    return date;
  },

  succ: function() {
    return this.clone(function(date) {
      date.setDate(date.getDate() + 1);
    });
  },

  startOfMonth: function() {
    return this.clone(function(date) {
      date.setDate(1);
    });
  },

  endOfMonth: function() {
    return this.clone(function(date) {
      date.setDate(1);
      date.setMonth(date.getMonth() + 1);
      date.setDate(0);
    });
  },

  setDayOfWeek: function(dayIdx) {
    date.setDate(date.getDate() - date.getDay() + dayIdx);
  },

  startOfWeek: function() {
    return this.clone(function(date) {
      date.setDayOfWeek(0);
    });
  },

  endOfWeek: function() {
    return this.clone(function(date) {
      date.setDayOfWeek(6);
    });
  },

  monthNames: $w('January February March April May June July August September October November December'),
  getMonthName: function() {
    return this.monthNames[this.getMonth()];
  },

  toShortString: function() {
    var dd = this.getDate().toPaddedString(2);
    var mm = (this.getMonth() + 1).toPaddedString(2);
    var yy = this.getFullYear().toString().substr(2,2);
    return [ mm, dd, yy ].join('/');
  },

  sameDateAs: function(other) {
    return ((other instanceof Date) && (this.toShortString() == other.toShortString()));
  },

  isToday: function() {
    return this.sameDateAs(new Date());
  }

});

var TableSectionMethods = {
  addRow: function(tHead) {
    return $(tHead.appendChild(document.createElement('tr')));
  }
};
Element.addMethods('THEAD', TableSectionMethods);
Element.addMethods('TBODY', TableSectionMethods);

var CalSelect = Class.create({

  initialize: function(dateField) {
    this.dateField = $(dateField);
    this.initCalWrapper();
    this.initObservers();
  },

  initCalWrapper: function() {
    this.calWrapper = $(document.createElement('div'));
    this.calWrapper.addClassName('calendar');
    this.calWrapper.hide();
    this.dateField.insert({after: this.calWrapper});
  },

  initObservers: function() {
    this.dateField.observe('focus', this.show.bind(this));
    this.dateField.observe('keydown', function(event) {
      if (event.keyCode == Event.KEY_TAB) { this.hide(); }
    }.bindAsEventListener(this));

    document.observe('click', this.hide.bind(this));

    this.dateField.observe('click', Event.stop);
    this.calWrapper.observe('click', Event.stop);
  },

  show: function() {
    this.dateField.select();
    var selectedDate = this.getDate();
    var pageDate = selectedDate ? selectedDate.clone() : new Date();
    var calPage = new CalPage(pageDate, selectedDate, this.setDate.bind(this));
    this.calWrapper.update(calPage);
    this.setPosition();
    this.calWrapper.show();
  },

  setPosition: function() {
    var offset = this.dateField.positionedOffset();
    offset.top += this.dateField.getHeight();
    this.calWrapper.setStyle({left: offset.left+'px', top: offset.top+'px'});
  },

  hide: function() {
    this.calWrapper.hide();
  },

  getDate: function() {
    var dateStr = $F(this.dateField);
    var dateMatch = dateStr.match(/^\s*(\d{1,2})\/(\d{1,2})\/(\d{2}(\d{2})?)\s*$/);
    if (dateMatch) {
      var month = dateMatch[1] - 1;
      var day   = dateMatch[2];
      var year  = dateMatch[3];
      if (!dateMatch[4]) { year = '20' + year; }
      return new Date(year, month, day);
    } else {
      return null;
    }
  },

  setDate: function(date) {
    this.dateField.setValue(date.toShortString());
    this.hide();
  }

});

var CalPage = Class.create({

  initialize: function(pageDate, selectedDate, dateSelectCallback) {
    this.pageDate = pageDate.startOfMonth();
    this.selectedDate = selectedDate;
    this.dateSelectCallback = dateSelectCallback;
  },

  monthIdx: function() {
    return this.pageDate.getMonth();
  },

  toElement: function() {
    this.calTable = $(document.createElement('table'));
    var tHead = $(document.createElement('thead'));
    this.calTable.insert(tHead);

    this.calTable.tHead.insert(new CalMonthHeader(this.pageDate, this.advance.bind(this)));
    this.calTable.tHead.insert(new CalDayHeader());
    this.calTable.insert(new CalMonth(this));

    return this.calTable;
  },

  advance: function(months) {
    this.pageDate.setMonth(this.pageDate.getMonth() + months);
    this.calTable.replace(this);
  },

});

var CalMonthHeader = Class.create({

  initialize: function(date, pagerCallback) {
    this.pageDate = date;
    this.pagerCallback = pagerCallback;
  },

  toElement: function() {
    var tr = document.createElement('tr');

    tr.insert(new CalPager('left', this.pagerCallback));

    var month = $(document.createElement('th'));
    month.colSpan = 5;
    tr.insert(month);
    month.insert(this.pageDate.getMonthName() + ' ' + this.pageDate.getFullYear());

    tr.insert(new CalPager('right', this.pagerCallback));

    return tr;
  },

});

var CalPager = Class.create({

  initialize: function(direction, pagerCallback) {
    this.direction = direction.capitalize();
    this.pagerCallback = pagerCallback;
  },

  createLeftPager: function(tr) {
    return this.createPager(tr, '«', -1);
  },

  createRightPager: function(tr) {
    return this.createPager(tr, '»', 1);
  },

  createPager: function(tr, text, months) {
    var th = $(document.createElement('th'));
    th.addClassName('pager');
    th.insert(text);
    th.observe('click', this.pagerCallback.curry(months));
    return th
  },

  toElement: function() {
    return this['create'+this.direction+'Pager']();
  }

});

var CalDayHeader = Class.create({
  headers: $w('S M T W T F S'),
  toElement: function() {
    var row = document.createElement('tr')
    this.headers.each(function(day) {
      var cell = $(document.createElement('th'));
      row.insert(cell.insert(day));
    });
    return row;
  }
});

var CalMonth = Class.create({

  initialize: function(calPage) {
    this.calPage = calPage;
  },

  dateRange: function() {
    return $R(this.calPage.pageDate.startOfMonth().startOfWeek(),
      this.calPage.pageDate.endOfMonth().endOfWeek());
  },

  toElement: function() {
    var calBody = $(document.createElement('tbody'));
    var calRow;
    var calPage = this.calPage;

    this.dateRange().each(function(date) {
      if (date.getDay() == 0) { calRow = calBody.addRow(); }
      calRow.insert(new CalDate(date, calPage));
    });

    return calBody;
  }

});

var CalDate = Class.create({

  initialize: function(date, calPage) {
    this.date = date;
    this.calPage = calPage;
    this.selectCallback = calPage.dateSelectCallback.curry(date);

    this.isOtherMonth = (date.getMonth() != calPage.monthIdx());
    this.isSelected   = (date.sameDateAs(calPage.selectedDate));
    this.isToday      = (this.date.isToday());
  },

  cssClassMap: $H({isOtherMonth: 'other', isSelected: 'selected', isToday: 'today'}),
  addConditionalClasses: function(element) {
    this.cssClassMap.each(function(pair) {
      if (this[pair.key]) { element.addClassName(pair.value); }
    }.bind(this));
  },

  toElement: function() {
    var calCell = $(document.createElement('td'));
    this.addConditionalClasses(calCell);
    calCell.insert(this.date.getDate());
    calCell.observe('click', this.selectCallback);
    return calCell;
  }

});<|endoftext|>


<commit_before>var EBApp = require('../templates/ebapp')
    , EBOptionsSettings = require('../utils/eb-option-settings')
    , novaform = require('novaform');

function EBWorker(options) {
    if (!(this instanceof EBWorker)) {
        return new EBWorker(options);
    }

    options.optionSettings = options.optionSettings.concat(EBOptionsSettings({
        'aws:elasticbeanstalk:sqsd': {
            WorkerQueueURL: options.sqsUrl,
            HttpPath: options.httpPath,
        },
    }));

    EBApp.call(this, options);

    this.environment.properties.Tier = {
        Name: 'Worker',
        Type: 'SQS/HTTP',
        Version: '1.0',
    };
}
EBWorker.prototype = Object.create(EBApp.prototype);

module.exports = EBWorker;
<commit_msg>remove Version from EBWorker template<commit_after>var EBApp = require('../templates/ebapp')
    , EBOptionsSettings = require('../utils/eb-option-settings')
    , novaform = require('novaform');

function EBWorker(options) {
    if (!(this instanceof EBWorker)) {
        return new EBWorker(options);
    }

    options.optionSettings = options.optionSettings.concat(EBOptionsSettings({
        'aws:elasticbeanstalk:sqsd': {
            WorkerQueueURL: options.sqsUrl,
            HttpPath: options.httpPath,
        },
    }));

    EBApp.call(this, options);

    this.environment.properties.Tier = {
        Name: 'Worker',
        Type: 'SQS/HTTP',
    };
}
EBWorker.prototype = Object.create(EBApp.prototype);

module.exports = EBWorker;
<|endoftext|>


<commit_before>'use strict';

// Init the application configuration module for AngularJS application
var ApplicationConfiguration = (function() {
	// Init module configuration options
	var applicationModuleName = 'doomsday-clock';
	var applicationModuleVendorDependencies = ['ngResource', 'ngCookies',  'ngAnimate',  'ngTouch',  'ngSanitize',  'ui.router', 'ui.bootstrap', 'ui.utils'];

	// Add a new vertical module
	var registerModule = function(moduleName, dependencies) {
		// Create angular module
		angular.module(moduleName, dependencies || []);

		// Add the module to the AngularJS configuration file
		angular.module(applicationModuleName).requires.push(moduleName);
	};

	return {
		applicationModuleName: applicationModuleName,
		applicationModuleVendorDependencies: applicationModuleVendorDependencies,
		registerModule: registerModule
	};
})();<commit_msg>touch<commit_after>'use strict';

// Init the application configuration module for AngularJS application
var ApplicationConfiguration = (function() {
	// Init module configuration options
	var applicationModuleName = 'doomsday-clock';
	var applicationModuleVendorDependencies = ['ngResource', 'ngCookies',  'ngAnimate',  'ngTouch',  'ngSanitize',
    'ui.router', 'ui.bootstrap', 'ui.utils'];

	// Add a new vertical module
	var registerModule = function(moduleName, dependencies) {
		// Create angular module
		angular.module(moduleName, dependencies || []);

		// Add the module to the AngularJS configuration file
		angular.module(applicationModuleName).requires.push(moduleName);
	};

	return {
		applicationModuleName: applicationModuleName,
		applicationModuleVendorDependencies: applicationModuleVendorDependencies,
		registerModule: registerModule
	};
})();<|endoftext|>


<commit_before>//global services go here
angular.module( 'omniwallet' ).factory('userService', ['$rootScope', '$http', function ($rootScope, $http) {
  var service = {
    data: {
      walletKey: '',
      asymKey: {},
      wallet : {},
      loggedIn: false
    },

    login: function(wallet, walletKey, asymKey) {
      service.data.walletKey = walletKey;
      service.data.asymKey = asymKey;
      service.data.wallet = wallet;
      service.data.loggedIn = true;
    },

    logout: function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
    },

    addAddress: function( address, privKey ) {
      for( var i in service.data.wallet.addresses )
      {
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      }
      service.data.wallet.addresses.push( {
        "address": address,
        "privkey": privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
    },

    getAddress: function(address) {
      for(var i in service.data.wallet.addresses) {
        if(service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses: function () {
      return service.data.wallet.addresses;
    },

    getWallet: function() {
      return service.data.wallet;
    },

    getUUID: function() {
      return service.data.wallet.uuid;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    updateWallet: function() {
      var uuid = service.getUUID();
      return $http.get('/v1/user/wallet/challenge?uuid='+uuid)
        .then(function(result) {
          var data = result.data;
          var encryptedWallet = CryptUtil.encryptObject(service.data.wallet, service.data.walletKey);
          var challenge = data.challenge;
          var signature = ""

          return $http({
            url: '/v1/user/wallet/update',
            method: 'POST',
            data: { uuid: uuid, wallet: encryptedWallet, challenge: challenge, signature: signature }
          });
        });
    },

    saveSession: function () {
      service.updateWallet().then(function() { console.log("Success saving") });
    }
  };

  return service;
}]);

angular.module( 'omniwallet' ).factory( 'appraiser', ['$rootScope', '$http', function ( $rootScope, $http ) {

  function AppraiserService() {
    this.conversions = {};
    this.smartProperties = {};
    var self = this;
    function BtcUpdateLoop() {
      self.updateBtcValue( function() {
        setTimeout( BtcUpdateLoop, 30000 );
      } );
    }
    function MscUpdateLoop() {
      self.updateMscValue( function() {
        setTimeout( MscUpdateLoop, 600000 );
      } );
    }
    BtcUpdateLoop();
    MscUpdateLoop();
  };
  AppraiserService.prototype.updateBtcValue = function( callback ) {
    var self = this;
    $http.get( 'https://api.bitcoinaverage.com/all' ).then( function( result ) {
      // Store these things internally as the value of a satoshi.
      self.conversions.BTC = result.data.USD.averages.last / 100000000;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'BTC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.updateMscValue = function( callback ) {
    var self = this;
    $http.get( 'https://masterxchange.com/api/trades.php' ).then( function( result ) {
      var volume = 0;
      var sum = 0;

      for( var i=0; i<result.data.length; i++ )
      {
        volume += parseFloat( result.data[i].amount );
        sum += parseFloat( result.data[i].amount ) * parseFloat( result.data[i].price );
      }

      self.conversions.MSC = sum / volume;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'MSC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.getValue = function( amount, symbol ) {
    if( symbol == 'TMSC' )
      return 0;
    else if( symbol == 'BTC' )
    {
      if( this.conversions.BTC )
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    }
    else
    {
      if( this.conversions.hasOwnProperty(symbol) )
      {
        return this.getValue( this.conversions[symbol] * amount, 'BTC' );
      }
      else
        return symbol + ' Value Unavailable';
    }
  };

  return new AppraiserService();
}]);
<commit_msg>Add Smart Property Tokens update loop<commit_after>//global services go here
angular.module( 'omniwallet' ).factory('userService', ['$rootScope', '$http', function ($rootScope, $http) {
  var service = {
    data: {
      walletKey: '',
      asymKey: {},
      wallet : {},
      loggedIn: false
    },

    login: function(wallet, walletKey, asymKey) {
      service.data.walletKey = walletKey;
      service.data.asymKey = asymKey;
      service.data.wallet = wallet;
      service.data.loggedIn = true;
    },

    logout: function() {
      service.data.loggedIn = false;
      service.data.wallet = {}
    },

    addAddress: function( address, privKey ) {
      for( var i in service.data.wallet.addresses )
      {
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses[i].privkey = privKey;
          service.saveSession();
          return;
        }
      }
      service.data.wallet.addresses.push( {
        "address": address,
        "privkey": privKey
      });
      service.data.loggedIn = true;
      service.saveSession();
    },

    getAddress: function(address) {
      for(var i in service.data.wallet.addresses) {
        if(service.data.wallet.addresses[i].address == address) {
          return service.data.wallet.addresses[i];
        }
      }
    },

    getAllAddresses: function () {
      return service.data.wallet.addresses;
    },

    getWallet: function() {
      return service.data.wallet;
    },

    getUUID: function() {
      return service.data.wallet.uuid;
    },

    removeAddress: function( address ) {
      for( var i=0; i<service.data.wallet.addresses.length; i++ )
        if( service.data.wallet.addresses[i].address == address )
        {
          service.data.wallet.addresses.splice( i, 1 );
          service.saveSession();
          return;
        }
    },

    updateWallet: function() {
      var uuid = service.getUUID();
      return $http.get('/v1/user/wallet/challenge?uuid='+uuid)
        .then(function(result) {
          var data = result.data;
          var encryptedWallet = CryptUtil.encryptObject(service.data.wallet, service.data.walletKey);
          var challenge = data.challenge;
          var signature = ""

          return $http({
            url: '/v1/user/wallet/update',
            method: 'POST',
            data: { uuid: uuid, wallet: encryptedWallet, challenge: challenge, signature: signature }
          });
        });
    },

    saveSession: function () {
      service.updateWallet().then(function() { console.log("Success saving") });
    }
  };

  return service;
}]);

angular.module( 'omniwallet' ).factory( 'appraiser', ['$rootScope', '$http', function ( $rootScope, $http ) {

  function AppraiserService() {
    this.conversions = {};
    this.smartProperties = {};
    var self = this;
    function BtcUpdateLoop() {
      self.updateBtcValue( function() {
        setTimeout( BtcUpdateLoop, 30000 );
      } );
    }
    function MscUpdateLoop() {
      self.updateMscValue( function() {
        setTimeout( MscUpdateLoop, 600000 );
      } );
    }
    function SptUpdateLoop() {
      self.updateSptValue( function() {
        setTimeout( SptUpdateLoop, 600000 );
      } );
    }
    BtcUpdateLoop();
    MscUpdateLoop();
    SptUpdateLoop();
  };
  AppraiserService.prototype.updateBtcValue = function( callback ) {
    var self = this;
    $http.get( 'https://api.bitcoinaverage.com/all' ).then( function( result ) {
      // Store these things internally as the value of a satoshi.
      self.conversions.BTC = result.data.USD.averages.last / 100000000;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'BTC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.updateMscValue = function( callback ) {
    var self = this;
    $http.get( 'https://masterxchange.com/api/trades.php' ).then( function( result ) {
      var volume = 0;
      var sum = 0;

      for( var i=0; i<result.data.length; i++ )
      {
        volume += parseFloat( result.data[i].amount );
        sum += parseFloat( result.data[i].amount ) * parseFloat( result.data[i].price );
      }

      self.conversions.MSC = sum / volume;
      $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', 'MSC' );
      callback();
    }, function( error ) {
      console.log( error );
      callback();
    });
  };
  AppraiserService.prototype.updateSptValue = function( callback ) {
    var self = this;
    // Maybe use $q to call this using deferred?
    self.smartProperties.forEach(function(token,value){
        $http.post( '/v1/smartproperty/token', { 'token': token } ).success( function( result ) {
        // Return the rates of the token.
        self.conversions[token] = result.data.rate;
        $rootScope.$emit( 'APPRAISER_VALUE_CHANGED', token );
      }).error( function( error ) {
        console.log( error );
      });
    });
    callback();
  };
  AppraiserService.prototype.getValue = function( amount, symbol ) {
    if( symbol == 'TMSC' )
      return 0;
    else if( symbol == 'BTC' )
    {
      if( this.conversions.BTC )
        return this.conversions.BTC * amount;
      else
        return 'BTC Value Unavailable';
    }
    else
    {
      if( this.conversions.hasOwnProperty(symbol) )
      {
        return this.getValue( this.conversions[symbol] * amount, 'BTC' );
      }
      else
        return symbol + ' Value Unavailable';
    }
  };

  return new AppraiserService();
}]);
<|endoftext|>