<commit_before>const gulp = require('gulp'),
      eventStream = require('event-stream'),
      gulpLoadPlugins = require('gulp-load-plugins'),
      fs = require('fs'),
      del = require('del'),
      path = require('path'),
      size = require('gulp-size'),
      uri = require('urijs'),
      urljoin = require('url-join'),
      s = require('underscore.string'),
      stringifyObject = require('stringify-object'),
      argv = require('yargs').argv,
      hawtio = require('hawtio-node-backend');

const package = require('./package.json');
const plugins = gulpLoadPlugins({});

var config = {
  main: '.',
  ts: ['plugins/**/*.ts'],
  dist: argv.out || './dist/',
  js: 'hawtio-kubernetes-api.js',
  dts: 'hawtio-kubernetes-api.d.ts',
  sourceMap: argv.sourcemap
};

const tsProject = plugins.typescript.createProject('tsconfig.json');

var normalSizeOptions = {
    showFiles: true
}, gZippedSizeOptions  = {
    showFiles: true,
    gzip: true
};

gulp.task('tsc', function() {
    const tsResult = tsProject.src()
    .pipe(plugins.if(config.sourceMap, plugins.sourcemaps.init()))
    .pipe(tsProject())
    .on('error', plugins.notify.onError({
      onLast : true,
      message: '<%= error.message %>',
      title  : 'Typescript compilation error'
    }));

    return eventStream.merge(
      tsResult.js
        .pipe(plugins.ngAnnotate())
        .pipe(plugins.if(config.sourceMap, plugins.sourcemaps.write()))
        .pipe(gulp.dest('.')),
      tsResult.dts
        .pipe(plugins.rename(config.dts))
        .pipe(gulp.dest(config.dist)));
});

gulp.task('concat', ['tsc'], function() {
  var gZipSize = size(gZippedSizeOptions);
  return gulp.src(['compiled.js'])
    .pipe(plugins.concat(config.js))
    .pipe(size(normalSizeOptions))
    .pipe(gZipSize)
    .pipe(gulp.dest(config.dist));
});

gulp.task('clean', ['concat'], function() {
  return del(['compiled.js']);
});

gulp.task('watch', ['build'], function() {
  plugins.watch(['node_modules/**/*.js', 'index.html', config.dist + '/' + config.js], ['reload']);
  plugins.watch(['node_modules/**/*.d.ts', config.ts], ['tsc', 'template', 'concat', 'clean']);
});

gulp.task('connect', ['watch'], function() {
  // lets disable unauthorised TLS issues with kube REST API
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

  var kubeBase = process.env.KUBERNETES_MASTER || 'https://localhost:8443';
  var kube = uri(urljoin(kubeBase, 'api'));
  var oapi = uri(urljoin(kubeBase, 'oapi'));
  console.log("Connecting to Kubernetes on: " + kube);

  var staticAssets = [{
      path: '/',
      dir: '.'
  }];

  var localProxies = [];
  var defaultProxies = [{
    proto: kube.protocol(),
    port: kube.port(),
    hostname: kube.hostname(),
    path: '/kubernetes/api',
    targetPath: kube.path()
  }, {
    proto: oapi.protocol(),
    port: oapi.port(),
    hostname: oapi.hostname(),
    path: '/kubernetes/oapi',
    targetPath: oapi.path()
  }, {
    proto: kube.protocol(),
    hostname: kube.hostname(),
    port: kube.port(),
    path: '/jolokia',
    targetPath: '/hawtio/jolokia'
  }, {
    proto: kube.protocol(),
    hostname: kube.hostname(),
    port: kube.port(),
    path: '/git',
    targetPath: '/hawtio/git'
  }];

  var staticProxies = localProxies.concat(defaultProxies);

  hawtio.setConfig({
    port: process.env.DEV_PORT || 2772,
    staticProxies: staticProxies,
    staticAssets: staticAssets,
    fallback: 'index.html',
    liveReload: {
      enabled: true
    }
  });
  var debugLoggingOfProxy = process.env.DEBUG_PROXY === "true";
  var useAuthentication = process.env.DISABLE_OAUTH !== "true";

  var googleClientId = process.env.GOOGLE_OAUTH_CLIENT_ID;
  var googleClientSecret = process.env.GOOGLE_OAUTH_CLIENT_SECRET;

  hawtio.use('/osconsole/config.js', function(req, res, next) {
    var config = {
      api: {
        openshift: {
          proto: oapi.protocol(),
          hostPort: oapi.host(),
          prefix: oapi.path()
        },
        k8s: {
          proto: kube.protocol(),
          hostPort: kube.host(),
          prefix: kube.path()
        }
      }
    };
    if (googleClientId && googleClientSecret) {
      config.master_uri = kubeBase;
      config.google = {
         clientId: googleClientId,
         clientSecret: googleClientSecret,
         authenticationURI: "https://accounts.google.com/o/oauth2/auth",
         authorizationURI: "https://accounts.google.com/o/oauth2/auth",
         scope: "profile",
         redirectURI: "http://localhost:9000"
      };

    } else if (useAuthentication) {
      config.master_uri = kubeBase;
      config.openshift = {
        oauth_authorize_uri: urljoin(kubeBase, '/oauth/authorize'),
        oauth_client_id    : 'system:serviceaccount:hawtio:hawtio-online-dev',
        scope              : 'user:info user:check-access role:edit:hawtio',
      };
    }
    var answer = "window.OPENSHIFT_CONFIG = window.HAWTIO_OAUTH_CONFIG = " + stringifyObject(config);
    res.set('Content-Type', 'application/javascript');
    res.send(answer);
  });

  hawtio.use('/', function(req, res, next) {
          var path = req.originalUrl;
          // avoid returning these files, they should get pulled from js
          if (s.startsWith(path, '/plugins/') && s.endsWith(path, 'html')) {
            console.log("returning 404 for: ", path);
            res.statusCode = 404;
            res.end();
          } else {
            if (debugLoggingOfProxy) {
              console.log("allowing: ", path);
            }
            next();
          }
        });
  hawtio.listen(function(server) {
    var host = server.address().address;
    var port = server.address().port;
    console.log("started from gulp file at ", host, ":", port);
  });
});

gulp.task('reload', function() {
  gulp.src('.')
    .pipe(hawtio.reload());
});

gulp.task('version', ['concat'], function() {
  return gulp.src(path.join(config.dist, config.js))
    .pipe(plugins.replace('PACKAGE_VERSION_PLACEHOLDER', package.version))
    .pipe(gulp.dest(config.dist));
});

gulp.task('build', ['tsc', 'concat', 'version', 'clean']);

gulp.task('default', ['connect']);
<commit_msg>build: Only update product version on version publish<commit_after>const gulp = require('gulp'),
      eventStream = require('event-stream'),
      gulpLoadPlugins = require('gulp-load-plugins'),
      fs = require('fs'),
      del = require('del'),
      path = require('path'),
      size = require('gulp-size'),
      uri = require('urijs'),
      urljoin = require('url-join'),
      s = require('underscore.string'),
      stringifyObject = require('stringify-object'),
      argv = require('yargs').argv,
      hawtio = require('hawtio-node-backend');

const package = require('./package.json');
const plugins = gulpLoadPlugins({});

var config = {
  main: '.',
  ts: ['plugins/**/*.ts'],
  dist: argv.out || './dist/',
  js: 'hawtio-kubernetes-api.js',
  dts: 'hawtio-kubernetes-api.d.ts',
  sourceMap: argv.sourcemap
};

const tsProject = plugins.typescript.createProject('tsconfig.json');

var normalSizeOptions = {
    showFiles: true
}, gZippedSizeOptions  = {
    showFiles: true,
    gzip: true
};

gulp.task('tsc', function() {
    const tsResult = tsProject.src()
    .pipe(plugins.if(config.sourceMap, plugins.sourcemaps.init()))
    .pipe(tsProject())
    .on('error', plugins.notify.onError({
      onLast : true,
      message: '<%= error.message %>',
      title  : 'Typescript compilation error'
    }));

    return eventStream.merge(
      tsResult.js
        .pipe(plugins.ngAnnotate())
        .pipe(plugins.if(config.sourceMap, plugins.sourcemaps.write()))
        .pipe(gulp.dest('.')),
      tsResult.dts
        .pipe(plugins.rename(config.dts))
        .pipe(gulp.dest(config.dist)));
});

gulp.task('concat', ['tsc'], function() {
  var gZipSize = size(gZippedSizeOptions);
  return gulp.src(['compiled.js'])
    .pipe(plugins.concat(config.js))
    .pipe(size(normalSizeOptions))
    .pipe(gZipSize)
    .pipe(gulp.dest(config.dist));
});

gulp.task('clean', ['concat'], function() {
  return del(['compiled.js']);
});

gulp.task('watch', ['build'], function() {
  plugins.watch(['node_modules/**/*.js', 'index.html', config.dist + '/' + config.js], ['reload']);
  plugins.watch(['node_modules/**/*.d.ts', config.ts], ['tsc', 'template', 'concat', 'clean']);
});

gulp.task('connect', ['watch'], function() {
  // lets disable unauthorised TLS issues with kube REST API
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

  var kubeBase = process.env.KUBERNETES_MASTER || 'https://localhost:8443';
  var kube = uri(urljoin(kubeBase, 'api'));
  var oapi = uri(urljoin(kubeBase, 'oapi'));
  console.log("Connecting to Kubernetes on: " + kube);

  var staticAssets = [{
      path: '/',
      dir: '.'
  }];

  var localProxies = [];
  var defaultProxies = [{
    proto: kube.protocol(),
    port: kube.port(),
    hostname: kube.hostname(),
    path: '/kubernetes/api',
    targetPath: kube.path()
  }, {
    proto: oapi.protocol(),
    port: oapi.port(),
    hostname: oapi.hostname(),
    path: '/kubernetes/oapi',
    targetPath: oapi.path()
  }, {
    proto: kube.protocol(),
    hostname: kube.hostname(),
    port: kube.port(),
    path: '/jolokia',
    targetPath: '/hawtio/jolokia'
  }, {
    proto: kube.protocol(),
    hostname: kube.hostname(),
    port: kube.port(),
    path: '/git',
    targetPath: '/hawtio/git'
  }];

  var staticProxies = localProxies.concat(defaultProxies);

  hawtio.setConfig({
    port: process.env.DEV_PORT || 2772,
    staticProxies: staticProxies,
    staticAssets: staticAssets,
    fallback: 'index.html',
    liveReload: {
      enabled: true
    }
  });
  var debugLoggingOfProxy = process.env.DEBUG_PROXY === "true";
  var useAuthentication = process.env.DISABLE_OAUTH !== "true";

  var googleClientId = process.env.GOOGLE_OAUTH_CLIENT_ID;
  var googleClientSecret = process.env.GOOGLE_OAUTH_CLIENT_SECRET;

  hawtio.use('/osconsole/config.js', function(req, res, next) {
    var config = {
      api: {
        openshift: {
          proto: oapi.protocol(),
          hostPort: oapi.host(),
          prefix: oapi.path()
        },
        k8s: {
          proto: kube.protocol(),
          hostPort: kube.host(),
          prefix: kube.path()
        }
      }
    };
    if (googleClientId && googleClientSecret) {
      config.master_uri = kubeBase;
      config.google = {
         clientId: googleClientId,
         clientSecret: googleClientSecret,
         authenticationURI: "https://accounts.google.com/o/oauth2/auth",
         authorizationURI: "https://accounts.google.com/o/oauth2/auth",
         scope: "profile",
         redirectURI: "http://localhost:9000"
      };

    } else if (useAuthentication) {
      config.master_uri = kubeBase;
      config.openshift = {
        oauth_authorize_uri: urljoin(kubeBase, '/oauth/authorize'),
        oauth_client_id    : 'system:serviceaccount:hawtio:hawtio-online-dev',
        scope              : 'user:info user:check-access role:edit:hawtio',
      };
    }
    var answer = "window.OPENSHIFT_CONFIG = window.HAWTIO_OAUTH_CONFIG = " + stringifyObject(config);
    res.set('Content-Type', 'application/javascript');
    res.send(answer);
  });

  hawtio.use('/', function(req, res, next) {
          var path = req.originalUrl;
          // avoid returning these files, they should get pulled from js
          if (s.startsWith(path, '/plugins/') && s.endsWith(path, 'html')) {
            console.log("returning 404 for: ", path);
            res.statusCode = 404;
            res.end();
          } else {
            if (debugLoggingOfProxy) {
              console.log("allowing: ", path);
            }
            next();
          }
        });
  hawtio.listen(function(server) {
    var host = server.address().address;
    var port = server.address().port;
    console.log("started from gulp file at ", host, ":", port);
  });
});

gulp.task('reload', function() {
  gulp.src('.')
    .pipe(hawtio.reload());
});

gulp.task('version', function() {
  return gulp.src(path.join(config.dist, config.js))
    .pipe(plugins.replace('PACKAGE_VERSION_PLACEHOLDER', package.version))
    .pipe(gulp.dest(config.dist));
});

gulp.task('build', ['tsc', 'concat', 'clean']);

gulp.task('default', ['connect']);
<|endoftext|>


<commit_before>export const DICTIONARY = {
  hc: "Headcount Ratio",
  povgap: "Poverty Gap Ratio",
  ppp1: "$1.90/day (PPP)",
  ppp2: "$3.10/day (PPP)",
  rainfall_awa_mm: "Average Annual Rainfall",
  sevpov: "Poverty Severity Ratio",
  stunted: "Stunted",
  underweight: "Underweight",
  wasted: "Wasted"
};
<commit_msg>add ppp year to label. closes #5.<commit_after>export const DICTIONARY = {
  hc: "Headcount Ratio",
  povgap: "Poverty Gap Ratio",
  ppp1: "$1.90/day (2011 PPP)",
  ppp2: "$3.10/day (2011 PPP)",
  rainfall_awa_mm: "Average Annual Rainfall",
  sevpov: "Poverty Severity Ratio",
  stunted: "Stunted",
  underweight: "Underweight",
  wasted: "Wasted"
};
<|endoftext|>


<commit_before>(function (window, undefined) {
    var document = window.document;

    function ready(callback) {

        if (typeof callback !== 'function') {
            return;
        }

        var isReady = false;

        function fire() {
            isReady = true;
            callback();
        }

        function completed() {
            // readyState === "complete" is good enough for us to call the dom ready in oldIE
            if (document.addEventListener || event.type === 'load' || document.readyState === 'complete') {
                detach();
                fire();
            }
        }

        function detach() {
            if (document.addEventListener) {
                document.removeEventListener('DOMContentLoaded', completed, false);
                window.removeEventListener('load', completed, false);
            } else {
                document.detachEvent('onreadystatechange', completed);
                window.detachEvent('onload', completed);
            }
        }

        // already loaded when comes here
        if (document.readyState === 'complete') {
            fire();
        } else if (document.addEventListener) {
            // Use the handy event callback
            document.addEventListener('DOMContentLoaded', completed, false);
            // A fallback to window.onload, that will always work
            window.addEventListener('load', completed, false);
        } else { // IE
            // Ensure firing before onload, maybe late but safe also for iframes
            document.attachEvent('onreadystatechange', completed);
            // A fallback to window.onload, that will always work
            window.attachEvent('onload', completed);

            // If IE and not a frame
            // continually check to see if the document is ready
            var top = false;

            try {
                top = window.frameElement == null && document.documentElement;
            } catch (e) {}

            if (top && top.doScroll) {
                (function doScrollCheck() {
                    if (isReady) {

                        try {
                            top.doScroll('left');
                        } catch (e) {
                            return setTimeout(doScrollCheck, 50);
                        }
                        detach();
                        fire();
                    }
                })();
            }
        }
    }

    function detect() {
        var root = document.getElementById('wrapper'),
            spliter = '.',
            children;

        root = root.firstChild;
        while (root && root.className !== 'post') {
            root = root.nextSibling;
        }
        root = root.firstChild;
        while (root && root.className !== 'post-content') {
            root = root.nextSibling;
        }
        root = root.firstChild;
        while (root && root.className !== 'entry') {
            root = root.nextSibling;
        }
        if (!root || !(children = root.childNodes)) {
            return;
        }

        var i = 0,
            len = children.length,
            level2 = 0,
            level3 = 0,
            level4 = 0,
            level5 = 0,
            level6 = 0,
            elem,
            titles = [];
        for (; i < len; i++) {
            elem = children[i];
            if (elem.nodeType !== 1) {
                continue;
            }
            elem.tagName.replace(/h([23456])/i, function (input, level) {
                var text = elem.innerText || elem.textContent,
                    matches,
                    link,
                    title;
                level = parseInt(level);
                title = {
                    level: level,
                    text: text
                };
                switch (level) {
                    case 2:
                        level2++;
                        level3 = 0;
                        level4 = 0;
                        level5 = 0;
                        level6 = 0;
                        title.prefix = level2 + spliter;
                        break;
                    case 3:
                        level3++;
                        level4 = 0;
                        level5 = 0;
                        level6 = 0;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + level3 + spliter;
                        break;
                    case 4:
                        level4++;
                        level5 = 0;
                        level6 = 0;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + (level3 === 0 ? '' : level3 + spliter) + level4 + spliter;
                        break;
                    case 5:
                        level5++;
                        level6 = 0;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + (level3 === 0 ? '' : level3 + spliter) + (level4 === 0 ? '' : level4 + spliter) + level5 + spliter;
                        break;
                    case 6:
                        level6++;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + (level3 === 0 ? '' : level3 + spliter) + (level4 === 0 ? '' : level4 + spliter) + (level5 === 0 ? '' : level5 + spliter) + level6 + spliter;
                        break;
                    default:
                        break;
                }
                matches = text.match(/([a-z-A-Z]+)/g);
                if (!matches) {
                    link = title.prefix.replace(/\./g, '-');
                    link = 'i-' + link.substr(0, link.length - 1);
                } else {
                    link = title.prefix.replace(/\./g, '-') + matches.join('-');
                }
                title.text = text;
                title.level = level;
                title.link = link;
                //                title.link = title.prefix + elem.getAttribute('id');
                titles.push(title);
                elem.setAttribute('id', title.link);
            });
        }
        createTree(titles);

    }

    function createTree(titles) {
        var buffer = '',
            container = document.getElementById('topic-list'),
            title,
            level,
            lastLevel = 0,
            nextLevel,
            i = 0,
            len = titles.length;
        if (len) {
            for (; i < len; i++) {
                title = titles[i];
                level = title.level;
                nextLevel = i + 1 < len ? titles[i + 1].level : 0;
                if (level > lastLevel) {
                    buffer += '
\n';
                }
                buffer += '
' + title.prefix + '' + title.text + '
\n';
                if (level > nextLevel) {
                    buffer += '
\n';
                }
                if (level === 2) {
                    lastLevel = 2;
                } else {
                    lastLevel = level;
                }
            }
            container = container.firstChild;
            while (container) {
                if (container.nodeType === 1 && container.tagName.toLocaleLowerCase() === 'div') {
                    break;
                } else {
                    container = container.nextSibling;
                }
            }
            container.innerHTML = buffer;

        } else {
            if (container) {
                container.parentNode.removeChild(container);
            }
        }

    }

    ready(function () {
        detect();

        var elem = $('#topic-list'),
            nativeSpy,
            ghostSpy;

        if (elem && elem.length) {

            sticky(elem, {
                top: 30
            }, function (sticky) {

                if (sticky) {
                    // startSticky
                    if (nativeSpy) {
                        nativeSpy.destroy();
                        nativeSpy = null;
                    }
                    ghostSpy = scrollSpy(this.ghost.find('.topic-tree'));
                } else {
                    // stopSticky
                    if (ghostSpy) {
                        ghostSpy.destroy();
                        ghostSpy = null;
                    }
                    nativeSpy = scrollSpy($('#topic-list').find('.topic-tree'));
                }
            });
        }

    });

})(window);<commit_msg>bugfix: images lazy loading<commit_after>(function (window, undefined) {
    var document = window.document;

    function ready(callback) {

        if (typeof callback !== 'function') {
            return;
        }

        var isReady = false;

        function fire() {
            isReady = true;
            callback();
        }

        function completed() {
            // readyState === "complete" is good enough for us to call the dom ready in oldIE
            if (document.addEventListener || event.type === 'load' || document.readyState === 'complete') {
                detach();
                fire();
            }
        }

        function detach() {
            if (document.addEventListener) {
                document.removeEventListener('DOMContentLoaded', completed, false);
                window.removeEventListener('load', completed, false);
            } else {
                document.detachEvent('onreadystatechange', completed);
                window.detachEvent('onload', completed);
            }
        }

        // already loaded when comes here
        if (document.readyState === 'complete') {
            fire();
        } else if (document.addEventListener) {
            // Use the handy event callback
            document.addEventListener('DOMContentLoaded', completed, false);
            // A fallback to window.onload, that will always work
            window.addEventListener('load', completed, false);
        } else { // IE
            // Ensure firing before onload, maybe late but safe also for iframes
            document.attachEvent('onreadystatechange', completed);
            // A fallback to window.onload, that will always work
            window.attachEvent('onload', completed);

            // If IE and not a frame
            // continually check to see if the document is ready
            var top = false;

            try {
                top = window.frameElement == null && document.documentElement;
            } catch (e) {}

            if (top && top.doScroll) {
                (function doScrollCheck() {
                    if (isReady) {

                        try {
                            top.doScroll('left');
                        } catch (e) {
                            return setTimeout(doScrollCheck, 50);
                        }
                        detach();
                        fire();
                    }
                })();
            }
        }
    }

    function detect() {
        var root = document.getElementById('wrapper'),
            spliter = '.',
            children;

        root = root.firstChild;
        while (root && root.className !== 'post') {
            root = root.nextSibling;
        }
        root = root.firstChild;
        while (root && root.className !== 'post-content') {
            root = root.nextSibling;
        }
        root = root.firstChild;
        while (root && root.className !== 'entry') {
            root = root.nextSibling;
        }
        if (!root || !(children = root.childNodes)) {
            return;
        }

        var i = 0,
            len = children.length,
            level2 = 0,
            level3 = 0,
            level4 = 0,
            level5 = 0,
            level6 = 0,
            elem,
            titles = [];
        for (; i < len; i++) {
            elem = children[i];
            if (elem.nodeType !== 1) {
                continue;
            }
            elem.tagName.replace(/h([23456])/i, function (input, level) {
                var text = elem.innerText || elem.textContent,
                    matches,
                    link,
                    title;
                level = parseInt(level);
                title = {
                    level: level,
                    text: text
                };
                switch (level) {
                    case 2:
                        level2++;
                        level3 = 0;
                        level4 = 0;
                        level5 = 0;
                        level6 = 0;
                        title.prefix = level2 + spliter;
                        break;
                    case 3:
                        level3++;
                        level4 = 0;
                        level5 = 0;
                        level6 = 0;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + level3 + spliter;
                        break;
                    case 4:
                        level4++;
                        level5 = 0;
                        level6 = 0;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + (level3 === 0 ? '' : level3 + spliter) + level4 + spliter;
                        break;
                    case 5:
                        level5++;
                        level6 = 0;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + (level3 === 0 ? '' : level3 + spliter) + (level4 === 0 ? '' : level4 + spliter) + level5 + spliter;
                        break;
                    case 6:
                        level6++;
                        title.prefix = (level2 === 0 ? '' : level2 + spliter) + (level3 === 0 ? '' : level3 + spliter) + (level4 === 0 ? '' : level4 + spliter) + (level5 === 0 ? '' : level5 + spliter) + level6 + spliter;
                        break;
                    default:
                        break;
                }
                matches = text.match(/([a-z-A-Z]+)/g);
                if (!matches) {
                    link = title.prefix.replace(/\./g, '-');
                    link = 'i-' + link.substr(0, link.length - 1);
                } else {
                    link = title.prefix.replace(/\./g, '-') + matches.join('-');
                }
                title.text = text;
                title.level = level;
                title.link = link;
                //                title.link = title.prefix + elem.getAttribute('id');
                titles.push(title);
                elem.setAttribute('id', title.link);
            });
        }
        createTree(titles);

    }

    function createTree(titles) {
        var buffer = '',
            container = document.getElementById('topic-list'),
            title,
            level,
            lastLevel = 0,
            nextLevel,
            i = 0,
            len = titles.length;
        if (len) {
            for (; i < len; i++) {
                title = titles[i];
                level = title.level;
                nextLevel = i + 1 < len ? titles[i + 1].level : 0;
                if (level > lastLevel) {
                    buffer += '
\n';
                }
                buffer += '
' + title.prefix + '' + title.text + '
\n';
                if (level > nextLevel) {
                    buffer += '
\n';
                }
                if (level === 2) {
                    lastLevel = 2;
                } else {
                    lastLevel = level;
                }
            }
            container = container.firstChild;
            while (container) {
                if (container.nodeType === 1 && container.tagName.toLocaleLowerCase() === 'div') {
                    break;
                } else {
                    container = container.nextSibling;
                }
            }
            container.innerHTML = buffer;

        } else {
            if (container) {
                container.parentNode.removeChild(container);
            }
        }

    }

    ready(function () {
        detect();

        var elem = $('#topic-list'),
            oldLoad,
            stick,
            nativeSpy,
            ghostSpy;

        if (elem && elem.length) {

            stick = sticky(elem, {
                top: 30
            }, function (sticky) {

                if (sticky) {
                    // startSticky
                    if (nativeSpy) {
                        nativeSpy.destroy();
                        nativeSpy = null;
                    }
                    ghostSpy = scrollSpy(this.ghost.find('.topic-tree'));
                } else {
                    // stopSticky
                    if (ghostSpy) {
                        ghostSpy.destroy();
                        ghostSpy = null;
                    }
                    nativeSpy = scrollSpy($('#topic-list').find('.topic-tree'));
                }
            });

            oldLoad = window.onload;
            window.onload = function () {
                stick.adjust();
                if (oldLoad) {
                    oldLoad();
                }
            };

        }

    });

})(window);<|endoftext|>


<commit_before>var gulp = require('gulp');
var gulpLoadPlugins = require('gulp-load-plugins');
var browserSync = require('browser-sync');
var del = require('del');
var fs = require('fs');
var git = require('git-rev-sync');
var tryFn = require('nice-try');
var saveLicense = require('uglify-save-license');

var $ = gulpLoadPlugins();
var reload = browserSync.reload;

gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

gulp.task('lint', function () {
    return gulp.src([
        'src/scripts/**/*.js'
    ]).pipe(reload({stream: true, once: true}))
        .pipe($.eslint.format())
        .pipe($.if(!browserSync.active, $.eslint.failAfterError()))
        .pipe(gulp.dest('src/scripts'));
});

gulp.task('prepare-fonts', function () {
    return gulp.src([
        'node_modules/font-awesome/fonts/fontawesome-webfont.*'
    ]).pipe(gulp.dest('.tmp/fonts'));
});

gulp.task('process-fonts', ['prepare-fonts'], function () {
    return gulp.src([
        '.tmp/fonts/**/*'
    ]).pipe(gulp.dest('dist/fonts'));
});

gulp.task('prepare-langs', function () {
    return gulp.src([
        'src/langs/**/*'
    ]).pipe(gulp.dest('.tmp/langs'));
});

gulp.task('process-langs', ['prepare-langs'], function () {
    return gulp.src([
        '.tmp/langs/**/*'
    ]).pipe(gulp.dest('dist/langs'));
});

gulp.task('prepare-styles', function () {
    return gulp.src([
        'src/styles/**/*.css'
    ]).pipe($.autoprefixer({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']}))
        .pipe(gulp.dest('.tmp/styles'))
        .pipe(reload({stream: true}));
});

gulp.task('prepare-scripts', function () {
    return gulp.src([
        'src/scripts/**/*.js'
    ]).pipe($.plumber())
        .pipe($.injectVersion({replace: '${ARIANG_VERSION}'}))
        .pipe($.replace(/\${ARIANG_BUILD_COMMIT}/g, tryFn(git.short) || 'Local'))
        .pipe(gulp.dest('.tmp/scripts'))
        .pipe(reload({stream: true}));
});

gulp.task('prepare-views', function () {
    return gulp.src([
        'src/views/**/*.html'
    ]).pipe($.htmlmin({collapseWhitespace: true}))
        .pipe($.angularTemplatecache({module: 'ariaNg', filename: 'views/templates.js', root: 'views/'}))
        .pipe(gulp.dest('.tmp/scripts'));
});

gulp.task('prepare-html', ['prepare-styles', 'prepare-scripts', 'prepare-views'], function () {
    return gulp.src([
        'src/*.html'
    ]).pipe($.useref({searchPath: ['.tmp', 'src', '.']}))
        .pipe($.if('js/*.js', $.replace(/\/\/# sourceMappingURL=.*/g, '')))
        .pipe($.if('css/*.css', $.replace(/\/\*# sourceMappingURL=.* \*\/$/g, '')))
        .pipe($.if(['js/moment-with-locales-*.min.js', 'js/plugins.min.js', 'js/aria-ng.min.js'], $.uglify({output: {comments: saveLicense}})))
        .pipe($.if(['css/plugins.min.css', 'css/aria-ng.min.css'], $.cssnano({safe: true, autoprefixer: false})))
        .pipe($.if(['js/plugins.min.js', 'js/aria-ng.min.js', 'css/plugins.min.css', 'css/aria-ng.min.css'], $.rev()))
        .pipe($.if('*.html', $.htmlmin({collapseWhitespace: true})))
        .pipe($.revReplace())
        .pipe(gulp.dest('.tmp'));
});

gulp.task('process-html', ['prepare-html'], function () {
    return gulp.src([
        '.tmp/*.html'
    ]).pipe($.replace(/<!-- AriaNg-Bundle:\w+ -->/, ''))
        .pipe(gulp.dest('dist'));
});

gulp.task('process-assets', ['process-html'], function () {
    return gulp.src([
        '.tmp/css/**/*',
        '.tmp/js/**/*'
    ],{ base: '.tmp' })
        .pipe(gulp.dest('dist'));
});

gulp.task('process-assets-bundle', ['prepare-fonts', 'prepare-langs', 'prepare-html'], function () {
    return gulp.src('.tmp/index.html')
        .pipe($.replace(/<link rel="stylesheet" href="(css\/[a-zA-Z0-9\-_.]+\.css)">/g, function(match, fileName) {
            var content = fs.readFileSync('.tmp/' + fileName, 'utf8');
            return '<style type="text/css">' + content + '</style>';
        }))
        .pipe($.replace(/<script src="(js\/[a-zA-Z0-9\-_.]+\.js)"><\/script>/g, function(match, fileName) {
            var content = fs.readFileSync('.tmp/' + fileName, 'utf8');
            return '<script type="application/javascript">' + content + '</script>';
        }))
        .pipe($.replace(/url\(\.\.\/(fonts\/[a-zA-Z0-9\-]+\.woff)(\?[a-zA-Z0-9\-_=.]+)?\)/g, function(match, fileName) {
            if (!fs.existsSync('.tmp/' + fileName)) {
                return match;
            }

            var contentBuffer = fs.readFileSync('.tmp/' + fileName);
            var contentBase64 = contentBuffer.toString('base64');
            return 'url(data:application/x-font-woff;base64,' + contentBase64 + ')';
        }))
        .pipe($.replace('<!-- AriaNg-Bundle:languages -->', function() {
            var langDir = '.tmp/langs/';
            var result = '';
            var fileNames = fs.readdirSync(langDir, 'utf8');

            if (fileNames.length > 0) {
                result = '<script type="application/javascript">' +
                    'angular.module("ariaNg").config(["ariaNgAssetsCacheServiceProvider",function(e){';

                for (var i = 0; i < fileNames.length; i++) {
                    var fileName = fileNames[i];
                    var content = fs.readFileSync(langDir + fileName, 'utf8');

                    var lastPointIndex = fileName.lastIndexOf('.');
                    var languageName = fileName.substr(0, lastPointIndex);

                    content = content.replace(/\\/g, '\\\\');
                    content = content.replace(/\r/g, '');
                    content = content.replace(/\n/g, '\\n');
                    content = content.replace(/"/g, '\\"');
                    result += 'e.setLanguageAsset(\'' + languageName + '\',"' + content + '");';
                }

                result += '}]);</script>';
            }

            return result;
        }))
        .pipe($.replace(/<[a-z]+( [a-z\-]+="[a-zA-Z0-9\- ]+")* [a-z\-]+="((favicon.ico)|(favicon.png)|(tileicon.png)|(touchicon.png))"\/?>/g, ''))
        .pipe(gulp.dest('dist'));
});

gulp.task('process-manifest', function () {
    return gulp.src([
        'dist/css/**',
        'dist/js/**',
        'dist/fonts/fontawesome-webfont.woff2',
        'dist/*.html',
        'dist/*.ico',
        'dist/*.png'
    ], {base: 'dist/'})
        .pipe($.manifest({
            hash: true,
            preferOnline: true,
            network: ['*'],
            filename: 'index.manifest',
            exclude: 'index.manifest'
        }))
        .pipe(gulp.dest('dist'));
});

gulp.task('process-full-extras', function () {
    return gulp.src([
        'LICENSE',
        'src/*.*',
        '!src/*.html'
    ], {
        dot: true
    }).pipe(gulp.dest('dist'));
});

gulp.task('process-tiny-extras', function () {
    return gulp.src([
        'LICENSE'
    ]).pipe(gulp.dest('dist'));
});

gulp.task('info', function () {
    return gulp.src([
        'dist/**/*'
    ]).pipe($.size({title: 'build', gzip: true}));
});

gulp.task('build', $.sequence('lint', 'process-fonts', 'process-langs', 'process-assets', 'process-manifest', 'process-full-extras', 'info'));

gulp.task('build-bundle', $.sequence('lint', 'process-assets-bundle', 'process-tiny-extras', 'info'));

gulp.task('serve', ['prepare-styles', 'prepare-scripts', 'prepare-fonts'], function () {
    browserSync({
        notify: false,
        port: 9000,
        server: {
            baseDir: ['.tmp', 'src'],
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    });

    gulp.watch([
        'src/*.html',
        'src/*.ico',
        'src/*.png',
        'src/langs/*.txt',
        'src/views/*.html',
        'src/imgs/**/*',
        '.tmp/fonts/**/*'
    ]).on('change', reload);

    gulp.watch('src/styles/**/*.css', ['prepare-styles']);
    gulp.watch('src/scripts/**/*.js', ['prepare-scripts']);
    gulp.watch('src/fonts/**/*', ['prepare-fonts']);
});

gulp.task('serve:dist', function () {
    browserSync({
        notify: false,
        port: 9000,
        server: {
            baseDir: ['dist']
        }
    });
});

gulp.task('default', ['clean'], function () {
    gulp.start('build');
});
<commit_msg>remove version of woff2 file<commit_after>var gulp = require('gulp');
var gulpLoadPlugins = require('gulp-load-plugins');
var browserSync = require('browser-sync');
var del = require('del');
var fs = require('fs');
var git = require('git-rev-sync');
var tryFn = require('nice-try');
var saveLicense = require('uglify-save-license');

var $ = gulpLoadPlugins();
var reload = browserSync.reload;

gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

gulp.task('lint', function () {
    return gulp.src([
        'src/scripts/**/*.js'
    ]).pipe(reload({stream: true, once: true}))
        .pipe($.eslint.format())
        .pipe($.if(!browserSync.active, $.eslint.failAfterError()))
        .pipe(gulp.dest('src/scripts'));
});

gulp.task('prepare-fonts', function () {
    return gulp.src([
        'node_modules/font-awesome/fonts/fontawesome-webfont.*'
    ]).pipe(gulp.dest('.tmp/fonts'));
});

gulp.task('process-fonts', ['prepare-fonts'], function () {
    return gulp.src([
        '.tmp/fonts/**/*'
    ]).pipe(gulp.dest('dist/fonts'));
});

gulp.task('prepare-langs', function () {
    return gulp.src([
        'src/langs/**/*'
    ]).pipe(gulp.dest('.tmp/langs'));
});

gulp.task('process-langs', ['prepare-langs'], function () {
    return gulp.src([
        '.tmp/langs/**/*'
    ]).pipe(gulp.dest('dist/langs'));
});

gulp.task('prepare-styles', function () {
    return gulp.src([
        'src/styles/**/*.css'
    ]).pipe($.autoprefixer({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']}))
        .pipe(gulp.dest('.tmp/styles'))
        .pipe(reload({stream: true}));
});

gulp.task('prepare-scripts', function () {
    return gulp.src([
        'src/scripts/**/*.js'
    ]).pipe($.plumber())
        .pipe($.injectVersion({replace: '${ARIANG_VERSION}'}))
        .pipe($.replace(/\${ARIANG_BUILD_COMMIT}/g, tryFn(git.short) || 'Local'))
        .pipe(gulp.dest('.tmp/scripts'))
        .pipe(reload({stream: true}));
});

gulp.task('prepare-views', function () {
    return gulp.src([
        'src/views/**/*.html'
    ]).pipe($.htmlmin({collapseWhitespace: true}))
        .pipe($.angularTemplatecache({module: 'ariaNg', filename: 'views/templates.js', root: 'views/'}))
        .pipe(gulp.dest('.tmp/scripts'));
});

gulp.task('prepare-html', ['prepare-styles', 'prepare-scripts', 'prepare-views'], function () {
    return gulp.src([
        'src/*.html'
    ]).pipe($.useref({searchPath: ['.tmp', 'src', '.']}))
        .pipe($.if('js/*.js', $.replace(/\/\/# sourceMappingURL=.*/g, '')))
        .pipe($.if('css/*.css', $.replace(/\/\*# sourceMappingURL=.* \*\/$/g, '')))
        .pipe($.if(['js/moment-with-locales-*.min.js', 'js/plugins.min.js', 'js/aria-ng.min.js'], $.uglify({output: {comments: saveLicense}})))
        .pipe($.if(['css/plugins.min.css', 'css/aria-ng.min.css'], $.cssnano({safe: true, autoprefixer: false})))
        .pipe($.replace(/url\((\.\.\/fonts\/[a-zA-Z0-9\-]+\.woff2)(\?[a-zA-Z0-9\-_=.]+)?\)/g, function(match, fileName) {
            return 'url(' + fileName + ')'; // remove version of woff2 file (woff2 file should be cached via application cache)
        }))
        .pipe($.if(['js/plugins.min.js', 'js/aria-ng.min.js', 'css/plugins.min.css', 'css/aria-ng.min.css'], $.rev()))
        .pipe($.if('*.html', $.htmlmin({collapseWhitespace: true})))
        .pipe($.revReplace())
        .pipe(gulp.dest('.tmp'));
});

gulp.task('process-html', ['prepare-html'], function () {
    return gulp.src([
        '.tmp/*.html'
    ]).pipe($.replace(/<!-- AriaNg-Bundle:\w+ -->/, ''))
        .pipe(gulp.dest('dist'));
});

gulp.task('process-assets', ['process-html'], function () {
    return gulp.src([
        '.tmp/css/**/*',
        '.tmp/js/**/*'
    ],{ base: '.tmp' })
        .pipe(gulp.dest('dist'));
});

gulp.task('process-assets-bundle', ['prepare-fonts', 'prepare-langs', 'prepare-html'], function () {
    return gulp.src('.tmp/index.html')
        .pipe($.replace(/<link rel="stylesheet" href="(css\/[a-zA-Z0-9\-_.]+\.css)">/g, function(match, fileName) {
            var content = fs.readFileSync('.tmp/' + fileName, 'utf8');
            return '<style type="text/css">' + content + '</style>';
        }))
        .pipe($.replace(/<script src="(js\/[a-zA-Z0-9\-_.]+\.js)"><\/script>/g, function(match, fileName) {
            var content = fs.readFileSync('.tmp/' + fileName, 'utf8');
            return '<script type="application/javascript">' + content + '</script>';
        }))
        .pipe($.replace(/url\(\.\.\/(fonts\/[a-zA-Z0-9\-]+\.woff)(\?[a-zA-Z0-9\-_=.]+)?\)/g, function(match, fileName) {
            if (!fs.existsSync('.tmp/' + fileName)) {
                return match;
            }

            var contentBuffer = fs.readFileSync('.tmp/' + fileName);
            var contentBase64 = contentBuffer.toString('base64');
            return 'url(data:application/x-font-woff;base64,' + contentBase64 + ')';
        }))
        .pipe($.replace('<!-- AriaNg-Bundle:languages -->', function() {
            var langDir = '.tmp/langs/';
            var result = '';
            var fileNames = fs.readdirSync(langDir, 'utf8');

            if (fileNames.length > 0) {
                result = '<script type="application/javascript">' +
                    'angular.module("ariaNg").config(["ariaNgAssetsCacheServiceProvider",function(e){';

                for (var i = 0; i < fileNames.length; i++) {
                    var fileName = fileNames[i];
                    var content = fs.readFileSync(langDir + fileName, 'utf8');

                    var lastPointIndex = fileName.lastIndexOf('.');
                    var languageName = fileName.substr(0, lastPointIndex);

                    content = content.replace(/\\/g, '\\\\');
                    content = content.replace(/\r/g, '');
                    content = content.replace(/\n/g, '\\n');
                    content = content.replace(/"/g, '\\"');
                    result += 'e.setLanguageAsset(\'' + languageName + '\',"' + content + '");';
                }

                result += '}]);</script>';
            }

            return result;
        }))
        .pipe($.replace(/<[a-z]+( [a-z\-]+="[a-zA-Z0-9\- ]+")* [a-z\-]+="((favicon.ico)|(favicon.png)|(tileicon.png)|(touchicon.png))"\/?>/g, ''))
        .pipe(gulp.dest('dist'));
});

gulp.task('process-manifest', function () {
    return gulp.src([
        'dist/css/**',
        'dist/js/**',
        'dist/fonts/fontawesome-webfont.woff2',
        'dist/*.html',
        'dist/*.ico',
        'dist/*.png'
    ], {base: 'dist/'})
        .pipe($.manifest({
            hash: true,
            preferOnline: true,
            network: ['*'],
            filename: 'index.manifest',
            exclude: 'index.manifest'
        }))
        .pipe(gulp.dest('dist'));
});

gulp.task('process-full-extras', function () {
    return gulp.src([
        'LICENSE',
        'src/*.*',
        '!src/*.html'
    ], {
        dot: true
    }).pipe(gulp.dest('dist'));
});

gulp.task('process-tiny-extras', function () {
    return gulp.src([
        'LICENSE'
    ]).pipe(gulp.dest('dist'));
});

gulp.task('info', function () {
    return gulp.src([
        'dist/**/*'
    ]).pipe($.size({title: 'build', gzip: true}));
});

gulp.task('build', $.sequence('lint', 'process-fonts', 'process-langs', 'process-assets', 'process-manifest', 'process-full-extras', 'info'));

gulp.task('build-bundle', $.sequence('lint', 'process-assets-bundle', 'process-tiny-extras', 'info'));

gulp.task('serve', ['prepare-styles', 'prepare-scripts', 'prepare-fonts'], function () {
    browserSync({
        notify: false,
        port: 9000,
        server: {
            baseDir: ['.tmp', 'src'],
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    });

    gulp.watch([
        'src/*.html',
        'src/*.ico',
        'src/*.png',
        'src/langs/*.txt',
        'src/views/*.html',
        'src/imgs/**/*',
        '.tmp/fonts/**/*'
    ]).on('change', reload);

    gulp.watch('src/styles/**/*.css', ['prepare-styles']);
    gulp.watch('src/scripts/**/*.js', ['prepare-scripts']);
    gulp.watch('src/fonts/**/*', ['prepare-fonts']);
});

gulp.task('serve:dist', function () {
    browserSync({
        notify: false,
        port: 9000,
        server: {
            baseDir: ['dist']
        }
    });
});

gulp.task('default', ['clean'], function () {
    gulp.start('build');
});
<|endoftext|>


<commit_before>/* global browserSync, config, module, path, project */

module.exports = function(grunt) {
	var fs = require('fs'),
		yaml = require('js-yaml'),
		Remarkable = require('remarkable');

	grunt.registerTask('buildGenerator', function(task) {
		var scope = this,
			build = Wee.$toArray(project.generator.build),
			configPath = build[task],
			json = grunt.file.readJSON(configPath),
			siteConfig = json.config,
			staticRoot = path.dirname(configPath),
			site = Wee.$extend(json.data, {
				config: config,
				name: json.name,
				description: json.description,
				env: 'default',
				time: new Date(),
				sections: json.sections
			}),
			errors = 0;

		// Setup CommonMark parser
		var md = new Remarkable({
			html: true,
			typographer: siteConfig.enhanceTypography || false
		});

		// Merge default environment data
		if (json.env.default) {
			site = Wee.$extend(site, json.env.default);
		}

		if (grunt.option('env')) {
			var env = grunt.option('env');

			site = Wee.$extend(site, json.env[env]);
			site.env = env;
		}

		// Recursive function for processing site sections
		var processSection = function(context, parent) {
			var keys = Object.keys(context);

			// Loop though sections in current context
			keys.forEach(function(key) {
				var block = context[key],
					root = block.contentRoot || '',
					template = grunt.file.read(Wee.buildPath(staticRoot, siteConfig.paths.templates + '/' + block.template + '.html')),
					content = block.content ? grunt.file.expand({
						cwd: path.join(staticRoot, root)
					}, block.content) : [],
					data = {
						content: [],
						site: site
					},
					single = false;

				Wee.$toArray(block.target).forEach(function(target) {
					target = path.join(staticRoot, target);

					// Target writing function
					var writeTarget = function(target, data) {
						// Add parent reference
						if (parent) {
							data.parent = parent;
						}

						// Create target directory
						var dir = target.substring(0, target.lastIndexOf('/'));

						try {
							grunt.file.mkdir(dir);
						} catch (e) {
							Wee.notify({
								title: 'Generator Error',
								message: 'Error creating "' + dir + '" directory'
							}, 'error');
						}

						// Render template
						var output = Wee.view.render(template, data);

						// Minify rendered output
						if (siteConfig.minify === true) {
							try {
								var minify = require('html-minifier').minify;

								output = minify(output, {
									collapseWhitespace: true,
									removeComments: true
								});
							} catch (e) {
								Wee.notify({
									title: 'Generator Error',
									message: 'Error minifying "' + target + '"'
								}, 'error');
							}
						}

						var done;

						if (grunt.cli.tasks[0] == 'generate') {
							done = scope.async();
						}

						// Write output to target file
						fs.writeFile(target, output, function(err) {
							if (err) {
								Wee.notify({
									title: 'Generator Error',
									message: 'Error writing to "' + target + '"'
								}, 'error');

								errors++;
							}

							if (grunt.cli.tasks[0] == 'generate') {
								done();
							}
						});

						// Check for nested sections
						if (block.sections) {
							block.isCurrent = false;
							data.sections = block.sections;

							processSection(block.sections, block);
						}

						block.isActive = false;
						block.isCurrent = false;
					};

					// Merge in global config values
					if (block.data) {
						Wee.$extend(data, block.data);
					}

					// Determine target processing mode
					if (target.indexOf('{{') !== -1) {
						single = true;
					}

					// Set current section to active
					block.isActive = true;
					block.isCurrent = true;

					// Inject current context
					data.section = block;
					data.sections = block.sections;
					data.content = [];

					content.forEach(function(name, i) {
						var src = path.isAbsolute(name) ?
								name :
								Wee.buildPath(staticRoot, root + '/' + name),
							template = grunt.file.read(src),
							fileSegments = name.replace(/^.*[\\\/]/, '').split('.');

						fileSegments.splice(-1, 1);

						var obj = {
							sourcePath: name,
							sourceFile: name.replace(/^.*[\\\/]/, ''),
							sourceName: fileSegments.join('.'),
							name: fileSegments.join('.'),
							created: fs.statSync(src).ctime.getTime(),
							modified: fs.statSync(src).mtime.getTime(),
							original: template,
							input: '',
							blocks: []
						};

						// Check for front matter
						if (template.substring(0, 3) == '---') {
							var results = /^(---(?:\n|\r)([\w\W]+?)---)?([\w\W]*)*/.exec(template);

							// Merge YAML into the data
							if (results[2] !== undefined) {
								try {
									var front = yaml.load(results[2]);

									// Check for global data
									if (front.global) {
										data = Wee.$extend(front.global, data);
										delete front.global;
									}

									// Check for site data
									if (front.site) {
										data.site = Wee.$extend(front.site. data.site);
										delete front.site;
									}

									// Check for section data
									if (front.section) {
										data.section = Wee.$extend(front.section, data.section);
										delete front.section;
									}

									// Merge in YAML data
									obj = Wee.$extend(obj, front);
								} catch (e) {
									Wee.notify({
										title: 'Generator Error',
										message: 'There was a problem parsing the YAML'
									}, 'error');
								}
							}

							obj.original = results[3] ? results[3].trim() : '';
						}

						// Process content blocks
						var last = obj.original.length,
							regex = /(?:---(.+)---)\n/g,
							values = [],
							matches;

						// Loop through segment matches
						while ((matches = regex.exec(obj.original)) !== null) {
							var match = matches[1].trim(),
								segs = match.split('|');

							values.push({
								name: segs[0],
								helpers: segs.splice(1),
								start: matches.index,
								end: regex.lastIndex
							});
						}

						// Loop through segment values
						values.forEach(function(value, i) {
							// Calculate ending index
							var name = value.name,
								end = (i + 1) < values.length ?
									values[i + 1].start :
									last,
								helpers = value.helpers,
								content = obj.original.substr(value.end, end - value.end).trim();

							// Process primary content block
							if (i === 0 && value.start > 0) {
								obj.input = obj.original.substr(0, value.start);

								obj.blocks.push({
									name: 'content',
									input: obj.input,
									output: md.render(obj.input),
									render: true
								});
							}

							// Concatenate additional content blocks
							if (name === 'content') {
								obj.input += content;
							} else {
								var append = helpers.indexOf('append') !== -1,
									render = helpers.indexOf('render') !== -1,
									val = {
										name: name,
										input: content,
										output: md.render(content),
										render: render
									};

								// Check for block values
								helpers.forEach(function(helper) {
									if (helper.indexOf(':') !== -1) {
										var split = helper.split(':');

										val[split[0]] = split[1];
									}
								});

								// Handle array blocks
								if (append === true) {
									if (! obj.hasOwnProperty(name)) {
										obj[name] = [];
									}

									obj[name].push(val);
								} else {
									obj[name] = val;
								}

								obj.blocks.push(val);

								// Handle rendered block
								if (render === true) {
									obj.input += content;
								}
							}
						});

						// Inject current index
						obj['#'] = i;
						obj['##'] = i + 1;

						// Handle basic content
						if (values.length === 0) {
							var rendered = md.render(obj.original);

							obj.input = obj.original;

							obj.blocks.push({
								name: 'content',
								input: obj.original,
								output: rendered,
								render: true
							});

							obj.output = rendered;
						} else {
							obj.output = md.render(obj.input);
						}

						// Push current content object in to content array
						data.content.push(obj);

						// Set current target, path, and URL
						var uri = target.replace(project.paths.root, '');

						if (siteConfig.removeIndex) {
							uri = uri.replace('index.html', '');
						}

						if (siteConfig.removeTrailingSlashes === true) {
							uri = uri.replace(/\/$/, '');
						}

						data.target = block.target;
						data.path = uri;
						data.url = path.join(site.domain || '', uri);

						// Handle block ordering and sorting
						if (block.order) {
							data.content.sort(function(a, b) {
								if (a[block.order] < b[block.order]) {
									return -1;
								}

								if (a[block.order] > b[block.order]) {
									return 1;
								}

								return 0;
							});
						}

						if (block.sort == 'desc') {
							data.content.reverse();
						}

						if (single === true) {
							var dest = Wee.view.render(target, obj);

							writeTarget(dest, Wee.$extend(data, {
								content: [obj]
							}));
						}
					});

					if (single === false) {
						writeTarget(target, data);
					}
				});
			});
		};

		var tempPath = config.paths.temp,
			remoteUrls = [],
			remotesDownloaded = 0,
			remoteIndex = 1,
			done;

		// Extract remote URLs
		var getRemotePaths = function(context) {
			var keys = Object.keys(context);

			keys.forEach(function(key) {
				var block = context[key];

				if (block.content) {
					Wee.$toArray(block.content).forEach(function(value, i) {
						if (value.substring(0, 4) == 'http') {
							var filename = '/remote-' + remoteIndex + '.html',
								absolutePath = tempPath + filename,
								relativePath = './' + path.relative(
									configPath,
									tempPath
								) + filename;

							remoteUrls.push([
								value,
								absolutePath
							]);
							remoteIndex++;

							// Inject temp path into content value
							if (typeof block.content == 'string') {
								block.content = relativePath;
							} else {
								block.content[i] = path.resolve(configPath, relativePath);
							}
						}
					});
				}

				if (block.sections) {
					getRemotePaths(block.sections);
				}
			});
		};

		getRemotePaths(json.sections);

		// Download all available remote content
		if (remoteUrls.length) {
			done = this.async();

			// Create remote cache directory
			grunt.file.mkdir(path.normalize(tempPath));

			var cacheRemote = function(i) {
				var arr = remoteUrls[i],
					url = arr[0],
					http = url.substring(4, 5) == 's' ?
						require('https') :
						require('http'),
					tempFile = fs.createWriteStream(arr[1]);

				http.get(url, function(res) {
					res.on('data', function(chunk) {
						tempFile.write(chunk);
					}).on('end', function() {
						tempFile.end();

						remotesDownloaded++;

						// Continue processing if all remotes have been downloaded
						if (remotesDownloaded === remoteUrls.length) {
							processSection(json.sections);
							done();
						} else {
							cacheRemote(i + 1);
						}
					});
				}).on('error', function() {
					Wee.notify({
						title: 'Generation Error',
						message: 'There was a problem downloading ' + url
					}, 'error');

					fs.unlink(dest);
				});
			};

			cacheRemote(0);
		} else {
			processSection(json.sections);
		}

		// Reload browsers
		browserSync.reload();

		if (errors < 1) {
			Wee.notify({
				title: 'Generation Complete',
				message: 'Static site successfully built'
			});
		}
	});
};<commit_msg>Resolve issue with single generator page date<commit_after>/* global browserSync, config, module, path, project */

module.exports = function(grunt) {
	var fs = require('fs'),
		yaml = require('js-yaml'),
		Remarkable = require('remarkable');

	grunt.registerTask('buildGenerator', function(task) {
		var scope = this,
			build = Wee.$toArray(project.generator.build),
			configPath = build[task],
			json = grunt.file.readJSON(configPath),
			siteConfig = json.config,
			staticRoot = path.dirname(configPath),
			site = Wee.$extend(json.data, {
				config: config,
				name: json.name,
				description: json.description,
				env: 'default',
				time: new Date(),
				sections: json.sections
			}),
			errors = 0;

		// Setup CommonMark parser
		var md = new Remarkable({
			html: true,
			typographer: siteConfig.enhanceTypography || false
		});

		// Merge default environment data
		if (json.env.default) {
			site = Wee.$extend(site, json.env.default);
		}

		if (grunt.option('env')) {
			var env = grunt.option('env');

			site = Wee.$extend(site, json.env[env]);
			site.env = env;
		}

		// Recursive function for processing site sections
		var processSection = function(context, parent) {
			var keys = Object.keys(context);

			// Loop though sections in current context
			keys.forEach(function(key) {
				var block = context[key],
					root = block.contentRoot || '',
					template = grunt.file.read(Wee.buildPath(staticRoot, siteConfig.paths.templates + '/' + block.template + '.html')),
					content = block.content ? grunt.file.expand({
						cwd: path.join(staticRoot, root)
					}, block.content) : [],
					data = {
						content: [],
						site: site
					},
					single = false;

				Wee.$toArray(block.target).forEach(function(target) {
					target = path.join(staticRoot, target);

					// Target writing function
					var writeTarget = function(target, data) {
						// Add parent reference
						if (parent) {
							data.parent = parent;
						}

						// Create target directory
						var dir = target.substring(0, target.lastIndexOf('/'));

						try {
							grunt.file.mkdir(dir);
						} catch (e) {
							Wee.notify({
								title: 'Generator Error',
								message: 'Error creating "' + dir + '" directory'
							}, 'error');
						}

						// Render template
						var output = Wee.view.render(template, data);

						// Minify rendered output
						if (siteConfig.minify === true) {
							try {
								var minify = require('html-minifier').minify;

								output = minify(output, {
									collapseWhitespace: true,
									removeComments: true
								});
							} catch (e) {
								Wee.notify({
									title: 'Generator Error',
									message: 'Error minifying "' + target + '"'
								}, 'error');
							}
						}

						var done;

						if (grunt.cli.tasks[0] == 'generate') {
							done = scope.async();
						}

						// Write output to target file
						fs.writeFile(target, output, function(err) {
							if (err) {
								Wee.notify({
									title: 'Generator Error',
									message: 'Error writing to "' + target + '"'
								}, 'error');

								errors++;
							}

							if (grunt.cli.tasks[0] == 'generate') {
								done();
							}
						});

						// Check for nested sections
						if (block.sections) {
							block.isCurrent = false;
							data.sections = block.sections;

							processSection(block.sections, block);
						}

						block.isActive = false;
						block.isCurrent = false;
					};

					// Merge in global config values
					if (block.data) {
						Wee.$extend(data, block.data);
					}

					// Determine target processing mode
					if (target.indexOf('{{') !== -1) {
						single = true;
					}

					// Set current section to active
					block.isActive = true;
					block.isCurrent = true;

					// Inject current context
					data.section = block;
					data.sections = block.sections;
					data.content = [];

					content.forEach(function(name, i) {
						var src = path.isAbsolute(name) ?
								name :
								Wee.buildPath(staticRoot, root + '/' + name),
							template = grunt.file.read(src),
							fileSegments = name.replace(/^.*[\\\/]/, '').split('.');

						fileSegments.splice(-1, 1);

						// Reset single data
						if (single === true) {
							data = {
								content: [],
								site: site,
								section: block,
								sections: block.sections
							};
						}

						var fileStats = fs.statSync(src),
							obj = {
								sourcePath: name,
								sourceFile: name.replace(/^.*[\\\/]/, ''),
								sourceName: fileSegments.join('.'),
								name: fileSegments.join('.'),
								created: fileStats.birthtime.getTime(),
								modified: fileStats.mtime.getTime(),
								original: template,
								input: '',
								blocks: []
							};

						// Check for front matter
						if (template.substring(0, 3) == '---') {
							var results = /^(---(?:\n|\r)([\w\W]+?)---)?([\w\W]*)*/.exec(template);

							// Merge YAML into the data
							if (results[2] !== undefined) {
								try {
									var front = yaml.load(results[2]);

									// Check for global data
									if (front.global) {
										data = Wee.$extend(front.global, data);
										delete front.global;
									}

									// Check for site data
									if (front.site) {
										data.site = Wee.$extend(front.site. data.site);
										delete front.site;
									}

									// Check for section data
									if (front.section) {
										data.section = Wee.$extend(front.section, data.section);
										delete front.section;
									}

									// Merge in YAML data
									obj = Wee.$extend(obj, front);
								} catch (e) {
									Wee.notify({
										title: 'Generator Error',
										message: 'There was a problem parsing the YAML'
									}, 'error');
								}
							}

							obj.original = results[3] ? results[3].trim() : '';
						}

						// Process content blocks
						var last = obj.original.length,
							regex = /(?:---(.+)---)\n/g,
							values = [],
							matches;

						// Loop through segment matches
						while ((matches = regex.exec(obj.original)) !== null) {
							var match = matches[1].trim(),
								segs = match.split('|');

							values.push({
								name: segs[0],
								helpers: segs.splice(1),
								start: matches.index,
								end: regex.lastIndex
							});
						}

						// Loop through segment values
						values.forEach(function(value, i) {
							// Calculate ending index
							var name = value.name,
								end = (i + 1) < values.length ?
									values[i + 1].start :
									last,
								helpers = value.helpers,
								content = obj.original.substr(value.end, end - value.end).trim();

							// Process primary content block
							if (i === 0 && value.start > 0) {
								obj.input = obj.original.substr(0, value.start);

								obj.blocks.push({
									name: 'content',
									input: obj.input,
									output: md.render(obj.input),
									render: true
								});
							}

							// Concatenate additional content blocks
							if (name === 'content') {
								obj.input += content;
							} else {
								var append = helpers.indexOf('append') !== -1,
									render = helpers.indexOf('render') !== -1,
									val = {
										name: name,
										input: content,
										output: md.render(content),
										render: render
									};

								// Check for block values
								helpers.forEach(function(helper) {
									if (helper.indexOf(':') !== -1) {
										var split = helper.split(':');

										val[split[0]] = split[1];
									}
								});

								// Handle array blocks
								if (append === true) {
									if (! obj.hasOwnProperty(name)) {
										obj[name] = [];
									}

									obj[name].push(val);
								} else {
									obj[name] = val;
								}

								obj.blocks.push(val);

								// Handle rendered block
								if (render === true) {
									obj.input += content;
								}
							}
						});

						// Inject current index
						obj['#'] = i;
						obj['##'] = i + 1;

						// Handle basic content
						if (values.length === 0) {
							var rendered = md.render(obj.original);

							obj.input = obj.original;

							obj.blocks.push({
								name: 'content',
								input: obj.original,
								output: rendered,
								render: true
							});

							obj.output = rendered;
						} else {
							obj.output = md.render(obj.input);
						}

						// Push current content object in to content array
						data.content.push(obj);

						// Set current target, path, and URL
						var uri = target.replace(project.paths.root, '');

						if (siteConfig.removeIndex) {
							uri = uri.replace('index.html', '');
						}

						if (siteConfig.removeTrailingSlashes === true) {
							uri = uri.replace(/\/$/, '');
						}

						data.target = block.target;
						data.path = uri;
						data.url = path.join(site.domain || '', uri);

						// Handle block ordering and sorting
						if (block.order) {
							data.content.sort(function(a, b) {
								if (a[block.order] < b[block.order]) {
									return -1;
								}

								if (a[block.order] > b[block.order]) {
									return 1;
								}

								return 0;
							});
						}

						if (block.sort == 'desc') {
							data.content.reverse();
						}

						if (single === true) {
							var dest = Wee.view.render(target, obj);

							writeTarget(dest, Wee.$extend(data, {
								content: [obj]
							}));
						}
					});

					if (single === false) {
						writeTarget(target, data);
					}
				});
			});
		};

		var tempPath = config.paths.temp,
			remoteUrls = [],
			remotesDownloaded = 0,
			remoteIndex = 1,
			done;

		// Extract remote URLs
		var getRemotePaths = function(context) {
			var keys = Object.keys(context);

			keys.forEach(function(key) {
				var block = context[key];

				if (block.content) {
					Wee.$toArray(block.content).forEach(function(value, i) {
						if (value.substring(0, 4) == 'http') {
							var filename = '/remote-' + remoteIndex + '.html',
								absolutePath = tempPath + filename,
								relativePath = './' + path.relative(
									configPath,
									tempPath
								) + filename;

							remoteUrls.push([
								value,
								absolutePath
							]);
							remoteIndex++;

							// Inject temp path into content value
							if (typeof block.content == 'string') {
								block.content = relativePath;
							} else {
								block.content[i] = path.resolve(configPath, relativePath);
							}
						}
					});
				}

				if (block.sections) {
					getRemotePaths(block.sections);
				}
			});
		};

		getRemotePaths(json.sections);

		// Download all available remote content
		if (remoteUrls.length) {
			done = this.async();

			// Create remote cache directory
			grunt.file.mkdir(path.normalize(tempPath));

			var cacheRemote = function(i) {
				var arr = remoteUrls[i],
					url = arr[0],
					http = url.substring(4, 5) == 's' ?
						require('https') :
						require('http'),
					tempFile = fs.createWriteStream(arr[1]);

				http.get(url, function(res) {
					res.on('data', function(chunk) {
						tempFile.write(chunk);
					}).on('end', function() {
						tempFile.end();

						remotesDownloaded++;

						// Continue processing if all remotes have been downloaded
						if (remotesDownloaded === remoteUrls.length) {
							processSection(json.sections);
							done();
						} else {
							cacheRemote(i + 1);
						}
					});
				}).on('error', function() {
					Wee.notify({
						title: 'Generation Error',
						message: 'There was a problem downloading ' + url
					}, 'error');

					fs.unlink(dest);
				});
			};

			cacheRemote(0);
		} else {
			processSection(json.sections);
		}

		// Reload browsers
		browserSync.reload();

		if (errors < 1) {
			Wee.notify({
				title: 'Generation Complete',
				message: 'Static site successfully built'
			});
		}
	});
};<|endoftext|>


<commit_before>/**************************************************
** GAME VARIABLES
**************************************************/
var canvas,			// Canvas DOM element
	ctx,			// Canvas rendering context
	keys,			// Keyboard input
	devOris,		//Device Orientation
	localPlayer,	// Local player
	remotePlayers,	// Remote players
	socket;			// Socket connection
var startColor = randomColor();

var ball   = document.querySelector('.ball');
var garden = document.querySelector('.garden');
var output = document.querySelector('.output');

var maxX = garden.clientWidth  - ball.clientWidth;
var maxY = garden.clientHeight - ball.clientHeight;

var serverURL = "http://demo.redline-china.com";
// var serverURL = "http://localhost";
/**************************************************
** GAME INITIALISATION
**************************************************/
function init() {

	// Declare the canvas and rendering context

	// Maximise the canvas
	var canvasWidth = 1024;
	var canvasHeight = 768;

	// Initialise keyboard controls
	// keys = new Keys();

	devOris = new DevOris();

	// Calculate a random start position for the local player
	// The minus 5 (half a player size) stops the player being
	// placed right on the egde of the screen
	var startX = Math.round(Math.random()*(canvasWidth-3-5)),
		startY = Math.round(Math.random()*(canvasHeight-3-5));

	// Initialise the local player

	localPlayer = new Player(startX, startY, startColor);

	// Initialise socket connection
	socket = io.connect(serverURL, {port: 8000, transports: ["websocket"]});

	// Initialise remote players array
	remotePlayers = [];

	// Start listening for events
	setEventHandlers();

};

function handleOrientation(event) {
	var x = event.beta;  // In degree in the range [-180,180]
	var y = event.gamma; // In degree in the range [-90,90]

	output.innerHTML  = "beta : " + x + "\n";
	output.innerHTML += "gamma: " + y + "\n";

	// Because we don't want to have the device upside down
	// We constrain the x value to the range [-90,90]
	if (x >  90) { x =  90};
	if (x < -90) { x = -90};

	// To make computation easier we shift the range of
	// x and y to [0,180]
	x += 90;
	y += 90;

	// 10 is half the size of the ball
	// It center the positioning point to the center of the ball
	ball.style.top  = (maxX*x/90 - 10) + "px";
	ball.style.left = (maxY*y/90 - 10) + "px";
	ball.style.background = startColor;

}

/**************************************************
** GAME EVENT HANDLERS
**************************************************/
var setEventHandlers = function() {

	// Device Orientation
	window.addEventListener("deviceorientation", onMove, false);

	// Socket connection successful
	socket.on("connect", onSocketConnected);

	// Socket disconnection
	socket.on("disconnect", onSocketDisconnect);

};

function onMove(e) {
	if(localPlayer) {
		devOris.onMove(e);
	}
	handleOrientation(e);
}

// Socket connected
function onSocketConnected() {
	console.log("Connected to socket server");

	// Send local player data to the game server
	socket.emit("new player", {x: localPlayer.getX(), y: localPlayer.getY(), color:localPlayer.getColor()});
};

// Socket disconnected
function onSocketDisconnect() {
	console.log("Disconnected from socket server");
};

/**************************************************
** GAME ANIMATION LOOP
**************************************************/
function animate() {
	update();
	// draw();

	// Request a new animation frame using Paul Irish's shim
	window.requestAnimFrame(animate);
};

/**************************************************
** GAME UPDATE
**************************************************/
function update() {
	// Update local player and check for change
	// if (localPlayer.update(keys)) {
	// 	// Send local player data to the game server
	// 	socket.emit("move player", {x: localPlayer.getX(), y: localPlayer.getY()});
	// };

	if (localPlayer.updateMove(devOris)) {

		socket.emit("move player", {x: localPlayer.getX(), y: localPlayer.getY()});
	};

};

/**************************************************
** GAME DRAW
**************************************************/
function draw() {

};

/**************************************************
** GAME HELPER FUNCTIONS
**************************************************/

function randomNum(max,min){
  return Math.floor(Math.random()*(max-min+1)+min)
}
function randomColor(){
  var color="#";
  var colorArr=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];
  for(i=0;i<6;i++){
      var cur=randomNum(15,0);
      color+=colorArr[cur];
  }
  function randomNum(max,min){
      return Math.floor(Math.random()*(max-min+1)+min)
  }
  return color;
}<commit_msg>change mobile js<commit_after>/**************************************************
** GAME VARIABLES
**************************************************/
var canvas,			// Canvas DOM element
	ctx,			// Canvas rendering context
	keys,			// Keyboard input
	devOris,		//Device Orientation
	localPlayer,	// Local player
	remotePlayers,	// Remote players
	socket;			// Socket connection
var startColor = randomColor();

var ball   = document.querySelector('.ball');
var garden = document.querySelector('.garden');
var output = document.querySelector('.output');

var maxX = garden.clientWidth  - ball.clientWidth;
var maxY = garden.clientHeight - ball.clientHeight;

var serverURL = "http://demo.redline-china.com";
// var serverURL = "http://localhost";
/**************************************************
** GAME INITIALISATION
**************************************************/
function init() {

	// Declare the canvas and rendering context

	// Maximise the canvas
	var canvasWidth = 1024;
	var canvasHeight = 768;

	// Initialise keyboard controls
	// keys = new Keys();

	devOris = new DevOris();

	// Calculate a random start position for the local player
	// The minus 5 (half a player size) stops the player being
	// placed right on the egde of the screen
	var startX = Math.round(Math.random()*(canvasWidth-3-5)),
		startY = Math.round(Math.random()*(canvasHeight-3-5));

	// Initialise the local player

	localPlayer = new Player(startX, startY, startColor);

	// Initialise socket connection
	socket = io.connect(serverURL, {port: 8000, transports: ["websocket"]});

	// Initialise remote players array
	remotePlayers = [];

	// Start listening for events
	setEventHandlers();

};

function handleOrientation(event) {
	var x = event.beta;  // In degree in the range [-180,180]
	var y = event.gamma; // In degree in the range [-90,90]

	output.innerHTML  = "beta : " + x + "\n";
	output.innerHTML += "gamma: " + y + "\n";

	// Because we don't want to have the device upside down
	// We constrain the x value to the range [-90,90]
	if (x >  90) { x =  90};
	if (x < -90) { x = -90};
	if (y >  90) { y =  90};
	if (y < -90) { y = -90};

	// To make computation easier we shift the range of
	// x and y to [0,180]
	// x += 90;
	// y += 90;

	// 10 is half the size of the ball
	// It center the positioning point to the center of the ball
	ball.style.top  = (maxX*x/90 + 200 ) + "px";
	ball.style.left = (maxY*y/90 + 200) + "px";
	ball.style.background = startColor;

}

/**************************************************
** GAME EVENT HANDLERS
**************************************************/
var setEventHandlers = function() {

	// Device Orientation
	window.addEventListener("deviceorientation", onMove, false);

	// Socket connection successful
	socket.on("connect", onSocketConnected);

	// Socket disconnection
	socket.on("disconnect", onSocketDisconnect);

};

function onMove(e) {
	if(localPlayer) {
		devOris.onMove(e);
	}
	handleOrientation(e);
}

// Socket connected
function onSocketConnected() {
	console.log("Connected to socket server");

	// Send local player data to the game server
	socket.emit("new player", {x: localPlayer.getX(), y: localPlayer.getY(), color:localPlayer.getColor()});
};

// Socket disconnected
function onSocketDisconnect() {
	console.log("Disconnected from socket server");
};

/**************************************************
** GAME ANIMATION LOOP
**************************************************/
function animate() {
	update();
	// draw();

	// Request a new animation frame using Paul Irish's shim
	window.requestAnimFrame(animate);
};

/**************************************************
** GAME UPDATE
**************************************************/
function update() {
	// Update local player and check for change
	// if (localPlayer.update(keys)) {
	// 	// Send local player data to the game server
	// 	socket.emit("move player", {x: localPlayer.getX(), y: localPlayer.getY()});
	// };

	if (localPlayer.updateMove(devOris)) {

		socket.emit("move player", {x: localPlayer.getX(), y: localPlayer.getY()});
	};

};

/**************************************************
** GAME DRAW
**************************************************/
function draw() {

};

/**************************************************
** GAME HELPER FUNCTIONS
**************************************************/

function randomNum(max,min){
  return Math.floor(Math.random()*(max-min+1)+min)
}
function randomColor(){
  var color="#";
  var colorArr=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];
  for(i=0;i<6;i++){
      var cur=randomNum(15,0);
      color+=colorArr[cur];
  }
  function randomNum(max,min){
      return Math.floor(Math.random()*(max-min+1)+min)
  }
  return color;
}<|endoftext|>


<commit_before>require('shelljs/global');

const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const gh = require('ghreleases');
const semver = require('semver');
const bump = require('gulp-bump');
const Dropbox = require('dropbox');
const pkg = require('./package.json');
const markdownEscape = require('markdown-escape');
const commitsBetween = require('commits-between');
const electronBuilder = require('electron-builder');

const DROPBOX_TOKEN = process.env.DROPBOX_TOKEN;
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const GITHUB_USER = process.env.GITHUB_USER;

const isTravisCi = process.env.TRAVIS === 'true';
const isPullRequest = process.env.TRAVIS_PULL_REQUEST !== 'false';
const commitish = process.env.TRAVIS_COMMIT || null;
const tagName = process.env.TRAVIS_TAG || null;
const branchName = process.env.TRAVIS_BRANCH;
const isOsx = process.env.TRAVIS_OS_NAME === 'osx';
const platformsToBuild = isOsx ? 'm' : 'lw';
const versionFromTagName = semver.valid(tagName);
const buildVersion = versionFromTagName || semver.valid(pkg.version);
const mainVersion = [semver.major(buildVersion), semver.minor(buildVersion), semver.patch(buildVersion)].join('.');
const prereleaseChannel = (semver.prerelease(buildVersion) || [])[0];
const isBeta = prereleaseChannel === 'beta';
const shouldRelease = isTravisCi && !!versionFromTagName;

if (shouldRelease) {
  checkReleasePreConditions();
}

const artifactNames = {
  linux: `${pkg.name}-${buildVersion}-linux-x86_64.AppImage`,
  win: `${pkg.name}-${buildVersion}-windows.exe`,
  osx: `${pkg.name}-${buildVersion}-osx.dmg`
};

const buildConfig = {
  appId: isBeta ? 'de.anavis.beta' : 'de.anavis',
  productName: isBeta ? 'AnaVis Beta' : 'AnaVis',
  electronVersion: '1.8.1',
  mac: {
    target: [{ target: 'dmg', arch: ['x64'] }],
    category: 'public.app-category.education'
  },
  linux: {
    target: [{ target: 'AppImage', arch: ['x64'] }],
    category: 'Education'
  },
  win: {
    target: [{ target: 'nsis', arch: ['x64'] }]
  },
  dmg: {
    artifactName: artifactNames.osx,
    iconSize: 120,
    iconTextSize: 14,
    contents: [{
      x: 478,
      y: 170,
      type: 'link',
      path: '/Applications'
    }, {
      x: 130,
      y: 170,
      type: 'file'
    }]
  },
  nsis: {
    artifactName: artifactNames.win,
    oneClick: false,
    allowToChangeInstallationDirectory: true
  },
  appImage: {
    artifactName: artifactNames.linux
  },
  publish: null
}

gulp.task('version', () => {
  return gulp.src(['package.json', 'app/package.json'], { base: '.' })
    .pipe(bump({ version: buildVersion }))
    .pipe(gulp.dest('.'));
});

gulp.task('build', ['version'], async () => {
  await electronBuilder.build({
    config: buildConfig,
    mac: isOsx ? ['dmg'] : null,
    win: isOsx ? null : ['nsis'],
    linux: isOsx ? null : ['AppImage']
  });
  if (shouldRelease) {
    const filesToUpload = isOsx ? [artifactNames.osx] : [artifactNames.win, artifactNames.linux];
    await uploadArtifactsToDropbox(filesToUpload, './dist');
  }
});

gulp.task('release', async () => {
  if (!shouldRelease) {
    console.log('No release, nothing to do here.');
    return;
  }

  const filesToDownload = [artifactNames.osx, artifactNames.win, artifactNames.linux];
  const fileToUpload = filesToDownload.map(file => path.resolve(`./release/${file}`));
  const releaseName = `${buildConfig.productName} v${buildVersion}`;
  const githubAuth = { token: GITHUB_TOKEN, user: GITHUB_USER };

  await downloadArtifactsFromDropbox(filesToDownload, './release');
  const latestRelease = await getLatestGithubRelease(githubAuth, 'learningmedia', 'anavis');
  const commits = await commitsBetween({ from: latestRelease.tag_name });
  const releaseNotes = await createReleaseNotes(commits);
  const release = await createGithubRelease(githubAuth,'learningmedia', 'anavis', { tag_name: tagName, name: releaseName, body: releaseNotes, prerelease: isBeta });
  await uploadAssetsToGithubRelease(githubAuth, 'learningmedia', 'anavis', release.id, fileToUpload);
});

/// HELPERS //////////////////////////////////////////////////////////////////////////////

function uploadArtifactsToDropbox(fileNames, sourceDir) {
  const absoluteDir = path.resolve(sourceDir);
  return Promise.all(fileNames.map(file => uploadToDropbox(path.join(absoluteDir, file), `/${file}`)));
}

function downloadArtifactsFromDropbox(fileNames, targetDir) {
  const absoluteDir = path.resolve(targetDir);
  mkdir('-p', absoluteDir);
  return Promise.all(fileNames.map(file => downloadFromDropbox(`/${file}`, path.join(absoluteDir, file))));
}

function uploadToDropbox(source, target) {
  const fileContent = fs.readFileSync(source);
  const dbx = new Dropbox({ accessToken: DROPBOX_TOKEN });
  return dbx.filesUpload({ path: target, contents: fileContent });
}

function downloadFromDropbox(source, target) {
  const dbx = new Dropbox({ accessToken: DROPBOX_TOKEN });
  return dbx.filesDownload({ path: source })
    .then(data => fs.writeFileSync(target, data.fileBinary, 'binary'));
}

function getLatestGithubRelease(githubAuth, owner, repo) {
  return new Promise((reject, resolve) => {
    gh.getLatest(githubAuth, owner, repo, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
}

function createGithubRelease(githubAuth, owner, repo, data) {
  return new Promise((reject, resolve) => {
    gh.create(githubAuth, owner, repo, data, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
}

function uploadAssetsToGithubRelease(githubAuth, owner, repo, releaseId, files) {
  return new Promise((reject, resolve) => {
    gh.uploadAssets(githubAuth, owner, repo, releaseId, files, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
}

function checkReleasePreConditions() {
  if (mainVersion !== pkg.version) {
    throw new Error(`Tag version ${versionFromTagName} does not correspond to package version ${pkg.version}.`);
  }

  if (prereleaseChannel && prereleaseChannel !== 'beta') {
    throw new Error(`Tag version ${versionFromTagName} does not fulfill version name constraints.`);
  }
}

function createReleaseNotes(commits) {
  return commits.map(c => `* ${markdownEscape(c.subject)}`).join('\n');
}
<commit_msg>Fix gulp release task<commit_after>require('shelljs/global');

const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const gh = require('ghreleases');
const semver = require('semver');
const bump = require('gulp-bump');
const Dropbox = require('dropbox');
const pkg = require('./package.json');
const markdownEscape = require('markdown-escape');
const commitsBetween = require('commits-between');
const electronBuilder = require('electron-builder');

const DROPBOX_TOKEN = process.env.DROPBOX_TOKEN;
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const GITHUB_USER = process.env.GITHUB_USER;

const isTravisCi = process.env.TRAVIS === 'true';
const isPullRequest = process.env.TRAVIS_PULL_REQUEST !== 'false';
const commitish = process.env.TRAVIS_COMMIT || null;
const tagName = process.env.TRAVIS_TAG || null;
const branchName = process.env.TRAVIS_BRANCH;
const isOsx = process.env.TRAVIS_OS_NAME === 'osx';
const platformsToBuild = isOsx ? 'm' : 'lw';
const versionFromTagName = semver.valid(tagName);
const buildVersion = versionFromTagName || semver.valid(pkg.version);
const mainVersion = [semver.major(buildVersion), semver.minor(buildVersion), semver.patch(buildVersion)].join('.');
const prereleaseChannel = (semver.prerelease(buildVersion) || [])[0];
const isBeta = prereleaseChannel === 'beta';
const shouldRelease = isTravisCi && !!versionFromTagName && (!prereleaseChannel || prereleaseChannel === 'beta');

const artifactNames = {
  linux: `${pkg.name}-${buildVersion}-linux-x86_64.AppImage`,
  win: `${pkg.name}-${buildVersion}-windows.exe`,
  osx: `${pkg.name}-${buildVersion}-osx.dmg`
};

const buildConfig = {
  appId: isBeta ? 'de.anavis.beta' : 'de.anavis',
  productName: isBeta ? 'AnaVis Beta' : 'AnaVis',
  electronVersion: '1.8.1',
  mac: {
    target: [{ target: 'dmg', arch: ['x64'] }],
    category: 'public.app-category.education'
  },
  linux: {
    target: [{ target: 'AppImage', arch: ['x64'] }],
    category: 'Education'
  },
  win: {
    target: [{ target: 'nsis', arch: ['x64'] }]
  },
  dmg: {
    artifactName: artifactNames.osx,
    iconSize: 120,
    iconTextSize: 14,
    contents: [{
      x: 478,
      y: 170,
      type: 'link',
      path: '/Applications'
    }, {
      x: 130,
      y: 170,
      type: 'file'
    }]
  },
  nsis: {
    artifactName: artifactNames.win,
    oneClick: false,
    allowToChangeInstallationDirectory: true
  },
  appImage: {
    artifactName: artifactNames.linux
  },
  publish: null
}

gulp.task('version', () => {
  return gulp.src(['package.json', 'app/package.json'], { base: '.' })
    .pipe(bump({ version: buildVersion }))
    .pipe(gulp.dest('.'));
});

gulp.task('build', ['version'], async () => {
  await electronBuilder.build({
    config: buildConfig,
    mac: isOsx ? ['dmg'] : null,
    win: isOsx ? null : ['nsis'],
    linux: isOsx ? null : ['AppImage']
  });
  if (shouldRelease) {
    const filesToUpload = isOsx ? [artifactNames.osx] : [artifactNames.win, artifactNames.linux];
    await uploadArtifactsToDropbox(filesToUpload, './dist');
  }
});

gulp.task('release', async () => {
  if (!shouldRelease) {
    console.log('No release, nothing to do here.');
    return;
  }

  const filesToDownload = [artifactNames.osx, artifactNames.win, artifactNames.linux];
  const fileToUpload = filesToDownload.map(file => path.resolve(`./release/${file}`));
  const releaseName = `${buildConfig.productName} v${buildVersion}`;
  const githubAuth = { token: GITHUB_TOKEN, user: GITHUB_USER };

  await downloadArtifactsFromDropbox(filesToDownload, './release');
  const latestRelease = await getLatestGithubRelease(githubAuth, 'learningmedia', 'anavis');
  const commits = await commitsBetween({ from: latestRelease.tag_name });
  const releaseNotes = await createReleaseNotes(commits);
  const release = await createGithubRelease(githubAuth,'learningmedia', 'anavis', { tag_name: tagName, name: releaseName, body: releaseNotes, prerelease: isBeta });
  await uploadAssetsToGithubRelease(githubAuth, 'learningmedia', 'anavis', release.id, fileToUpload);
});

/// HELPERS //////////////////////////////////////////////////////////////////////////////

function uploadArtifactsToDropbox(fileNames, sourceDir) {
  const absoluteDir = path.resolve(sourceDir);
  return Promise.all(fileNames.map(file => uploadToDropbox(path.join(absoluteDir, file), `/${file}`)));
}

function downloadArtifactsFromDropbox(fileNames, targetDir) {
  const absoluteDir = path.resolve(targetDir);
  mkdir('-p', absoluteDir);
  return Promise.all(fileNames.map(file => downloadFromDropbox(`/${file}`, path.join(absoluteDir, file))));
}

function uploadToDropbox(source, target) {
  const fileContent = fs.readFileSync(source);
  const dbx = new Dropbox({ accessToken: DROPBOX_TOKEN });
  return dbx.filesUpload({ path: target, contents: fileContent });
}

function downloadFromDropbox(source, target) {
  const dbx = new Dropbox({ accessToken: DROPBOX_TOKEN });
  return dbx.filesDownload({ path: source })
    .then(data => fs.writeFileSync(target, data.fileBinary, 'binary'));
}

function getLatestGithubRelease(githubAuth, owner, repo) {
  return new Promise((resolve, reject) => {
    gh.getLatest(githubAuth, owner, repo, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
}

function createGithubRelease(githubAuth, owner, repo, data) {
  return new Promise((resolve, reject) => {
    gh.create(githubAuth, owner, repo, data, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
}

function uploadAssetsToGithubRelease(githubAuth, owner, repo, releaseId, files) {
  return new Promise((resolve, reject) => {
    gh.uploadAssets(githubAuth, owner, repo, releaseId, files, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });
}

function createReleaseNotes(commits) {
  return commits.map(c => `* ${markdownEscape(c.subject)}`).join('\n');
}
<|endoftext|>