<commit_before>(function () {
//
// Select all links with the 'rel' attribute set to "less"
//
var sheets = [];

less.env = location.hostname == '127.0.0.1' ||
           location.hostname == '0.0.0.0'   ||
           location.hostname == 'localhost' ||
           location.protocol == 'file:'     ? 'development'
                                            : 'production';

// Load the stylesheets when the body is ready
var readyTimer = setInterval(function () {
    if (document.body) {
        if (!document.querySelectorAll && typeof(jQuery) === "undefined") {
            log("No selector method found");
        } else {
            sheets = (document.querySelectorAll || jQuery).call(document, 'link[rel="stylesheet/less"]');
        }
        clearInterval(readyTimer);
        loadStyleSheets(function (sheet, env) {
            if (env.local) {
                log("less: loading " + sheet.href + " from local storage.");
            } else {
                log("less: parsed " + sheet.href + " successfully.");
            }
        });
    }
}, 10);

//
// Auto-refresh
//
if (less.env === 'development') {
    refreshTimer = setInterval(function () {
        if (/!refresh/.test(location.hash)) {
            loadStyleSheets(function () {});
        }
    }, 1000);
}

function loadStyleSheets(callback) {
    for (var i = 0; i < sheets.length; i++) {
        loadStyleSheet(sheets[i], callback);
    }
}

function loadStyleSheet(sheet, callback) {
    var css = typeof(localStorage) !== "undefined" && localStorage.getItem(sheet.href);
    var styles = css && JSON.parse(css);

    xhr(sheet.href, function (data, lastModified) {
        if (styles && (new(Date)(lastModified).valueOf() ===
                       new(Date)(styles.timestamp).valueOf())) {
            // Use local copy
            createCSS(styles.css, sheet);
            callback(sheet, {local: true})
        } else {
            // Use remote copy (re-parse)
            new(less.Parser)({ optimization: 3 }).parse(data, function (e, root) {
                if (e) { return error(e, sheet.href) }
                try {
                    createCSS(root.toCSS(), sheet, lastModified);
                    callback(sheet, {local: false})
                } catch (e) {
                    error(e, sheet.href);
                }
            });
        }
    });
}

function createCSS(styles, sheet, lastModified) {
    var css = document.createElement('style');
    css.type = 'text/css';
    css.media = 'screen';
    css.title = 'less-sheet';

    if (sheet) {
        css.title = sheet.title || sheet.href.match(/(?:^|\/)([-\w]+)\.[a-z]+$/i)[1];

        // Don't update the local store if the file wasn't modified
        if (lastModified && typeof(localStorage) !== "undefined") {
            localStorage.setItem(sheet.href, JSON.stringify({ timestamp: lastModified, css: styles }));
        }
    }

    if (css.styleSheet) {
        css.styleSheet.cssText = styles;
    } else {
        css.appendChild(document.createTextNode(styles));
    }
    document.getElementsByTagName('head')[0].appendChild(css);
}

function xhr(url, callback, errback) {
    var xhr = getXMLHttpRequest();

    if (window.location.protocol === "file:") {
        xhr.open('GET', url, false);
        xhr.send(null);
        if (xhr.status === 0) {
            callback(xhr.responseText);
        } else {
            errback(xhr.responseText);
        }
    } else {
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    callback(xhr.responseText,
                             xhr.getResponseHeader("Last-Modified"));
                } else if (typeof(errback) === 'function') {
                    errback(xhr.responseText);
                }
            }
        };
        xhr.send(null);
    }
}

function getXMLHttpRequest() {
    if (window.XMLHttpRequest) {
        return new(XMLHttpRequest);
    } else {
        try {
            return new(ActiveXObject)("MSXML2.XMLHTTP.3.0");
        } catch (e) {
            log("less: browser doesn't support AJAX.");
            return null;
        }
    }
}

function log(str) {
    if (less.env == 'development' && typeof(console) !== "undefined") { console.log(str) }
}

function error(e, href) {
    var template = ['
',
                        '
[-1]{0}
',
                        '
[0]{current}
',
                        '
[1]{2}
',
                    '
'].join('\n');

    var elem = document.createElement('div'), timer;
    elem.id = "less-error-message";
    elem.innerHTML = '
' + (e.message || 'There is an error in your .less file') + '
' +
                     '
' + href + " "                +
                     'on line '     + e.line + ', column ' + (e.column + 1)         + ':
' +
                     template.replace(/\[(-?\d)\]/g, function (_, i) {
                         return e.line + parseInt(i);
                     }).replace(/\{(\d)\}/g, function (_, i) {
                         return e.extract[parseInt(i)];
                     }).replace(/\{current\}/, e.extract[1].slice(0, e.column)      +
                                               ''               +
                                               e.extract[1].slice(e.column)         +
                                               '');

    elem.style.cssText = [
        "font-family: Arial, sans-serif",
        "border: 1px solid #e00",
        "background-color: #eee",
        "border-radius: 5px",
        "color: #e00",
        "padding: 15px",
        "margin-bottom: 15px"
    ].join(';');

    if (less.env == 'development') {
        timer = setInterval(function () {
            if (document.body) {
                document.body.insertBefore(elem, document.body.childNodes[0]);
                clearInterval(timer);
            }
        }, 10);
    }
}

// CSS for error messages
createCSS([
    '#less-error-message span {',
        'margin-right: 15px;',
    '}',
    '#less-error-message pre {',
        'color: #ee4444;',
        'padding: 4px 0;',
        'margin: 0;',
    '}',
    '#less-error-message pre.ctx {',
        'color: #dd7777;',
    '}',
    '#less-error-message h3 {',
        'padding: 15px 0 5px 0;',
        'margin: 0;',
    '}',
    '#less-error-message a {',
        'color: #10a',
    '}',
    '#less-error-message .error {',
        'color: red;',
        'font-weight: bold;',
        'padding-bottom: 2px;',
        'border-bottom: 1px dashed red;',
    '}'
].join(''));

})();
<commit_msg>move error message css back in error function<commit_after>(function () {
//
// Select all links with the 'rel' attribute set to "less"
//
var sheets = [];

less.env = location.hostname == '127.0.0.1' ||
           location.hostname == '0.0.0.0'   ||
           location.hostname == 'localhost' ||
           location.protocol == 'file:'     ? 'development'
                                            : 'production';

// Load the stylesheets when the body is ready
var readyTimer = setInterval(function () {
    if (document.body) {
        if (!document.querySelectorAll && typeof(jQuery) === "undefined") {
            log("No selector method found");
        } else {
            sheets = (document.querySelectorAll || jQuery).call(document, 'link[rel="stylesheet/less"]');
        }
        clearInterval(readyTimer);
        loadStyleSheets(function (sheet, env) {
            if (env.local) {
                log("less: loading " + sheet.href + " from local storage.");
            } else {
                log("less: parsed " + sheet.href + " successfully.");
            }
        });
    }
}, 10);

//
// Auto-refresh
//
if (less.env === 'development') {
    refreshTimer = setInterval(function () {
        if (/!refresh/.test(location.hash)) {
            loadStyleSheets(function () {});
        }
    }, 1000);
}

function loadStyleSheets(callback) {
    for (var i = 0; i < sheets.length; i++) {
        loadStyleSheet(sheets[i], callback);
    }
}

function loadStyleSheet(sheet, callback) {
    var css = typeof(localStorage) !== "undefined" && localStorage.getItem(sheet.href);
    var styles = css && JSON.parse(css);

    xhr(sheet.href, function (data, lastModified) {
        if (styles && (new(Date)(lastModified).valueOf() ===
                       new(Date)(styles.timestamp).valueOf())) {
            // Use local copy
            createCSS(styles.css, sheet);
            callback(sheet, {local: true})
        } else {
            // Use remote copy (re-parse)
            new(less.Parser)({ optimization: 3 }).parse(data, function (e, root) {
                if (e) { return error(e, sheet.href) }
                try {
                    createCSS(root.toCSS(), sheet, lastModified);
                    callback(sheet, {local: false})
                } catch (e) {
                    error(e, sheet.href);
                }
            });
        }
    });
}

function createCSS(styles, sheet, lastModified) {
    var css = document.createElement('style');
    css.type = 'text/css';
    css.media = 'screen';
    css.title = 'less-sheet';

    if (sheet) {
        css.title = sheet.title || sheet.href.match(/(?:^|\/)([-\w]+)\.[a-z]+$/i)[1];

        // Don't update the local store if the file wasn't modified
        if (lastModified && typeof(localStorage) !== "undefined") {
            localStorage.setItem(sheet.href, JSON.stringify({ timestamp: lastModified, css: styles }));
        }
    }

    if (css.styleSheet) {
        css.styleSheet.cssText = styles;
    } else {
        css.appendChild(document.createTextNode(styles));
    }
    document.getElementsByTagName('head')[0].appendChild(css);
}

function xhr(url, callback, errback) {
    var xhr = getXMLHttpRequest();

    if (window.location.protocol === "file:") {
        xhr.open('GET', url, false);
        xhr.send(null);
        if (xhr.status === 0) {
            callback(xhr.responseText);
        } else {
            errback(xhr.responseText);
        }
    } else {
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    callback(xhr.responseText,
                             xhr.getResponseHeader("Last-Modified"));
                } else if (typeof(errback) === 'function') {
                    errback(xhr.responseText);
                }
            }
        };
        xhr.send(null);
    }
}

function getXMLHttpRequest() {
    if (window.XMLHttpRequest) {
        return new(XMLHttpRequest);
    } else {
        try {
            return new(ActiveXObject)("MSXML2.XMLHTTP.3.0");
        } catch (e) {
            log("less: browser doesn't support AJAX.");
            return null;
        }
    }
}

function log(str) {
    if (less.env == 'development' && typeof(console) !== "undefined") { console.log(str) }
}

function error(e, href) {
    var template = ['
',
                        '
[-1]{0}
',
                        '
[0]{current}
',
                        '
[1]{2}
',
                    '
'].join('\n');

    var elem = document.createElement('div'), timer;
    elem.id = "less-error-message";
    elem.innerHTML = '
' + (e.message || 'There is an error in your .less file') + '
' +
                     '
' + href + " "                +
                     'on line '     + e.line + ', column ' + (e.column + 1)         + ':
' +
                     template.replace(/\[(-?\d)\]/g, function (_, i) {
                         return e.line + parseInt(i);
                     }).replace(/\{(\d)\}/g, function (_, i) {
                         return e.extract[parseInt(i)];
                     }).replace(/\{current\}/, e.extract[1].slice(0, e.column)      +
                                               ''               +
                                               e.extract[1].slice(e.column)         +
                                               '');
    // CSS for error messages
    createCSS([
        '#less-error-message span {',
            'margin-right: 15px;',
        '}',
        '#less-error-message pre {',
            'color: #ee4444;',
            'padding: 4px 0;',
            'margin: 0;',
        '}',
        '#less-error-message pre.ctx {',
            'color: #dd7777;',
        '}',
        '#less-error-message h3 {',
            'padding: 15px 0 5px 0;',
            'margin: 0;',
        '}',
        '#less-error-message a {',
            'color: #10a',
        '}',
        '#less-error-message .error {',
            'color: red;',
            'font-weight: bold;',
            'padding-bottom: 2px;',
            'border-bottom: 1px dashed red;',
        '}'
    ].join(''));

    elem.style.cssText = [
        "font-family: Arial, sans-serif",
        "border: 1px solid #e00",
        "background-color: #eee",
        "border-radius: 5px",
        "color: #e00",
        "padding: 15px",
        "margin-bottom: 15px"
    ].join(';');

    if (less.env == 'development') {
        timer = setInterval(function () {
            if (document.body) {
                document.body.insertBefore(elem, document.body.childNodes[0]);
                clearInterval(timer);
            }
        }, 10);
    }
}

})();
<|endoftext|>


<commit_before>(function(){

   var util = require('util'),
       Transform = require('stream').Transform;

   util.inherits(LineCounter, Transform);

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

      Transform.call(this, options);
      this._lines = '';
      this._accumulatedLines = 0;
      this._numLines = (options && options.numLines) || 1;
      this._flushTail = (options && options.flushTail) || false;
   }

   LineCounter.prototype._transform = function (chunk, encoding, done) {

      // split chunk on lines
      var begin = 0;
      for (var i = 0; i < chunk.length; i++) {
         if (chunk[i] === 10) { // '\n'
            this._accumulatedLines++;
            if (this._accumulatedLines == this._numLines) {
               this._lines += chunk.slice(begin, i + 1).toString();
               this.push(this._lines);
               this._lines = '';
               this._accumulatedLines = 0;
               begin = i + 1;
            }
         }
      }

      this._lines += chunk.toString();

      done();
   };

   LineCounter.prototype._flush = function(done) {
      if(this._flushTail) {
         this.push(this._lines);
      }
      done();
   };

   module.exports = LineCounter;

})();<commit_msg>Tests fixed<commit_after>(function(){

   var util = require('util'),
       Transform = require('stream').Transform;

   util.inherits(LineCounter, Transform);

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

      Transform.call(this, options);
      this._lines = '';
      this._accumulatedLines = 0;
      this._numLines = (options && options.numLines) || 1;
      this._flushTail = (options && options.flushTail) || false;
   }

   LineCounter.prototype._transform = function (chunk, encoding, done) {

      // split chunk on lines
      var begin = 0;
      for (var i = 0; i < chunk.length; i++) {
         if (chunk[i] === 10) { // '\n'
            this._accumulatedLines++;
            if (this._accumulatedLines == this._numLines) {
               this._lines += chunk.slice(begin, i + 1).toString();
               this.push(this._lines);
               this._lines = '';
               this._accumulatedLines = 0;
               begin = i + 1;
            }
         }
      }

      this._lines += chunk.slice(begin).toString();

      done();
   };

   LineCounter.prototype._flush = function(done) {
      if(this._flushTail) {
         this.push(this._lines);
      }
      done();
   };

   module.exports = LineCounter;

})();<|endoftext|>


<commit_before>function run(code){
  if(typeof code !== "object")
    return code;
  var key;
  var args = [];
  if(typeof code[0] === "object"){
    key = run(code[0]);
  }else{
    key = code[0];
  }
  var temp =function(b){
              return function(){
                var c;
                if(!c)
                  c = run(code[b]);
                return c;
              };
            };
  for(var i = 1;i<code.length;i++){
    args[i-1]=temp(i);
  }
  return env[key](args);
}
var env = {};
<commit_msg>fixed double runtime<commit_after>function run(code){
  if(typeof code !== "object")
    return code;
  var key;
  var args = [];
  if(typeof code[0] === "object"){
    key = run(code[0]);
  }else{
    key = code[0];
  }
  var temp =function(b){
              var c;
              return function(){
                if(!c)
                  c = run(code[b]);
                return c;
              };
            };
  for(var i = 1;i<code.length;i++){
    args[i-1]=temp(i);
  }
  return env[key](args);
}
var env = {};
<|endoftext|>


<commit_before>'use strict';

Connector.playerSelector = '#footerPlayer';

Connector.playButtonSelector = `${Connector.playerSelector} button[data-test="play"]`;

Connector.pauseButtonSelector = `${Connector.playerSelector} button[data-test="pause"]`;

Connector.isScrobblingAllowed = () => !!Util.queryElements(Connector.playButtonSelector);

Connector.trackSelector = `${Connector.playerSelector} div[data-test="footer-track-title"]`;

Connector.getUniqueID = () => {
	const trackUrl = Util.getAttrFromSelectors(`${Connector.trackSelector} a`, 'href');
	if (trackUrl) {
		return trackUrl.split('/').pop();
	}
	return null;
};

Connector.artistSelector = `${Connector.playerSelector} span.artist-link`;

Connector.albumSelector = ['#nowPlaying div.react-tabs a[href^="/album/"]', `${Connector.playerSelector} a[href^="/album/"]`];

Connector.getAlbumArtist = () => {
	const albumUrl = Util.getAttrFromSelectors(Connector.albumSelector, 'href');
	const canonicalUrl = Util.getAttrFromSelectors('head link[rel="canonical"]', 'href');
	if (albumUrl && canonicalUrl && canonicalUrl.endsWith(albumUrl)) {
		return Util.getTextFromSelectors('#main .header-details .artist-link');
	}
	return null;
};

Connector.trackArtSelector = `${Connector.playerSelector} figure[data-test="current-media-imagery"] img`;

Connector.currentTimeSelector = `${Connector.playerSelector} time[data-test="current-time"]`;

Connector.durationSelector = `${Connector.playerSelector} time[data-test="duration-time"]`;

Connector.applyFilter(MetadataFilter.getTidalFilter());
<commit_msg>Add short name selector as default for Tidal. (#3065)<commit_after>'use strict';

Connector.playerSelector = '#footerPlayer';

Connector.playButtonSelector = `${Connector.playerSelector} button[data-test="play"]`;

Connector.pauseButtonSelector = `${Connector.playerSelector} button[data-test="pause"]`;

Connector.isScrobblingAllowed = () => !!Util.queryElements(Connector.playButtonSelector);

Connector.trackSelector = ['#nowPlaying div.react-tabs__tab-panel--selected > div > div:nth-child(1) > div:nth-child(1) > span:nth-child(2)', `${Connector.playerSelector} div[data-test="footer-track-title"]`];

Connector.getUniqueID = () => {
	const trackUrl = Util.getAttrFromSelectors(`${Connector.trackSelector} a`, 'href');
	if (trackUrl) {
		return trackUrl.split('/').pop();
	}
	return null;
};

Connector.artistSelector = `${Connector.playerSelector} span.artist-link`;

Connector.albumSelector = ['#nowPlaying div.react-tabs a[href^="/album/"]', `${Connector.playerSelector} a[href^="/album/"]`];

Connector.getAlbumArtist = () => {
	const albumUrl = Util.getAttrFromSelectors(Connector.albumSelector, 'href');
	const canonicalUrl = Util.getAttrFromSelectors('head link[rel="canonical"]', 'href');
	if (albumUrl && canonicalUrl && canonicalUrl.endsWith(albumUrl)) {
		return Util.getTextFromSelectors('#main .header-details .artist-link');
	}
	return null;
};

Connector.trackArtSelector = `${Connector.playerSelector} figure[data-test="current-media-imagery"] img`;

Connector.currentTimeSelector = `${Connector.playerSelector} time[data-test="current-time"]`;

Connector.durationSelector = `${Connector.playerSelector} time[data-test="duration-time"]`;

Connector.applyFilter(MetadataFilter.getTidalFilter());
<|endoftext|>


<commit_before>import React, { Fragment } from 'react'
import {
  Provider,
  Heading,
  Lead,
  Container,
  Flex,
  Box,
  Text,
  Subhead,
  Link as A
} from 'rebass'
import theme, { colors, cx, mx, mm } from '../theme'
import { Head, Link } from 'react-static'
import Nav from '../components/Nav'
import CTA from '../components/CTA'
import Icon from '../components/Icon'
import Footer from '../components/Footer'

const Section = Flex.extend.attrs({
  is: 'section',
  align: 'center',
  justify: 'center',
  direction: 'column',
  color: 'white',
  py: [4, 5],
  px: 3
})`
  text-align: center;
`
const One = Section.extend`
  padding-top: 0 !important;
  background-color: ${cx('red.5')};
  background-image: linear-gradient(
    16deg,
    ${cx('orange.4')} 0%,
    ${cx('red.5')} 50%,
    ${cx('red.6')} 100%
  );
`
const Two = Section.extend`
  background-color: ${cx('blue.6')};
  background-image: linear-gradient(
    16deg,
    ${cx('blue.6')} 0%,
    ${cx('blue.5')} 50%,
    ${cx('indigo.4')} 100%
  );
`
const Three = Section.extend`
  background-color: ${cx('fuschia.5')};
  background-image: linear-gradient(
    -32deg,
    ${cx('fuschia.5')} 0%,
    ${cx('fuschia.6')} 50%,
    ${cx('pink.4')} 100%
  );
`
const Four = Section.extend`
  background-color: ${cx('violet.6')};
  background-image: linear-gradient(
    48deg,
    ${cx('violet.5')} 0%,
    ${cx('violet.6')} 50%,
    ${cx('indigo.4')} 100%
  );
`

const Modules = Flex.extend.attrs({
  wrap: true,
  justify: 'center',
  mt: 3
})`
  ${mm[1]} {
    text-align: left;
  }
`

const ModuleBase = Flex.extend.attrs({
  w: [1, 1 / 3],
  p: 2,
  direction: ['row', 'column'],
  align: ['flex-start', 'center']
})`
  img {
    width: 3rem !important;
    height: 3rem !important;
    flex-shrink: 0;
    margin-right: 1rem;
  }

  ${mx[1]} {
    max-width: 20rem;
    img { margin-right: 0; }
  }
`

const ModuleHeading = Subhead.extend.attrs({ mt: 0, mb: 1, f: 3 })``
const ModuleBody = Text.extend.attrs({ my: 0, f: 2 })`
  line-height: 1.5;
  position: relative;
`

const Module = ({ icon, heading, body, ...props }) => (
  <ModuleBase>
    <Icon name={icon} fill="white" />

      <ModuleHeading children={heading} />
      <ModuleBody children={body} />

  </ModuleBase>
)

const LeftCol = Flex.extend.attrs({
  direction: 'column',
  align: ['center', 'flex-end'],
  mr: [0, 4]
})`
  ${mx[1]} { text-align: right; }
`

const MeetingsLink = Box.extend.attrs({
  bg: 'white',
  color: 'fuschia.5',
  f: 4,
  px: 4,
  py: 3,
  my: 3
})`
  border-radius: 4rem;
  font-weight: bold;
  line-height: 1;
  text-decoration: none;
`

const CardBase = Container.extend.attrs({ bg: 'fuschia.0', p: 3, mt: 3 })`
  border-radius: .25rem;
  box-shadow: 0 2px 16px 2px rgba(0,0,0,.1);
  max-width: 28rem;
  text-align: left;

  ${mx[1]} { transform: rotate(2deg); }

  p {
    color: ${cx('slate')};
    font-size: 1rem;
    line-height: 1.375;
    margin-top: .5rem;
  }
`
const Card = ({ name, children, ...props }) => (
  <CardBase {...props}>
    <Subhead color="fuschia.5" m={0} f={3} children={name} />
    {children}
  </CardBase>
)

const CTASection = Box.extend.attrs({ is: 'section', px: 3, mt: 4, mb: 2 })`
  a {
    font-size: 1.5rem;
    ${mx[1]} { font-size: 1.75rem; }
  }
`

export default () => (
  <Provider theme={theme}>

      <title>Start – Hack Club</title>

    <One>

      <Heading is="h1" f={[5, 6]} mt={[4, 5]}>
        Let’s get your Hack Club started.
      </Heading>
      <Heading f={[3, 4]} my={2} style={{ fontWeight: 'normal' }}>
        The awesome coding club at your high school is coming soon.
      </Heading>
    </One>
    <Two>
      <Heading f={[4, 5]}>
        HQ provides the resources you’ll need to soar.
      </Heading>
      <Modules>
        <Module
          icon="forum"
          heading="Online community"
          body="Join our Slack and meet thousands of other club leaders and members."
        />
        <Module
          icon="chrome_reader_mode"
          heading="Curriculum"
          body="Give your members dozens of tutorials for making websites, apps, and games."
        />
        <Module
          icon="voice_chat"
          heading="Mentorship"
          body="Talk to our team for guidance and assistance whenever you need help."
        />
        <Module
          icon="description"
          heading="Structure & guidelines"
          body="Learn from hundreds of other clubs—we’ve got info, advice, and experience."
        />
        <Module
          icon="local_activity"
          heading="Local events"
          body="Attend hackathons, workshops, and other events from Hack Clubs nearby."
        />
        <Module
          icon="wallpaper"
          heading="Marketing"
          body="Get stickers, posters, and ideas for spreading the word about your club."
        />
      </Modules>
    </Two>
    <Three>
      <Flex direction={['column', 'row']} align="center">
        <LeftCol>
          <Heading f={[4, 5]}>Hack Clubs are student-led.</Heading>
          <Text f={[3, 4]}>
            Each club meets weekly after school
at their high school.
          </Text>
          <MeetingsLink is={Link} to="/meetings" mt={4}>
            Explore meetings →
          </MeetingsLink>
        </LeftCol>
        <Card name="Are you a teacher or parent?">
          <Text>
            We hate to say it, but we’re currently only accepting applications
            from students.
          </Text>
          <Text>
            Teachers and parents can help by recruiting students, sharing Hack
            Club with the local PTA, and expressing interest in Hack Club to
            school administration.
          </Text>
          <Text>
            That said, shoot us an email at{' '}

              contact@hackclub.com
            {' '}
            and we’d really love to help where we can.
          </Text>
        </Card>
      </Flex>
    </Three>
    <Four>
      <Heading f={[4, 5]}>It’s time to submit your application.</Heading>
      <Modules>
        <Module
          icon="assignment"
          heading="Submit your application"
          body="Fill out your contact info and a few questions to get going."
        />
        <Module
          icon="ring_volume"
          heading="Training call"
          body="We’ll start getting to know you and making a plan for your club."
        />
        <Module
          icon="event_available"
          heading="Lead your club!"
          body="Schedule your first meeting, start marketing, and get ready!"
        />
      </Modules>
      <CTASection>
        <CTA to="/apply" bg="white" color="primary">
          Apply to Hack Club
        </CTA>
      </CTASection>
    </Four>

  </Provider>
)
<commit_msg>Mention that it's free<commit_after>import React, { Fragment } from 'react'
import {
  Provider,
  Heading,
  Lead,
  Container,
  Flex,
  Box,
  Text,
  Subhead,
  Link as A
} from 'rebass'
import theme, { colors, cx, mx, mm } from '../theme'
import { Head, Link } from 'react-static'
import Nav from '../components/Nav'
import CTA from '../components/CTA'
import Icon from '../components/Icon'
import Footer from '../components/Footer'

const Section = Flex.extend.attrs({
  is: 'section',
  align: 'center',
  justify: 'center',
  direction: 'column',
  color: 'white',
  py: [4, 5],
  px: 3
})`
  text-align: center;
`
const One = Section.extend`
  padding-top: 0 !important;
  background-color: ${cx('red.5')};
  background-image: linear-gradient(
    16deg,
    ${cx('orange.4')} 0%,
    ${cx('red.5')} 50%,
    ${cx('red.6')} 100%
  );
`
const Two = Section.extend`
  background-color: ${cx('blue.6')};
  background-image: linear-gradient(
    16deg,
    ${cx('blue.6')} 0%,
    ${cx('blue.5')} 50%,
    ${cx('indigo.4')} 100%
  );
`
const Three = Section.extend`
  background-color: ${cx('fuschia.5')};
  background-image: linear-gradient(
    -32deg,
    ${cx('fuschia.5')} 0%,
    ${cx('fuschia.6')} 50%,
    ${cx('pink.4')} 100%
  );
`
const Four = Section.extend`
  background-color: ${cx('violet.6')};
  background-image: linear-gradient(
    48deg,
    ${cx('violet.5')} 0%,
    ${cx('violet.6')} 50%,
    ${cx('indigo.4')} 100%
  );
`

const Modules = Flex.extend.attrs({
  wrap: true,
  justify: 'center',
  mt: 3
})`
  ${mm[1]} {
    text-align: left;
  }
`

const ModuleBase = Flex.extend.attrs({
  w: [1, 1 / 3],
  p: 2,
  direction: ['row', 'column'],
  align: ['flex-start', 'center']
})`
  img {
    width: 3rem !important;
    height: 3rem !important;
    flex-shrink: 0;
    margin-right: 1rem;
  }

  ${mx[1]} {
    max-width: 20rem;
    img { margin-right: 0; }
  }
`

const ModuleHeading = Subhead.extend.attrs({ mt: 0, mb: 1, f: 3 })``
const ModuleBody = Text.extend.attrs({ my: 0, f: 2 })`
  line-height: 1.5;
  position: relative;
`

const Module = ({ icon, heading, body, ...props }) => (
  <ModuleBase>
    <Icon name={icon} fill="white" />

      <ModuleHeading children={heading} />
      <ModuleBody children={body} />

  </ModuleBase>
)

const LeftCol = Flex.extend.attrs({
  direction: 'column',
  align: ['center', 'flex-end'],
  mr: [0, 4]
})`
  ${mx[1]} { text-align: right; }
`

const MeetingsLink = Box.extend.attrs({
  bg: 'white',
  color: 'fuschia.5',
  f: 4,
  px: 4,
  py: 3,
  my: 3
})`
  border-radius: 4rem;
  font-weight: bold;
  line-height: 1;
  text-decoration: none;
`

const CardBase = Container.extend.attrs({ bg: 'fuschia.0', p: 3, mt: 3 })`
  border-radius: .25rem;
  box-shadow: 0 2px 16px 2px rgba(0,0,0,.1);
  max-width: 28rem;
  text-align: left;

  ${mx[1]} { transform: rotate(2deg); }

  p {
    color: ${cx('slate')};
    font-size: 1rem;
    line-height: 1.375;
    margin-top: .5rem;
  }
`
const Card = ({ name, children, ...props }) => (
  <CardBase {...props}>
    <Subhead color="fuschia.5" m={0} f={3} children={name} />
    {children}
  </CardBase>
)

const CTASection = Box.extend.attrs({ is: 'section', px: 3, mt: 4, mb: 2 })`
  a {
    font-size: 1.5rem;
    ${mx[1]} { font-size: 1.75rem; }
  }
`

export default () => (
  <Provider theme={theme}>

      <title>Start – Hack Club</title>

    <One>

      <Heading is="h1" f={[5, 6]} mt={[4, 5]}>
        Let’s get your Hack Club started.
      </Heading>
      <Heading f={[3, 4]} my={2} style={{ fontWeight: 'normal' }}>
        The awesome coding club at your high school is coming soon.
      </Heading>
    </One>
    <Two>
      <Heading f={[4, 5]}>
        HQ provides the resources you’ll need to soar.
      </Heading>
      <Modules>
        <Module
          icon="forum"
          heading="Online community"
          body="Join our Slack and meet thousands of other club leaders and members."
        />
        <Module
          icon="chrome_reader_mode"
          heading="Curriculum"
          body="Give your members dozens of tutorials for making websites, apps, and games."
        />
        <Module
          icon="voice_chat"
          heading="Mentorship"
          body="Talk to our team for guidance and assistance whenever you need help."
        />
        <Module
          icon="description"
          heading="Structure & guidelines"
          body="Learn from hundreds of other clubs—we’ve got info, advice, and experience."
        />
        <Module
          icon="local_activity"
          heading="Local events"
          body="Attend hackathons, workshops, and other events from Hack Clubs nearby."
        />
        <Module
          icon="wallpaper"
          heading="Marketing"
          body="Get stickers, posters, and ideas for spreading the word about your club."
        />
      </Modules>
    </Two>
    <Three>
      <Flex direction={['column', 'row']} align="center">
        <LeftCol>
          <Heading f={[4, 5]}>Hack Clubs are student-led.</Heading>
          <Text f={[3, 4]}>
            Each club meets weekly after school
at their high school.
          </Text>
          <MeetingsLink is={Link} to="/meetings" mt={4}>
            Explore meetings →
          </MeetingsLink>
        </LeftCol>
        <Card name="Are you a teacher or parent?">
          <Text>
            We hate to say it, but we’re currently only accepting applications
            from students.
          </Text>
          <Text>
            Teachers and parents can help by recruiting students, sharing Hack
            Club with the local PTA, and expressing interest in Hack Club to
            school administration.
          </Text>
          <Text>
            That said, shoot us an email at{' '}

              contact@hackclub.com
            {' '}
            and we’d really love to help where we can.
          </Text>
        </Card>
      </Flex>
    </Three>
    <Four>
      <Heading f={[4, 5]}>It’s time to submit your application.</Heading>
      <Modules>
        <Module
          icon="assignment"
          heading="Submit your application"
          body="Fill out a few questions to get going—totally free."
        />
        <Module
          icon="ring_volume"
          heading="Training call"
          body="We’ll start getting to know you and making a plan for your club."
        />
        <Module
          icon="event_available"
          heading="Lead your club!"
          body="Schedule your first meeting, start marketing, and get ready!"
        />
      </Modules>
      <CTASection>
        <CTA to="/apply" bg="white" color="primary">
          Apply to Hack Club
        </CTA>
      </CTASection>
    </Four>

  </Provider>
)
<|endoftext|>


<commit_before>import { getRowCol } from '../shared/cellHelpers'

/**
 * Abstract base class for a Stencila execution context
 *
 * Defines the Stencila `Context` API. The same methods (names and arguments) will be
 * implemented for all contexts regardless of implementation language. Semantics should be
 * consistent, but may need to differ, among implmentations.
 *
 * This class should be extended for JavaScript implementations. All methods return a Promise.
 */
export default class Context {

  /**
   * Get the list of supported programming languages
   *
   * @override
   */
  supportedLanguages () {
    return Promise.resolve(new Error('Not implemented'))
  }

  /**
   * Analyse code and return the names of inputs, output and
   * implicitly returned value expression
   *
   * @param {string} code - Code to execute
   * @param {object} exprOnly - Check that code is a simple expression only?
   */
  analyseCode (code, exprOnly = false) { // eslint-disable-line no-unused-vars
    // TODO: we want to have a general implementation
    // dealing with cell references and range expressions
    // transpiling the code so that it is syntactically
    // correct in the target language
    let symbols = {}
    code = this._transpile (code, symbols)
    return this._analyseCode(code, exprOnly)
    .then((res) => {
      // Note: external contexts can only analyse
      // input variables, so we have transpiled the code
      // before, and now need to map back
      if (res.inputs) {
        res.inputs = res.inputs.map((name) => {
          if (symbols[name]) {
            return symbols[name]
          } else {
            return {
              type: 'var',
              name
            }
          }
        })
      }
      return res
    })
  }

  _transpile (code, symbols) {
    // TODO: this needs to be maintained carefully
    // to be consistent with the code below
    let re = /\b([A-Z]+[1-9][0-9]*)([:]([A-Z]+[1-9][0-9]*))?/g
    let m
    while ((m = re.exec(code))) {
      let type
      let name
      if (m[3]) {
        type = 'range'
      } else if (m[1]) {
        type = 'cell'
      }
      switch (type) {
        case 'range': {
          let [startRow, startCol] = getRowCol(m[1])
          let [endRow, endCol] = getRowCol(m[3])
          name = `${m[1]}_${m[3]}`
          symbols[name] = {
            type, name,
            startRow, startCol, endRow, endCol
          }
          break
        }
        case 'cell': {
          let [row, col] = getRowCol(m[1])
          name = m[1]
          symbols[name] = {
            type, name,
            row, col
          }
          break
        }
        default:
          console.error('FIXME: invalid type')
          continue
      }
      code = code.substring(0, m.index) + name + code.substring(m.index+name.length)
    }
    return code
  }

  _analyseCode (code, exprOnly) { // eslint-disable-line
    return Promise.reject(new Error('Not implemented'))
  }

  /**
   * Execute code within the context
   *
   * @param {string} code - Code to execute
   * @param {object} inputs - Value of input variables
   * @param {object} exprOnly - Check that code is a simple expression only?
   */
  executeCode (code = '', inputs = {}, exprOnly = false) { // eslint-disable-line no-unused-vars
    // TODO: we want to have a general implementation
    // dealing with cell references and range expressions
    // transpiling the code so that it is syntactically
    // correct in the target language
    let symbols = {}
    code = this._transpile (code, symbols)
    return this._executeCode(code, inputs, exprOnly)
    .then((res) => {
      // Note: external contexts can only analyse
      // input variables, so we have transpiled the code
      // before, and now need to map back
      if (res.inputs) {
        res.inputs = res.inputs.map((name) => {
          if (symbols[name]) {
            return symbols[name]
          } else {
            return {
              type: 'var',
              name
            }
          }
        })
      }
      return res
    })
  }

  _executeCode (code = '', inputs = {}, exprOnly = false) { // eslint-disable-line no-unused-vars
    return Promise.reject(new Error('Not implemented'))
  }

  /**
   * Does the context provide a function?
   *
   * @param  {string} name - Function name e.g. 'sum'
   * @return {array<string>} - A Promise resolving to a boolean value
   */
  hasFunction (name) {  // eslint-disable-line no-unused-vars
    return Promise.reject(new Error('Not implemented'))
  }

  /**
   * Call a function
   *
   *
   * @param  {string} name - Function name e.g. 'sum'
   * @param {array} args - An array of unnamed arguments
   * @param {namedArgs} args - An object of named arguments
   * @param {object} options - Any execution options
   * @return {array<string>} - A Promise resolving to an object with any `errors` (an object with line numbers as keys) and `outputs` (
   *                         a data package)
   */
  callFunction (name, args, namedArgs, options) {  // eslint-disable-line no-unused-vars
    return Promise.reject(new Error('Not implemented'))
  }

}
<commit_msg>Simplify Context.<commit_after>import { getRowCol } from '../shared/cellHelpers'
import transpile from '../shared/transpile'

/**
 * Abstract base class for a Stencila execution context
 *
 * Defines the Stencila `Context` API. The same methods (names and arguments) will be
 * implemented for all contexts regardless of implementation language. Semantics should be
 * consistent, but may need to differ, among implmentations.
 *
 * This class should be extended for JavaScript implementations. All methods return a Promise.
 */
export default class Context {

  /**
   * Get the list of supported programming languages
   *
   * @override
   */
  supportedLanguages () {
    return Promise.resolve(new Error('Not implemented'))
  }

  /**
   * Analyse code and return the names of inputs, output and
   * implicitly returned value expression
   *
   * @param {string} code - Code to execute
   * @param {object} exprOnly - Check that code is a simple expression only?
   */
  analyseCode (code, exprOnly = false) { // eslint-disable-line no-unused-vars
    // transpiling the code so that it is syntactically correct in the target language
    let symbols = {}
    const transpiledCode = transpile(code, symbols)
    return this._analyseCode(transpiledCode, exprOnly)
    .then((res) => {
      // map transpiled symbols back to their original form
      if (res.inputs) {
        res.inputs = res.inputs.map(name => symbols[name]||name)
      }
      return res
    })
  }

  /**
   * Execute code within the context
   *
   * @param {string} code - Code to execute
   * @param {object} inputs - Value of input variables
   * @param {object} exprOnly - Check that code is a simple expression only?
   */
  executeCode (code = '', inputs = {}, exprOnly = false) { // eslint-disable-line no-unused-vars
    // transpiling the code so that it is syntactically correct in the target language
    let symbols = {}
    const transpiledCode = transpile(code, symbols)
    return this._executeCode(code, inputs, exprOnly)
    .then((res) => {
      // map transpiled symbols back to their original form
      if (res.inputs) {
        res.inputs = res.inputs.map(name => symbols[name]||name)
      }
      return res
    })
  }

  /**
   * Does the context provide a function?
   *
   * @param  {string} name - Function name e.g. 'sum'
   * @return {array<string>} - A Promise resolving to a boolean value
   */
  hasFunction (name) {  // eslint-disable-line no-unused-vars
    return Promise.reject(new Error('Not implemented'))
  }

  /**
   * Call a function
   *
   *
   * @param  {string} name - Function name e.g. 'sum'
   * @param {array} args - An array of unnamed arguments
   * @param {namedArgs} args - An object of named arguments
   * @param {object} options - Any execution options
   * @return {array<string>} - A Promise resolving to an object with any `errors` (an object with line numbers as keys) and `outputs` (
   *                         a data package)
   */
  callFunction (name, args, namedArgs, options) {  // eslint-disable-line no-unused-vars
    return Promise.reject(new Error('Not implemented'))
  }

  _analyseCode (code, exprOnly) { // eslint-disable-line
    return Promise.reject(new Error('Not implemented'))
  }

  _executeCode (code = '', inputs = {}, exprOnly = false) { // eslint-disable-line no-unused-vars
    return Promise.reject(new Error('Not implemented'))
  }
}
<|endoftext|>


<commit_before>// Copright 2015 A Medium Corporation

var https = require('https')
var qs = require('querystring')
var url = require('url')
var util = require('util')

var DEFAULT_ERROR_CODE = -1
var DEFAULT_TIMEOUT_MS = 5000

/**
 * Valid scope options.
 * @enum {string}
 */
var Scope = {
  BASIC_PROFILE: 'basicProfile',
  LIST_PUBLICATIONS: 'listPublications',
  PUBLISH_POST: 'publishPost'
}

/**
 * The publish status when creating a post.
 * @enum {string}
 */
var PostPublishStatus = {
  DRAFT: 'draft',
  UNLISTED: 'unlisted',
  PUBLIC: 'public'
}

/**
 * The content format to use when creating a post.
 * @enum {string}
 */
var PostContentFormat = {
  HTML: 'html',
  MARKDOWN: 'markdown'
}

/**
 * The license to use when creating a post.
 * @enum {string}
 */
var PostLicense = {
  ALL_RIGHTS_RESERVED: 'all-rights-reserved',
  CC_40_BY: 'cc-40-by',
  CC_40_BY_ND: 'cc-40-by-nd',
  CC_40_BY_SA: 'cc-40-by-sa',
  CC_40_BY_NC: 'cc-40-by-nc',
  CC_40_BY_NC_ND: 'cc-40-by-nc-nd',
  CC_40_BY_NC_SA: 'cc-40-by-nc-sa',
  CC_40_ZERO: 'cc-40-zero',
  PUBLIC_DOMAIN: 'public-domain'
}

/**
 * An error with a code.
 *
 * @param {string} message
 * @param {number} code
 * @constructor
 */
function MediumError(message, code) {
  this.message = message
  this.code = code
}
util.inherits(MediumError, Error)

/**
 * The core client.
 *
 * @param {{
 *  clientId: string,
 *  clientSecret: string
 * }} options
 * @constructor
 */
function MediumClient(options) {
  this._enforce(options, ['clientId', 'clientSecret'])
  this._clientId = options.clientId
  this._clientSecret = options.clientSecret
  this._accessToken = ""
}

/**
 * Sets an access token on the client used for making requests.
 *
 * @param {string} accessToken
 * @return {MediumClient}
 */
MediumClient.prototype.setAccessToken = function (accessToken) {
  this._accessToken = accessToken
  return this
}

/**
 * Builds a URL at which you may request authorization from the user.
 *
 * @param {string} state
 * @param {string} redirectUrl
 * @param {Array.<Scope>} scope
 * @return {string}
 */
MediumClient.prototype.getAuthorizationUrl = function (state, redirectUrl, requestedScope) {
  return url.format({
    protocol: 'https',
    host: 'medium.com',
    pathname: '/m/oauth/authorize',
    query: {
      client_id: this._clientId,
      scope: requestedScope.join(','),
      response_type: 'code',
      state: state,
      redirect_uri: redirectUrl
    }
  })
}

/**
 * Exchanges an authorization code for an access token and a refresh token.
 *
 * @param {string} code
 * @param {string} redirectUrl
 * @param {NodeCallback} callback
 */
MediumClient.prototype.exchangeAuthorizationCode = function (code, redirectUrl, callback) {
  this._acquireAccessToken({
    code: code,
    client_id: this._clientId,
    client_secret: this._clientSecret,
    grant_type: 'authorization_code',
    redirect_uri: redirectUrl
  }, callback)
}

/**
 * Exchanges a refresh token for an access token and a refresh token.
 *
 * @param {string} refreshToken
 * @param {NodeCallback} callback
 */
MediumClient.prototype.exchangeRefreshToken = function (refreshToken, callback) {
  this._acquireAccessToken({
    refresh_token: refreshToken,
    client_id: this._clientId,
    client_secret: this._clientSecret,
    grant_type: 'refresh_token'
  }, callback)
}

/**
 * Returns the details of the user associated with the current
 * access token.
 *
 * Requires the current access token to have the basicProfile scope.
 *
 * @param {NodeCallback} callback
 */
MediumClient.prototype.getUser = function (callback) {
  this._makeRequest({
    method: 'GET',
    path: '/v1/me'
  }, callback)
}

/**
 * Returns the publications related to the current user. Notice that
 * the userId needs to be passed in as an option. It can be acquired
 * with a call to getUser().
 *
 * Requires the current access token to have the
 * listPublications scope.
 *
 * @param {{
 *  userId: string
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.getPublicationsForUser = function (options, callback) {
  this._enforce(options, ['userId'])
  this._makeRequest({
    method: 'GET',
    path: '/v1/users/' + options.userId + '/publications'
  }, callback)
}

/**
 * Returns the contributors for a chosen publication. The publication is identified
 * by the publication ID included in the options argument. IDs for publications
 * can be acquired by getUsersPublications.
 *
 * Requires the current access token to have the basicProfile scope.
 *
 * @param {{
 *  publicationId: string
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.getContributorsForPublication = function (options, callback) {
  this._enforce(options, ['publicationId'])
  this._makeRequest({
    method: 'GET',
    path: '/v1/publications/' + options.publicationId + '/contributors'
  }, callback)
}

/**
 * Creates a post on Medium.
 *
 * Requires the current access token to have the publishPost scope.
 *
 * @param {{
 *  userId: string,
 *  title: string,
 *  contentFormat: PostContentFormat,
 *  content: string,
 *  tags: Array.<string>,
 *  canonicalUrl: string,
 *  publishStatus: PostPublishStatus,
 *  license: PostLicense
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.createPost = function (options, callback) {
  this._enforce(options, ['userId'])
  this._makeRequest({
    method: 'POST',
    path: '/v1/users/' + options.userId + '/posts',
    data: {
      title: options.title,
      content: options.content,
      contentFormat: options.contentFormat,
      tags: options.tags,
      canonicalUrl: options.canonicalUrl,
      publishStatus: options.publishStatus,
      license: options.license
    }
  }, callback)
}

/**
 * Creates a post on Medium and places it under specified publication.
 * Please refer to the API documentation for rules around publishing in
 * a publication: https://github.com/Medium/medium-api-docs
 *
 * Requires the current access token to have the publishPost scope.
 *
 * @param {{
 *  userId: string,
 *  publicationId: string,
 *  title: string,
 *  contentFormat: PostContentFormat,
 *  content: string,
 *  tags: Array.<string>,
 *  canonicalUrl: string,
 *  publishStatus: PostPublishStatus,
 *  license: PostLicense
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.createPostInPublication = function (options, callback) {
  this._enforce(options, ['publicationId'])
  this._makeRequest({
    method: 'POST',
    path: '/v1/publications/' + options.publicationId + '/posts',
    data: {
      title: options.title,
      content: options.content,
      contentFormat: options.contentFormat,
      tags: options.tags,
      canonicalUrl: options.canonicalUrl,
      publishStatus: options.publishStatus,
      license: options.license
    }
  }, callback)
}

/**
 * Acquires an access token for the Medium API.
 *
 * Sets the access token on the client on success.
 *
 * @param {Object} params
 * @param {NodeCallback} callback
 */
MediumClient.prototype._acquireAccessToken = function (params, callback) {
  this._makeRequest({
    method: 'POST',
    path: '/v1/tokens',
    contentType: 'application/x-www-form-urlencoded',
    data: qs.stringify(params)
  }, function (err, data) {
    if (!err) {
      this._accessToken = data.access_token
    }
    callback(err, data)
  }.bind(this))
}

/**
 * Enforces that given options object (first param) defines
 * all keys requested (second param). Raises an error if any
 * is missing.
 *
 * @param {Object} options
 * @param {keys} requiredKeys
 */
MediumClient.prototype._enforce = function (options, requiredKeys) {
  if (!options) {
    throw new MediumError('Parameters for this call are undefined', DEFAULT_ERROR_CODE)
  }
  requiredKeys.forEach(function (requiredKey) {
    if (!options[requiredKey]) throw new MediumError('Missing required parameter "' + requiredKey + '"', DEFAULT_ERROR_CODE)
  })
}

/**
 * Makes a request to the Medium API.
 *
 * @param {Object} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype._makeRequest = function (options, callback) {
  var requestParams = {
    host: 'api.medium.com',
    port: 443,
    method: options.method,
    path: options.path
  }
  var req = https.request(requestParams, function (res) {
    var body = []

    res.setEncoding('utf-8')
    res.on('data', function (data) {
      body.push(data)
    })
    res.on('end', function () {
      var payload
      var responseText = body.join('')
      try {
        payload = JSON.parse(responseText)
      } catch (err) {
        callback(new MediumError('Failed to parse response', DEFAULT_ERROR_CODE), null)
        return
      }

      var statusCode = res.statusCode
      var statusType = Math.floor(res.statusCode / 100)

      if (statusType == 4 || statusType == 5) {
        var err = payload.errors[0]
        callback(new MediumError(err.message, err.code), null)
      } else if (statusType == 2) {
        callback(null, payload.data || payload)
      } else {
        callback(new MediumError('Unexpected response', DEFAULT_ERROR_CODE), null)
      }
    })
  }).on('error', function (err) {
    callback(new MediumError(err.message, DEFAULT_ERROR_CODE), null)
  })

  req.setHeader('Content-Type', options.contentType || 'application/json')
  req.setHeader('Authorization', 'Bearer ' + this._accessToken)
  req.setHeader('Accept', 'application/json')
  req.setHeader('Accept-Charset', 'utf-8')

  req.setTimeout(DEFAULT_TIMEOUT_MS, function () {
    // Aborting a request triggers the 'error' event.
    req.abort()
  })

  if (options.data) {
    var data = options.data
    if (typeof data == 'object') {
      data = JSON.stringify(data)
    }
    req.write(data)
  }
  req.end()
}

// Exports

module.exports = {
  MediumClient: MediumClient,
  Scope: Scope,
  PostPublishStatus: PostPublishStatus,
  PostLicense: PostLicense,
  PostContentFormat: PostContentFormat
}
<commit_msg>Just a typo change - Documentation review<commit_after>// Copright 2015 A Medium Corporation

var https = require('https')
var qs = require('querystring')
var url = require('url')
var util = require('util')

var DEFAULT_ERROR_CODE = -1
var DEFAULT_TIMEOUT_MS = 5000

/**
 * Valid scope options.
 * @enum {string}
 */
var Scope = {
  BASIC_PROFILE: 'basicProfile',
  LIST_PUBLICATIONS: 'listPublications',
  PUBLISH_POST: 'publishPost'
}

/**
 * The publish status when creating a post.
 * @enum {string}
 */
var PostPublishStatus = {
  DRAFT: 'draft',
  UNLISTED: 'unlisted',
  PUBLIC: 'public'
}

/**
 * The content format to use when creating a post.
 * @enum {string}
 */
var PostContentFormat = {
  HTML: 'html',
  MARKDOWN: 'markdown'
}

/**
 * The license to use when creating a post.
 * @enum {string}
 */
var PostLicense = {
  ALL_RIGHTS_RESERVED: 'all-rights-reserved',
  CC_40_BY: 'cc-40-by',
  CC_40_BY_ND: 'cc-40-by-nd',
  CC_40_BY_SA: 'cc-40-by-sa',
  CC_40_BY_NC: 'cc-40-by-nc',
  CC_40_BY_NC_ND: 'cc-40-by-nc-nd',
  CC_40_BY_NC_SA: 'cc-40-by-nc-sa',
  CC_40_ZERO: 'cc-40-zero',
  PUBLIC_DOMAIN: 'public-domain'
}

/**
 * An error with a code.
 *
 * @param {string} message
 * @param {number} code
 * @constructor
 */
function MediumError(message, code) {
  this.message = message
  this.code = code
}
util.inherits(MediumError, Error)

/**
 * The core client.
 *
 * @param {{
 *  clientId: string,
 *  clientSecret: string
 * }} options
 * @constructor
 */
function MediumClient(options) {
  this._enforce(options, ['clientId', 'clientSecret'])
  this._clientId = options.clientId
  this._clientSecret = options.clientSecret
  this._accessToken = ""
}

/**
 * Sets an access token on the client used for making requests.
 *
 * @param {string} accessToken
 * @return {MediumClient}
 */
MediumClient.prototype.setAccessToken = function (accessToken) {
  this._accessToken = accessToken
  return this
}

/**
 * Builds a URL at which you may request authorization from the user.
 *
 * @param {string} state
 * @param {string} redirectUrl
 * @param {Array.<Scope>} requestedScope
 * @return {string}
 */
MediumClient.prototype.getAuthorizationUrl = function (state, redirectUrl, requestedScope) {
  return url.format({
    protocol: 'https',
    host: 'medium.com',
    pathname: '/m/oauth/authorize',
    query: {
      client_id: this._clientId,
      scope: requestedScope.join(','),
      response_type: 'code',
      state: state,
      redirect_uri: redirectUrl
    }
  })
}

/**
 * Exchanges an authorization code for an access token and a refresh token.
 *
 * @param {string} code
 * @param {string} redirectUrl
 * @param {NodeCallback} callback
 */
MediumClient.prototype.exchangeAuthorizationCode = function (code, redirectUrl, callback) {
  this._acquireAccessToken({
    code: code,
    client_id: this._clientId,
    client_secret: this._clientSecret,
    grant_type: 'authorization_code',
    redirect_uri: redirectUrl
  }, callback)
}

/**
 * Exchanges a refresh token for an access token and a refresh token.
 *
 * @param {string} refreshToken
 * @param {NodeCallback} callback
 */
MediumClient.prototype.exchangeRefreshToken = function (refreshToken, callback) {
  this._acquireAccessToken({
    refresh_token: refreshToken,
    client_id: this._clientId,
    client_secret: this._clientSecret,
    grant_type: 'refresh_token'
  }, callback)
}

/**
 * Returns the details of the user associated with the current
 * access token.
 *
 * Requires the current access token to have the basicProfile scope.
 *
 * @param {NodeCallback} callback
 */
MediumClient.prototype.getUser = function (callback) {
  this._makeRequest({
    method: 'GET',
    path: '/v1/me'
  }, callback)
}

/**
 * Returns the publications related to the current user. Notice that
 * the userId needs to be passed in as an option. It can be acquired
 * with a call to getUser().
 *
 * Requires the current access token to have the
 * listPublications scope.
 *
 * @param {{
 *  userId: string
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.getPublicationsForUser = function (options, callback) {
  this._enforce(options, ['userId'])
  this._makeRequest({
    method: 'GET',
    path: '/v1/users/' + options.userId + '/publications'
  }, callback)
}

/**
 * Returns the contributors for a chosen publication. The publication is identified
 * by the publication ID included in the options argument. IDs for publications
 * can be acquired by getUsersPublications.
 *
 * Requires the current access token to have the basicProfile scope.
 *
 * @param {{
 *  publicationId: string
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.getContributorsForPublication = function (options, callback) {
  this._enforce(options, ['publicationId'])
  this._makeRequest({
    method: 'GET',
    path: '/v1/publications/' + options.publicationId + '/contributors'
  }, callback)
}

/**
 * Creates a post on Medium.
 *
 * Requires the current access token to have the publishPost scope.
 *
 * @param {{
 *  userId: string,
 *  title: string,
 *  contentFormat: PostContentFormat,
 *  content: string,
 *  tags: Array.<string>,
 *  canonicalUrl: string,
 *  publishStatus: PostPublishStatus,
 *  license: PostLicense
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.createPost = function (options, callback) {
  this._enforce(options, ['userId'])
  this._makeRequest({
    method: 'POST',
    path: '/v1/users/' + options.userId + '/posts',
    data: {
      title: options.title,
      content: options.content,
      contentFormat: options.contentFormat,
      tags: options.tags,
      canonicalUrl: options.canonicalUrl,
      publishStatus: options.publishStatus,
      license: options.license
    }
  }, callback)
}

/**
 * Creates a post on Medium and places it under specified publication.
 * Please refer to the API documentation for rules around publishing in
 * a publication: https://github.com/Medium/medium-api-docs
 *
 * Requires the current access token to have the publishPost scope.
 *
 * @param {{
 *  userId: string,
 *  publicationId: string,
 *  title: string,
 *  contentFormat: PostContentFormat,
 *  content: string,
 *  tags: Array.<string>,
 *  canonicalUrl: string,
 *  publishStatus: PostPublishStatus,
 *  license: PostLicense
 * }} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype.createPostInPublication = function (options, callback) {
  this._enforce(options, ['publicationId'])
  this._makeRequest({
    method: 'POST',
    path: '/v1/publications/' + options.publicationId + '/posts',
    data: {
      title: options.title,
      content: options.content,
      contentFormat: options.contentFormat,
      tags: options.tags,
      canonicalUrl: options.canonicalUrl,
      publishStatus: options.publishStatus,
      license: options.license
    }
  }, callback)
}

/**
 * Acquires an access token for the Medium API.
 *
 * Sets the access token on the client on success.
 *
 * @param {Object} params
 * @param {NodeCallback} callback
 */
MediumClient.prototype._acquireAccessToken = function (params, callback) {
  this._makeRequest({
    method: 'POST',
    path: '/v1/tokens',
    contentType: 'application/x-www-form-urlencoded',
    data: qs.stringify(params)
  }, function (err, data) {
    if (!err) {
      this._accessToken = data.access_token
    }
    callback(err, data)
  }.bind(this))
}

/**
 * Enforces that given options object (first param) defines
 * all keys requested (second param). Raises an error if any
 * is missing.
 *
 * @param {Object} options
 * @param {keys} requiredKeys
 */
MediumClient.prototype._enforce = function (options, requiredKeys) {
  if (!options) {
    throw new MediumError('Parameters for this call are undefined', DEFAULT_ERROR_CODE)
  }
  requiredKeys.forEach(function (requiredKey) {
    if (!options[requiredKey]) throw new MediumError('Missing required parameter "' + requiredKey + '"', DEFAULT_ERROR_CODE)
  })
}

/**
 * Makes a request to the Medium API.
 *
 * @param {Object} options
 * @param {NodeCallback} callback
 */
MediumClient.prototype._makeRequest = function (options, callback) {
  var requestParams = {
    host: 'api.medium.com',
    port: 443,
    method: options.method,
    path: options.path
  }
  var req = https.request(requestParams, function (res) {
    var body = []

    res.setEncoding('utf-8')
    res.on('data', function (data) {
      body.push(data)
    })
    res.on('end', function () {
      var payload
      var responseText = body.join('')
      try {
        payload = JSON.parse(responseText)
      } catch (err) {
        callback(new MediumError('Failed to parse response', DEFAULT_ERROR_CODE), null)
        return
      }

      var statusCode = res.statusCode
      var statusType = Math.floor(res.statusCode / 100)

      if (statusType == 4 || statusType == 5) {
        var err = payload.errors[0]
        callback(new MediumError(err.message, err.code), null)
      } else if (statusType == 2) {
        callback(null, payload.data || payload)
      } else {
        callback(new MediumError('Unexpected response', DEFAULT_ERROR_CODE), null)
      }
    })
  }).on('error', function (err) {
    callback(new MediumError(err.message, DEFAULT_ERROR_CODE), null)
  })

  req.setHeader('Content-Type', options.contentType || 'application/json')
  req.setHeader('Authorization', 'Bearer ' + this._accessToken)
  req.setHeader('Accept', 'application/json')
  req.setHeader('Accept-Charset', 'utf-8')

  req.setTimeout(DEFAULT_TIMEOUT_MS, function () {
    // Aborting a request triggers the 'error' event.
    req.abort()
  })

  if (options.data) {
    var data = options.data
    if (typeof data == 'object') {
      data = JSON.stringify(data)
    }
    req.write(data)
  }
  req.end()
}

// Exports

module.exports = {
  MediumClient: MediumClient,
  Scope: Scope,
  PostPublishStatus: PostPublishStatus,
  PostLicense: PostLicense,
  PostContentFormat: PostContentFormat
}
<|endoftext|>


<commit_before>
var createMeteorProcessManager = require('./meteorProcessManager');
var createDDPClientManager     = require('../ddp/ddpClientManager');
var BuildAsPromise             = require('./build');
var MongoDatabase              = require('../mongo/database');
var meteorMethods              = require('./methods');
var Promise                    = require('es6-promise').Promise;
var Closure                    = require('../tools/closure');
var generic                    = require('../tools/generic');
var tools                      = require('../tools');
var url                        = require('url');

module.exports = function createMeteor (options) {
  "use strict";

  options = options || {};

  if (typeof options === 'string') {
    options = { pathToApp: options };
  }

  var pathToApp       = options.pathToApp || path.resolve('.');
  var skipBuild       = !!options.skipBuild;

  var remoteServer    = options.remoteServer ? url.parse(options.remoteServer) : null;
  var mongoUrlPromise = null;
  var databasePromise = null;

  var uniqueCode = Math.random();

  if (typeof options.mongoUrl === 'string') {
    mongoUrlPromise = Promise.resolve(options.mongoUrl);

  } else if (options.mongoUrl && options.mongoUrl.then) {
    mongoUrlPromise = options.mongoUrl;

  } else if (options.mongoUrl) {
    throw new Error('mongoUrl must be a string or a promise returning a string');
  }

  if (!mongoUrlPromise && !remoteServer) {
    databasePromise = new MongoDatabase({ pathToApp: pathToApp });
    mongoUrlPromise = databasePromise.getMongoUrlPromise();
  }

  var helpers = options.helpers || {};

  var myPrototype = Object.create(helpers);

  myPrototype.init = function () {
    return this.branch().then(function () {
      // ...
    });
  }

  myPrototype.start = function () {
    return this.__custom__(function (operand, done) {
      done();
    });
  }

  myPrototype.stop = function () {
    return this.__custom__(function (operand, done) {

      operand.ddpClient.close();

      if (!operand.process) { // e.g. if using remote server
        return done();
      }

      operand.process.kill(function (err) {
        if (err) {
          done(err);
        } else if (databasePromise) {
          databasePromise.then(function (db) {
            db.cleanUp(done);
          }).catch(done);
        }
      });
    });
  }

  // TODO: think if this can be implemented outside the manager

  //myPrototype.restart = function (delay) {
  //  var self = this;
  //  return self.then(function () {
  //    uniqueCode = Math.random();
  //    return this.__custom__(function (operand, done) {
  //      done();
  //    });
  //  });
  //}

  var methods = [
    'restart'
  ];

  Object.keys(meteorMethods).forEach(function (name) {
    myPrototype[name] = meteorMethods[name];
  });

  var MeteorGeneric = generic(methods, myPrototype, function (operand, name, args, done) {
    if (!operand.process) {
      done(new Error('operand.process is undefined'));
    } else if (!operand.process[name]) {
      done(new Error('operand.process does not implement method: ' + name));
    } else {
      args.push(done);
      operand.process[name].apply(operand.process, args);
    }
  });

  var Meteor = function () {

    var getMeteorProcess = createMeteorProcessManager(options);
    var getDDPClient     = createDDPClientManager();
    var closure          = null;

    function getPathToMain () {
      return BuildAsPromise({ pathToApp: pathToApp, skipBuild: skipBuild });
    }

    function getMongoUrl () {
      return databasePromise.getMongoUrlPromise();
    }

    function getMeteor () {

      if (remoteServer) {
        return Promise.resolve(null);
      }

      return Promise.all([

        getPathToMain(),
        getMongoUrl(),

      ]).then(function (all) {

        var pathToMain = all[0];
        var mongoUrl   = all[1];

        return getMeteorProcess({
          pathToNode : tools.getNodePath(pathToApp),
          pathToMain : pathToMain,
          uniqueCode : uniqueCode,
          mongoUrl   : mongoUrl,
        });

      });
    }

    function operand () {

      return Promise.all([

        getDDPSetup(),
        getMeteor(),

      ]).then(function (all) {

        var setup = all[0];
        var process = all[1];

        return getDDPClient(setup).then(function (ddpClient) {
          return { ddpClient: ddpClient, process: process, closure: closure };
        });

      });
    }

    function getDDPSetup () {

      if (remoteServer) {
        return Promise.resolve({
          host: remoteServer.hostname,
          port: remoteServer.port || 443,
        });
      }

      return getMeteor().then(function (process) {
        return {
          port: process.env.PORT,
          code: process.pid,
        };
      });

    }

    this.getDDPSetup = getDDPSetup;

    MeteorGeneric.call(this, operand);

    Closure.mixin(this); // adds "useClosure" and "closure" methods
    closure = this.closure.bind(this);

  };

  Meteor.prototype = Object.create(new MeteorGeneric(), {
    methods: { value: [].concat(Object.keys(myPrototype), Object.keys(helpers), MeteorGeneric.prototype.methods) }
  });

  return new Meteor();

}
<commit_msg>Using constructors does not make sense here<commit_after>
var createMeteorProcessManager = require('./meteorProcessManager');
var createDDPClientManager     = require('../ddp/ddpClientManager');
var BuildAsPromise             = require('./build');
var MongoDatabase              = require('../mongo/database');
var meteorMethods              = require('./methods');
var Promise                    = require('es6-promise').Promise;
var Closure                    = require('../tools/closure');
var generic                    = require('../tools/generic');
var tools                      = require('../tools');
var url                        = require('url');

module.exports = function createMeteor (options) {
  "use strict";

  options = options || {};

  if (typeof options === 'string') {
    options = { pathToApp: options };
  }

  var pathToApp = options.pathToApp || path.resolve('.');
  var skipBuild = !!options.skipBuild;

  var remoteServer    = options.remoteServer ? url.parse(options.remoteServer) : null;
  var mongoUrlPromise = null;
  var databasePromise = null;

  var getMeteorProcess = createMeteorProcessManager(options);
  var getDDPClient     = createDDPClientManager();
  var closure          = null;

  if (typeof options.mongoUrl === 'string') {
    mongoUrlPromise = Promise.resolve(options.mongoUrl);

  } else if (options.mongoUrl && options.mongoUrl.then) {
    mongoUrlPromise = options.mongoUrl;

  } else if (options.mongoUrl) {
    throw new Error('mongoUrl must be a string or a promise returning a string');
  }

  if (!mongoUrlPromise && !remoteServer) {
    databasePromise = new MongoDatabase({ pathToApp: pathToApp });
    mongoUrlPromise = databasePromise.getMongoUrlPromise();
  }

  var helpers = options.helpers || {};

  var myPrototype = Object.create(helpers);

  // custom methods

  //myPrototype.init = function () {
  //  return this.branch().then(function () {
  //  });
  //}

  myPrototype.start = function () {
    return this.__custom__(function (operand, done) {
      done();
    });
  }

  myPrototype.stop = function () {
    return this.__custom__(function (operand, done) {

      operand.ddpClient.close();

      if (!operand.process) { // e.g. if using remote server
        return done();
      }

      operand.process.kill(function (err) {
        if (err) {
          done(err);
        } else if (databasePromise) {
          databasePromise.then(function (db) {
            db.cleanUp(done);
          }).catch(done);
        }
      });
    });
  }

  // TODO: think if this can be implemented outside the manager

  //myPrototype.restart = function (delay) {
  //  var self = this;
  //  return self.then(function () {
  //    uniqueCode = Math.random();
  //    return this.__custom__(function (operand, done) {
  //      done();
  //    });
  //  });
  //}

  var methods = [ // copy/pasted meteor process methods
    'restart'
  ];

  Object.keys(meteorMethods).forEach(function (name) {
    myPrototype[name] = meteorMethods[name];
  });

  var MeteorGeneric = generic(methods, myPrototype, function (operand, name, args, done) {
    if (!operand.process) {
      done(new Error('operand.process is undefined'));
    } else if (!operand.process[name]) {
      done(new Error('operand.process does not implement method: ' + name));
    } else {
      args.push(done);
      operand.process[name].apply(operand.process, args);
    }
  });

  // create an object inheriting from MeteorGeneric

  var meteor = Object.create(new MeteorGeneric(), {
    methods: { value: [].concat(Object.keys(myPrototype), Object.keys(helpers), MeteorGeneric.prototype.methods) }
  });

  MeteorGeneric.call(meteor, getOperand);

  meteor.getDDPSetup = getDDPSetup;

  // add closure mixins, i.e. "useClosure" and "closure" methods

  Closure.mixin(meteor);
  closure = meteor.closure.bind(meteor);

  // helper functions producing usefull promises

  function getPathToMain () {
    return BuildAsPromise({ pathToApp: pathToApp, skipBuild: skipBuild });
  }

  function getMongoUrl () {
    return databasePromise.getMongoUrlPromise();
  }

  function getMeteor () {

    if (remoteServer) {
      return Promise.resolve(null);
    }

    return Promise.all([

      getPathToMain(), getMongoUrl()

    ]).then(function (results) {

      return getMeteorProcess({
        pathToNode : tools.getNodePath(pathToApp),
        pathToMain : results[0],
        mongoUrl   : results[1],
      });

    });
  }

  function getOperand () {

    return Promise.all([

      getDDPSetup(), getMeteor()

    ]).then(function (results) {

      return getDDPClient(results[0]).then(function (ddpClient) {
        return { ddpClient: ddpClient, process: results[1], closure: closure };
      });

    });
  }

  function getDDPSetup () {

    if (remoteServer) {
      return Promise.resolve({
        host: remoteServer.hostname,
        port: remoteServer.port || 443,
      });
    }

    return getMeteor().then(function (process) {
      return {
        port: process.env.PORT,
        code: process.pid,
      };
    });

  }

  return meteor;

}
<|endoftext|>


<commit_before>define([
  'jsface', 'ko', 'text!./file-display.html', 'css!./file-display.css', 'jquery', 'sugar'
], function (Class, ko, template) {

  var ViewModel = Class({
    $static: {
      INLINE_TAGS: {
        img: { attr: 'src', affixes: ['gif', 'jpg', 'jpeg', 'png', 'tif', 'tiff'] }
      }
    },
    constructor: function (params) {
      this.content = '';
      if (ko.isObservable(params.url)) {
        params.url.subscribe(this.getContent.bind(this));
      }
      this.inlineTag = '';
      ko.observe(this);
      var url = ko.utils.unwrapObservable(params.url);
      var computed = {
        affix: function () {
          return url.from(url.lastIndexOf('.')).remove('.')
        }
      };
      Object.each(computed, function (key, value) {
        ko.defineComputedProperty(this, key, value);
      }.bind(this));
      this.getContent(url);
    },
    getContent: function (url) {
      var parts = url.toLowerCase().split('.');
      this.inlineTag = Object.find(ViewModel.INLINE_TAGS, function (key, value) {
        return value.affixes.indexOf(parts[parts.length - 1]) >= 0;
      });
      if (this.inlineTag) {
        this.content = '<{inlineTag} {attr}="{url}"></{inlineTag}>'.assign(
          {
            inlineTag: this.inlineTag,
            attr: ViewModel.INLINE_TAGS[this.inlineTag].attr,
            url: url
          }
        );
      } else {
        require(['text!' + url], this._content);
      }
    }
  });

  return {
    viewModel: ViewModel,
    template: template
  };

});
<commit_msg>Bring computed affix back.<commit_after>define([
  'jsface', 'ko', 'text!./file-display.html', 'css!./file-display.css', 'jquery', 'sugar'
], function (Class, ko, template) {

  var ViewModel = Class({
    $static: {
      INLINE_TAGS: {
        img: { attr: 'src', affixes: ['gif', 'jpg', 'jpeg', 'png', 'tif', 'tiff'] }
      }
    },
    constructor: function (params) {
      this.content = '';
      if (ko.isObservable(params.url)) {
        params.url.subscribe(this.getContent.bind(this));
      }
      this.inlineTag = '';
      ko.observe(this);
      var computed = {
        affix: function () {
          var url = ko.utils.unwrapObservable(params.url);
          return url.from(url.lastIndexOf('.')).remove('.')
        }
      };
      Object.each(computed, function (key, value) {
        ko.defineComputedProperty(this, key, value);
      }.bind(this));
      this.getContent(ko.utils.unwrapObservable(params.url));
    },
    getContent: function (url) {
      var parts = url.toLowerCase().split('.');
      this.inlineTag = Object.find(ViewModel.INLINE_TAGS, function (key, value) {
        return value.affixes.indexOf(parts[parts.length - 1]) >= 0;
      });
      if (this.inlineTag) {
        this.content = '<{inlineTag} {attr}="{url}"></{inlineTag}>'.assign(
          {
            inlineTag: this.inlineTag,
            attr: ViewModel.INLINE_TAGS[this.inlineTag].attr,
            url: url
          }
        );
      } else {
        require(['text!' + url], this._content);
      }
    }
  });

  return {
    viewModel: ViewModel,
    template: template
  };

});
<|endoftext|>


<commit_before>// --------------------
// Sequelize hierarchy
// extended model methods
// --------------------

// modules
var shimming = require('shimming');

// imports
var hooks = require('./hooks')

// exports

module.exports = function(Sequelize) {
	var Utils = Sequelize.Utils;
	var _ = Utils._;
	hooks = hooks(Sequelize);

	// return extended methods
	return {
		isHierarchy: function(options) {
			// set up options
			if (!options) options = {};

			_.defaults(options, {
				as: 'parent',
				childrenAs: 'children',
				ancestorsAs: 'ancestors',
				descendentsAs: 'descendents',
				levelFieldName: 'hierarchyLevel',
				levelFieldType: Sequelize.INTEGER.UNSIGNED,
				onDelete: (options.onDelete || 'restrict').toLowerCase()
			});

			_.defaults(options, {
				foreignKey: options.as + Utils.uppercaseFirst(this.primaryKeyAttribute),
				throughKey: this.name + Utils.uppercaseFirst(this.primaryKeyAttribute),
				throughForeignKey: Utils.singularize(options.ancestorsAs, this.options.language) + Utils.uppercaseFirst(this.primaryKeyAttribute),
				through: Utils.pluralize(this.name, this.options.language) + Utils.uppercaseFirst(options.ancestorsAs)
			});

			if (['restrict', 'cascade'].indexOf(options.onDelete) == -1) throw new Error('onDelete on hierarchies must be either \'restrict\' or \'cascade\'');

			// record hierarchy in model
			this.hierarchy = options;

			// add level field to model
			this.rawAttributes[options.levelFieldName] = {type: options.levelFieldType};
			this.init(this.daoFactoryManager);

			// create associations
			this.hasMany(this, {as: options.childrenAs, foreignKey: options.foreignKey, onDelete: options.onDelete});
			this.belongsTo(this, {as: options.as, foreignKey: options.foreignKey});

			// create through table
			// NB this follows Sequelize's convention of naming the through model in plural,
			// even though inconsistent with usual Sequelize behaviour
			var sequelize = this.sequelize;

			var throughFields = {};
			throughFields[options.throughKey] = {type: this.rawAttributes[this.primaryKeyAttribute].type, allowNull: false, primaryKey: true};
			throughFields[options.throughForeignKey] = {type: this.rawAttributes[this.primaryKeyAttribute].type, allowNull: false, primaryKey: true};
			options.through = sequelize.define(options.through, throughFields, {timestamps: false, paranoid: false, tableName: options.through});

			// create associations through join table
			this.hasMany(this, {
				as: options.descendentsAs,
				foreignKey: options.throughForeignKey,
				through: options.through
			});

			this.hasMany(this, {
				as: options.ancestorsAs,
				foreignKey: options.throughKey,
				through: options.through
			});

			// apply hooks
			_.forIn(hooks, function(hookFn, hookName) {
				this.addHook(hookName, hookFn);
			}.bind(this));

			// apply shim for bulkCreate
			shimming.shim(this, {
				bulkCreate: bulkCreateShim,
				update: bulkUpdateShim
			});

			// return this for chaining
			return this;
		},

		rebuildHierarchy: function() {
			var model = this,
				hierarchy = this.hierarchy,
				primaryKey = this.primaryKeyAttribute,
				foreignKey = hierarchy.foreignKey,
				throughKey = hierarchy.throughKey,
				throughForeignKey = hierarchy.throughForeignKey,
				levelFieldName = hierarchy.levelFieldName,
				through = hierarchy.through;

			// truncate hierarchy through table
			return through.destroy({}, {truncate: true})
			.then(function() {
				// go up tree level by level and set hierarchy level field + create hierarchy through table records
				var updateAttr = {};
				updateAttr[levelFieldName] = 0;

				return (function processLevel(parents) {
					// find next level (i.e. children of last batch)
					var where = {};
					where[foreignKey] = parents ? parents.map(function(item) {return item.id;}) : null;

					return model.findAll({where: where, attributes: [primaryKey, foreignKey]}, {raw: true}).then(function(items) {
						if (!items.length) return;

						// update hierarchy level
						updateAttr[levelFieldName]++;
						return model.update(updateAttr, where).then(function() {
							// add hierarchy path to newItems from items + create array for inserting into through table
							var ancestors = [];

							items = items.map(function(item) {
								var itemId = item[primaryKey];
								var parentId = item[foreignKey];
								var parent = parentId !== null ? _.find(parents, {id: parentId}) : {path: []};

								item = {id: itemId, path: _.clone(parent.path)};

								item.path.forEach(function(ancestorId) {
									var ancestor = {};
									ancestor[throughKey] = itemId;
									ancestor[throughForeignKey] = ancestorId;

									ancestors.push(ancestor);
								});

								item.path.push(itemId);

								return item;
							});

							// insert rows into hierarchy through table
							return through.bulkCreate(ancestors).then(function() {
								return processLevel(items);
							});
						});
					});
				})();
			})
			// return this for chaining
			.return(this);
		}
	};

	function bulkCreateShim(originalFn, records, fieldsOrOptions, options)
	{
		// combine fieldsOrOptions and options
		if (!options) options = {};
		if (fieldsOrOptions instanceof Array) {
			options.fields = fieldsOrOptions;
		} else {
			options.fields = options.fields || Object.keys(this.attributes);
			options = _.extend(options, fieldsOrOptions);
	    }

		// set hooks = true so that beforeCreate and afterCreate hooks fire
		options.hooks = true;

		// run original function
		return originalFn(records, options);
	}

	function bulkUpdateShim(originalFn, attrValueHash, where, options)
	{
		// set hooks = true so that beforeUpdate and afterUpdate hooks fire
		if (!options) options = {};
		options.hooks = true;

		// run original function
		return originalFn(attrValueHash, where, options);
	}
};
<commit_msg>Code tidy<commit_after>// --------------------
// Sequelize hierarchy
// extended model methods
// --------------------

// modules
var shimming = require('shimming');

// imports
var hooks = require('./hooks')

// exports

module.exports = function(Sequelize) {
	var Utils = Sequelize.Utils;
	var _ = Utils._;
	hooks = hooks(Sequelize);

	// return extended methods
	return {
		isHierarchy: function(options) {
			// set up options
			if (!options) options = {};

			_.defaults(options, {
				as: 'parent',
				childrenAs: 'children',
				ancestorsAs: 'ancestors',
				descendentsAs: 'descendents',
				levelFieldName: 'hierarchyLevel',
				levelFieldType: Sequelize.INTEGER.UNSIGNED,
				onDelete: (options.onDelete || 'restrict').toLowerCase()
			});

			_.defaults(options, {
				foreignKey: options.as + Utils.uppercaseFirst(this.primaryKeyAttribute),
				throughKey: this.name + Utils.uppercaseFirst(this.primaryKeyAttribute),
				throughForeignKey: Utils.singularize(options.ancestorsAs, this.options.language) + Utils.uppercaseFirst(this.primaryKeyAttribute),
				through: Utils.pluralize(this.name, this.options.language) + Utils.uppercaseFirst(options.ancestorsAs)
			});

			if (['restrict', 'cascade'].indexOf(options.onDelete) == -1) throw new Error('onDelete on hierarchies must be either \'restrict\' or \'cascade\'');

			// record hierarchy in model
			this.hierarchy = options;

			// add level field to model
			this.rawAttributes[options.levelFieldName] = {type: options.levelFieldType};
			this.init(this.daoFactoryManager);

			// create associations
			this.hasMany(this, {as: options.childrenAs, foreignKey: options.foreignKey, onDelete: options.onDelete});
			this.belongsTo(this, {as: options.as, foreignKey: options.foreignKey});

			// create through table
			// NB this follows Sequelize's convention of naming the through model in plural,
			// even though inconsistent with usual Sequelize behaviour
			var sequelize = this.sequelize;

			var throughFields = {};
			throughFields[options.throughKey] = {type: this.rawAttributes[this.primaryKeyAttribute].type, allowNull: false, primaryKey: true};
			throughFields[options.throughForeignKey] = {type: this.rawAttributes[this.primaryKeyAttribute].type, allowNull: false, primaryKey: true};
			options.through = sequelize.define(options.through, throughFields, {timestamps: false, paranoid: false, tableName: options.through});

			// create associations through join table
			this.hasMany(this, {
				as: options.descendentsAs,
				foreignKey: options.throughForeignKey,
				through: options.through
			});

			this.hasMany(this, {
				as: options.ancestorsAs,
				foreignKey: options.throughKey,
				through: options.through
			});

			// apply hooks
			_.forIn(hooks, function(hookFn, hookName) {
				this.addHook(hookName, hookFn);
			}.bind(this));

			// apply shim for bulkCreate
			shimming.shim(this, {
				bulkCreate: bulkCreateShim,
				update: bulkUpdateShim
			});

			// return this for chaining
			return this;
		},

		rebuildHierarchy: function() {
			var model = this,
				hierarchy = this.hierarchy,
				primaryKey = this.primaryKeyAttribute,
				foreignKey = hierarchy.foreignKey,
				throughKey = hierarchy.throughKey,
				throughForeignKey = hierarchy.throughForeignKey,
				levelFieldName = hierarchy.levelFieldName,
				through = hierarchy.through;

			// truncate hierarchy through table
			return through.destroy({}, {truncate: true})
			.then(function() {
				// go up tree level by level and set hierarchy level field + create hierarchy through table records
				var updateAttr = {};
				updateAttr[levelFieldName] = 0;

				return (function processLevel(parents) {
					// find next level (i.e. children of last batch)
					var where = {};
					where[foreignKey] = parents ? parents.map(function(item) {return item.id;}) : null;

					return model.findAll({where: where, attributes: [primaryKey, foreignKey]}, {raw: true})
					.then(function(items) {
						if (!items.length) return;

						// update hierarchy level
						updateAttr[levelFieldName]++;

						return model.update(updateAttr, where)
						.then(function() {
							// add hierarchy path to newItems from items + create array for inserting into through table
							var ancestors = [];

							items = items.map(function(item) {
								var itemId = item[primaryKey];
								var parentId = item[foreignKey];
								var parent = parentId !== null ? _.find(parents, {id: parentId}) : {path: []};

								item = {id: itemId, path: _.clone(parent.path)};

								item.path.forEach(function(ancestorId) {
									var ancestor = {};
									ancestor[throughKey] = itemId;
									ancestor[throughForeignKey] = ancestorId;

									ancestors.push(ancestor);
								});

								item.path.push(itemId);

								return item;
							});

							// insert rows into hierarchy through table
							return through.bulkCreate(ancestors)
							.then(function() {
								return processLevel(items);
							});
						});
					});
				})();
			})
			// return this for chaining
			.return(this);
		}
	};

	function bulkCreateShim(originalFn, records, fieldsOrOptions, options)
	{
		// combine fieldsOrOptions and options
		if (!options) options = {};
		if (fieldsOrOptions instanceof Array) {
			options.fields = fieldsOrOptions;
		} else {
			options.fields = options.fields || Object.keys(this.attributes);
			options = _.extend(options, fieldsOrOptions);
	    }

		// set hooks = true so that beforeCreate and afterCreate hooks fire
		options.hooks = true;

		// run original function
		return originalFn(records, options);
	}

	function bulkUpdateShim(originalFn, attrValueHash, where, options)
	{
		// set hooks = true so that beforeUpdate and afterUpdate hooks fire
		if (!options) options = {};
		options.hooks = true;

		// run original function
		return originalFn(attrValueHash, where, options);
	}
};
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import stylesProjectLink from './project-link.module.scss';
import {Link} from 'react-router';
import { prefixLink } from 'gatsby-helpers';

export default class ProjectLink extends Component {

  static propTypes() {

    return {
      name: PropTypes.string.isRequired,
      path: PropTypes.string.isRequired
    }
  }

  render() {

    //collect data
    const {name, path} = this.props;
    //render markup
    return (

          <Link to={prefixLink(path)}>{name}</Link>

    )
  }
}
<commit_msg>anchor element without paragraph wrapper<commit_after>import React, {Component, PropTypes} from 'react';
import stylesProjectLink from './project-link.module.scss';
import {Link} from 'react-router';
import { prefixLink } from 'gatsby-helpers';

export default class ProjectLink extends Component {

  static propTypes() {

    return {
      name: PropTypes.string.isRequired,
      path: PropTypes.string.isRequired
    }
  }

  render() {

    //collect data
    const {name, path} = this.props;
    //render markup
    return (

          <Link to={prefixLink(path)} title={name}  className={stylesProjectLink['title']}>{name}</Link>

    )
  }
}
<|endoftext|>


<commit_before>import http from "http"

import Koa from "koa"
import isInteger from "lodash/isInteger"
import isFunction from "lodash/isFunction"
import isPlainObject from "lodash/isPlainObject"
import deepFreeze from "deep-freeze"
import invariant from "@octetstream/invariant"

import objectIterator from "core/helper/iterator/sync/objectIterator"
import isListOf from "core/helper/typechecker/isListOf"
import getHostname from "core/helper/util/getHostname"

const isArray = Array.isArray
const defineProperty = Object.defineProperty

class Server extends Koa {
  constructor(config = {}) {
    invariant(!config.port, TypeError, "Port is required.")

    invariant(!isInteger(config.port), TypeError, "Port should be an integer.")

    super()

    // Private member
    this.__config = deepFreeze({
      ...config
    })

    // Binds
    this.use = this.use.bind(this)
  }

  // Get server name
  get name() {
    return this.config.name
  }

  // Get a port that will be listening by the server
  get port() {
    return this.config.port
  }

  // Get configured server address
  // Note: This is NOT an actual address that will be used by Node.js server
  get addr() {
    const {env, host, port, secure} = this.config

    return getHostname(host, port, secure, env.dev)
  }

  get config() {
    return this.__config
  }

  /**
   * @private
   */
  __extFromConfig = config => {
    invariant(
      !isPlainObject(config),
      "Extensions should be passed as s plsin JavaScript object " +
      "or as name and a funtion. See the Server#ext docs for more info."
    )

    for (const [key, value] of objectIterator.entries(config)) {
      defineProperty(this.context, key, {value})
    }

    return this
  }

  /**
   * Add milldeware to queue
   *
   * @see Koa.js docs tp get more information about middlewares
   *
   * @param {AsyncFunction|function|array} middleware – a function or a list
   *  of functions that will be added to Koa.js middleware queue
   *
   * @return {Server}
   */
  use(middlewares) {
    if (!isArray(middlewares)) {
      middlewares = [middlewares]
    }

    invariant(
      !isListOf(middlewares, isFunction), TypeError,
      "Middlewars should be passed as a functino or an array of functions."
    )

    // Set up middlewares to Koa instance
    middlewares.forEach(middleware => super.use(middleware))

    return this
  }

  /**
   * Extend Koa.js context with methods
   * This method allows you to extend a Koa.js context and use your function
   *   from it instance in middlewares.
   * @see src/server/api/core/base/view.js as working example.
   *
   * @param {string|object} – method name or palin object with sets of methods
   *   in format: {name: fn}
   *
   * @param {function} fn – handler that will extends Context
   *
   * @return {Server}
   *
   * Example:
   *
   * So, after you've create a Server instance, you can extend Koa.js context
   *   using this method if you want to use custiom methods from middlewares:
   *
   * ```js
   *   // Note: "this" keyword in your extension will be point to Koa.js context
   *   const greeter = (name = "Anon Pony") => this.body = `Hello, ${name}!`
   *
   *   // I've recomended passing extensions as a plain object
   *   //   of "name" => "fn" pair,
   *   //   cuz this is more shorter way than passing "name" and "function"
   *   //   as two different params.
   *   server.ext({greeter})
   * ```
   *
   * ...and after that, you can use your extension from middlewares, like so:
   *
   * ```js
   *  async function greeterMiddleware(ctx, next) {
   *    ctx.greeter(ctx.query.name)
   *    await next()
   *  }
   * ```
   */
  ext = (name, fn) => (
    this.__extFromConfig(isPlainObject(name) ? name : {[name]: fn})
  )

  /**
   * Start server that will be listening on port from config.
   */
  listen = () => new Promise((resolve, reject) => {
    const server = http.createServer(this.callback())

    const onFulfilled = () => resolve(server)

    server
      .on("error", reject)
      .listen(this.port, onFulfilled)
  })
}

export default Server
<commit_msg>More JSDoc.<commit_after>import http from "http"

import Koa from "koa"
import isInteger from "lodash/isInteger"
import isFunction from "lodash/isFunction"
import isPlainObject from "lodash/isPlainObject"
import deepFreeze from "deep-freeze"
import invariant from "@octetstream/invariant"

import objectIterator from "core/helper/iterator/sync/objectIterator"
import isListOf from "core/helper/typechecker/isListOf"
import getHostname from "core/helper/util/getHostname"

const isArray = Array.isArray
const defineProperty = Object.defineProperty

class Server extends Koa {
  constructor(config = {}) {
    invariant(!config.port, TypeError, "Port is required.")

    invariant(!isInteger(config.port), TypeError, "Port should be an integer.")

    super()

    // Private member
    this.__config = deepFreeze({
      ...config
    })

    // Binds
    this.use = this.use.bind(this)
  }

  // Get server name
  get name() {
    return this.config.name
  }

  // Get a port that will be listening by the server
  get port() {
    return this.config.port
  }

  // Get configured server address
  // Note: This is NOT an actual address that will be used by Node.js server
  get addr() {
    const {env, host, port, secure} = this.config

    return getHostname(host, port, secure, env.dev)
  }

  get config() {
    return this.__config
  }

  /**
   * @private
   */
  __extFromConfig = config => {
    invariant(
      !isPlainObject(config),
      "Extensions should be passed as s plsin JavaScript object " +
      "or as name and a funtion. See the Server#ext docs for more info."
    )

    for (const [key, value] of objectIterator.entries(config)) {
      defineProperty(this.context, key, {value})
    }

    return this
  }

  /**
   * Add milldeware to queue
   *
   * @see Koa.js docs tp get more information about middlewares
   *
   * @param {AsyncFunction|function|array} middleware – a function or a list
   *  of functions that will be added to Koa.js middleware queue
   *
   * @return {Server}
   */
  use(middlewares) {
    if (!isArray(middlewares)) {
      middlewares = [middlewares]
    }

    invariant(
      !isListOf(middlewares, isFunction), TypeError,
      "Middlewars should be passed as a functino or an array of functions."
    )

    // Set up middlewares to Koa instance
    middlewares.forEach(middleware => super.use(middleware))

    return this
  }

  /**
   * Extend Koa.js context with methods
   * This method allows you to extend a Koa.js context and use your function
   *   from it instance in middlewares.
   * @see src/server/api/core/base/view.js as working example.
   *
   * @param {string|object} – method name or palin object with sets of methods
   *   in format: {name: fn}
   *
   * @param {function} fn – handler that will extends Context
   *
   * @return {Server}
   *
   * @example
   * // So, after you've create a Server instance, you can extend Koa.js context
   * //  using this method if you want to use custiom methods from middlewares:
   *
   * // Note: "this" keyword in your extension will be point to Koa.js context
   * const greeter = (name = "Anon Pony") => this.body = `Hello, ${name}!`
   *
   * // I've recomended passing extensions as a plain object
   * //   of "name" => "fn" pair,
   * //   cuz this is more shorter way than passing "name" and "function"
   * //   as two different params.
   * server.ext({greeter})
   *
   * // ...and after that, you can use your extension from middlewares, like so:
   * async function greeterMiddleware(ctx, next) {
   *   ctx.greeter(ctx.query.name)
   *   await next()
   * }
   */
  ext = (name, fn) => (
    this.__extFromConfig(isPlainObject(name) ? name : {[name]: fn})
  )

  /**
   * Start server that will be listening on port from config.
   */
  listen = () => new Promise((resolve, reject) => {
    const server = http.createServer(this.callback())

    const onFulfilled = () => resolve(server)

    server
      .on("error", reject)
      .listen(this.port, onFulfilled)
  })
}

export default Server
<|endoftext|>


<commit_before>
//to clear db
// var mongoose = require('mongoose');
// /* Connect to the DB */
// mongoose.connect('mongodb://localhost/quickQuoteNodedb',function(){
//     /* Drop the DB */
//     mongoose.connection.db.dropDatabase();
// });

/**
 * Module dependencies
 */

var mongoose = require('mongoose');

// Connect to db
mongoose.connect('mongodb://localhost/quickQuoteNodedb');

var Schema = mongoose.Schema;

var ObjectId = Schema.ObjectId;

var UserSchema = new Schema({
  twitter_id: Number,
  name: String,
  screen_name: String,
  description: String,
  url: String,
  token: String,
  tokenSecret: String,
  hypertranscripts:[{ type: Schema.Types.ObjectId, ref: 'Hypertranscript' }]
});

var HypertranscriptSchema = new Schema({
	_creator: [{ type: Schema.Types.ObjectId, ref: 'User' }],
  	id : Number,
  	title: String,
  	description: String,
  	video : {
  		id : Number,
  		src: String,
  		srcHTML5 : String,
  		videoFileName : String,
		timecodeStart : Number,//seconds
		date : Date
  	},
  	words :[
  		{
	        startTime : Number,//seconds
	        endTime:  Number,//seconds
	        text : String,
	        id : Number
  		}
  	]
});

var User = exports.User = mongoose.model('User', UserSchema);

var Hypertranscript = exports.Hypertranscript = mongoose.model('Hypertranscript', HypertranscriptSchema);

<commit_msg>model db update<commit_after>
//to clear db
// var mongoose = require('mongoose');
// /* Connect to the DB */
// mongoose.connect('mongodb://localhost/quickQuoteNodedb',function(){
//     /* Drop the DB */
//     mongoose.connection.db.dropDatabase();
// });

/**
 * Module dependencies
 */

var mongoose = require('mongoose');
var config = require('config');
// Connect to db
console.log(config.db.path);
mongoose.connect(config.db.path);

var Schema = mongoose.Schema;

var ObjectId = Schema.ObjectId;

var UserSchema = new Schema({
  twitter_id: Number,
  name: String,
  screen_name: String,
  description: String,
  url: String,
  token: String,
  tokenSecret: String,
  hypertranscripts:[{ type: Schema.Types.ObjectId, ref: 'Hypertranscript' }]
});

var HypertranscriptSchema = new Schema({
	_creator: [{ type: Schema.Types.ObjectId, ref: 'User' }],
  	id : Number,
  	title: String,
  	description: String,
  	video : {
  		id : Number,
  		src: String,
  		srcHTML5 : String,
  		videoFileName : String,
		timecodeStart : Number,//seconds
		date : Date
  	},
  	words :[
  		{
	        startTime : Number,//seconds
	        endTime:  Number,//seconds
	        text : String,
	        id : Number
  		}
  	]
});

var User = exports.User = mongoose.model('User', UserSchema);

var Hypertranscript = exports.Hypertranscript = mongoose.model('Hypertranscript', HypertranscriptSchema);

<|endoftext|>