<commit_before>import React from 'react'
import styled from 'styled-components'
import {
  Avatar,
  BackgroundImage,
  Box,
  Container,
  Flex,
  Heading,
  LargeButton as Button,
  Link as A,
  OutlineButton,
  Text,
  theme
} from '@hackclub/design-system'
import { Link } from 'gatsby'
import Layout from 'components/Layout'
import Helmet from 'react-helmet'
import Nav from 'components/Nav'
import Footer from 'components/Footer'
import Sheet from 'components/Sheet'
import GlowingIcon from 'components/GlowingIcon'
import {
  ColoredHeadline,
  Subhline,
  Featline,
  Lead,
  AnimatedHighlight
} from 'components/Content'
import { timeTo } from 'helpers'
import { springPromo } from 'data.json'
// import Announcement from 'components/home/Announcement'

const cta = {
  chevronRight: true,
  color: 'white',
  scale: true
}
const CTA = styled(Button.withComponent(Link)).attrs(cta)`
  background-image: ${theme.gradient('pink.5', 'red.6')};
`
const StartCTA = styled(Button.withComponent(Link)).attrs({
  ...cta,
  fontSize: [4, 5],
  px: [4, 5]
})`
  background-image: ${theme.gradient('orange.5', 'red.5')};
`
OutlineButton.link = OutlineButton.withComponent(Link)

const HeadlineIcon = styled(GlowingIcon)`
  top: ${theme.space[1]}px;
  ${theme.mediaQueries.md} {
    top: ${theme.space[2]}px;
    width: 64px;
    height: 64px;
  }
`
const SubhlineIcon = styled(GlowingIcon)`
  top: ${theme.space[1]}px;
  ${theme.mediaQueries.md} {
    top: ${theme.space[2]}px;
    width: 48px;
    height: 48px;
  }
`

/*
const Megaline = styled(Heading.h1).attrs({
  fontSize: [6, 7, 8],
  mx: 'auto'
})`
  line-height: 1.125;
  color: ${theme.colors.success};
  @supports (-webkit-background-clip: text) {
    background-image: linear-gradient(
      to bottom right,
      ${theme.colors.cyan[5]} 25%,
      ${theme.colors.teal[5]} 50%,
      ${theme.colors.green[5]}
    );
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
  }
  ${theme.mediaQueries.md} {
    line-height: 1;
  }
`
*/

const Quote = styled(Sheet).attrs({ maxWidth: 48, bg: 'primary', fontSize: 3 })`
  border-radius: ${theme.radii[2]};
  position: relative;
  ${GlowingIcon} {
    opacity: 0.75;
    position: absolute;
    left: 0;
    top: 0;
    ${theme.mediaQueries.md} {
      width: 32px;
      height: 32px;
    }
  }
`
const MegaQuote = styled(Quote).attrs({
  px: [3, 4, 5],
  pt: 6,
  pb: [4, 5],
  color: 'white'
})`
  background-image: radial-gradient(
    ellipse farthest-corner at top left,
    ${theme.colors.pink[5]},
    ${theme.colors.fuschia[5]},
    ${theme.colors.indigo[5]}
  );
  &:before {
    color: ${theme.colors.pink[2]};
  }
  ${Text} {
    line-height: 1.125;
    ${theme.mediaQueries.md} {
      line-height: 1.25;
    }
  }
`

const Features = styled(Box)`
  display: grid;
  grid-gap: ${theme.space[3]}px;
  ${theme.mediaQueries.md} {
    grid-gap: ${theme.space[4]}px;
    grid-template-columns: repeat(2, 1fr);
  }
`
const FeatureLine = styled(Box).attrs({
  bg: 'primary',
  width: 1,
  mt: 2,
  mb: -2
})`
  border-radius: ${theme.radius};
  height: 4px;
`
const Photo = styled(Sheet.withComponent(BackgroundImage)).attrs({
  role: 'img',
  p: 0
})`
  min-height: 18rem;
  position: relative;
  ${theme.mediaQueries.md} {
    min-height: 25rem;
  }
  &:after {
    content: attr(aria-label);
    box-sizing: border-box;
    background-color: rgba(0, 0, 0, 0.875);
    border-radius: 0 0 ${theme.radii[2]} ${theme.radii[2]};
    bottom: 0;
    color: ${theme.colors.white};
    display: block;
    font-size: ${theme.fontSizes[2]}px;
    padding: ${theme.space[2]}px ${theme.space[3]}px;
    position: absolute;
    width: 100%;
    max-width: 100%;
    @supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) {
      background-color: rgba(0, 0, 0, 0.75);
      -webkit-backdrop-filter: saturate(180%) blur(16px);
    }
    ${theme.mediaQueries.reduceTransparency} {
      -webkit-backdrop-filter: auto !important;
    }
  }
`
const CommunityLine = styled(FeatureLine)`
  background-image: linear-gradient(
    to right,
    ${theme.colors.orange[5]},
    ${theme.colors.pink[5]},
    ${theme.colors.red[5]}
  );
`
const ResourcesLine = styled(FeatureLine)`
  background-image: linear-gradient(
    to right,
    ${theme.colors.fuschia[5]},
    ${theme.colors.violet[5]},
    ${theme.colors.blue[5]}
  );
`

const Promo = styled(Box.withComponent('section')).attrs({
  bg: 'primary',
  align: 'center',
  pt: [4, 5, 6]
})`
  background-image: radial-gradient(
    ellipse farthest-corner at top left,
    rgb(26, 211, 191),
    rgb(17, 195, 109)
  );
`
const PromoMegaline = styled(Heading.h1).attrs({
  color: 'white',
  fontSize: [7, 8, 9],
  pb: 2
})`
  letter-spacing: -0.015em;
  line-height: 1;
  + ${Lead} {
    line-height: 1.25;
    letter-spacing: -0.005em;
  }
`

export default () => (
  <Layout bg="dark">
    <Box.main color="white">
      <Helmet>
        <meta
          name="google-site-verification"
          content="f7cxVyFnrTxN9Q-HnpP-ueNWuWF5VgIEKF0C3tSnsnc"
        />
      </Helmet>

      <Promo>
        <Container maxWidth={72} px={3} py={[5, 6]}>
          <PromoMegaline mt={4} pb={1}>
            Start a coding club at your high school this spring.
          </PromoMegaline>
          <Lead
            fontSize={[3, 4, 5]}
            color="white"
            maxWidth={42}
            mt={[3, 4]}
            mb={[4, 5]}
          >
            Hack Club is a global, nonprofit network of high school coding
            clubs. Apply now for{' '}

              early admissions—open for {timeTo(springPromo.deadline)}

            .
          </Lead>
          {/* <OutlineButton.link bg="teal.1" to="/community" m={[1, 2]}>
            Join the community
          </OutlineButton.link> */}
          <StartCTA to="/start" m={[1, 2]}>
            Start your club
          </StartCTA>
        </Container>
      </Promo>
      <Box bg="white" color="black" align="center" py={[5, 6, 7]}>
        <Container px={3}>
          <ColoredHeadline
            fontSize={[6, 7, 8]}
            // colors={['green.5', 'teal.5', 'teal.7']}
            colors={['teal.6', 'cyan.6', 'blue.6']}
            mx="auto"
          />
          <Text fontSize={4} mb={3} mx="auto" style={{ maxWidth: '44rem' }}>
            We’re high schoolers running weekly afterschool coding clubs. For 2
            weeks, we’re running an exclusive campaign to help new
            <AnimatedHighlight>
              leaders start their clubs before the year ends
            </AnimatedHighlight>
            . You’ll learn a ton about leading your club, & be off to the races
            next fall.
          </Text>
          <OutlineButton.link to="/start" mt={3}>
            Start your club
          </OutlineButton.link>
          <Text
            fontSize={[1, 2]}
            color="slate"
            mt={3}
            mx="auto"
            style={{ maxWidth: '44rem' }}
          >
            Start a club, or bring yours—existing clubs are welcome too!
          </Text>
        </Container>
      </Box>
      <Box bg="snow" color="black" py={[5, 6, 7]}>
        <Container px={3}>
          <ColoredHeadline
            fontSize={[6, 7, 8]}
            colors={['orange.5', 'pink.5', 'red.5']}
          >
            Join an incredible global community of hackers.
            <HeadlineIcon
              glyph="like-fill"
              color="pink.5"
              aria-label="heart icon"
              size={36}
              ml={2}
              mt={-4}
            />
          </ColoredHeadline>
          <Text fontSize={4} mt={0} mb={3} style={{ maxWidth: '48rem' }}>
            Hack Club is an online community of thousands of other young makers.
            We’re artists, writers, tinkerers, filmmakers, volunteers.
            We make & learn together.{' '}
            You’ve found your place.
          </Text>
          <Text fontSize={4} mb={4} style={{ maxWidth: '48rem' }}>
            Have a coding question? Looking for project feedback? You’ll find
            some fabulous people to talk to in our global Slack (Discord-style
            online groupchat) with 3,000+ members, active at all hours.
          </Text>
          <CTA to="/community">Sign me up</CTA>
          <Features mt={[4, 5]}>
            <Box>
              <CommunityLine />
              <Featline mt={5}>Join forces with the best hackers.</Featline>
              <Lead color="slate">
                Making projects on your own can be isolating—we’ve been there.
                In the Slack community, you’ll find friends, supporters, and
                collaborators for your work.
              </Lead>
            </Box>
            <Box>
              <CommunityLine />
              <Featline mt={5}>Meet some truly incredible people.</Featline>
              <Lead color="slate">
                You’re going to meet super talented people, who organize
                hackathons, start coding clubs, build apps, lead camps, classes,
                and more.
              </Lead>
            </Box>
            <Photo
              src="/photos/dena_cover.jpg"
              aria-label="A Hack Club meeting near Toronto, Canada"
            />
            <Photo
              src="/photos/hackpenn_crew.jpg"
              aria-label="Organizers of PA’s largest high school hackathon met in our Slack"
            />
          </Features>
        </Container>
      </Box>
      <Box bg="white" color="black" py={[5, 6, 7]}>
        <Container px={3}>
          <ColoredHeadline
            fontSize={[6, 7, 8]}
            colors={['pink.5', 'fuschia.5', 'indigo.5']}
          >
            Grow as a programmer & human with our resources.
          </ColoredHeadline>
          <Text fontSize={4} mb={4} style={{ maxWidth: '48rem' }}>
            We offer of{' '}
            free, open-source coding tutorials. We
            write about{' '}

              running coding clubs
            {' '}
            and hackathons. We run seasonal Challenges,
            themed coding competitions with cash prizes. We’re deeply committed
            to improving the world of high school hacking.
          </Text>
          <Features mt={[4, 5, 6]}>
            <Box>
              <ResourcesLine />
              <Subhline mt={5}>
                Learn as you build at hackathons & events.
              </Subhline>
              <Text color="slate" fontSize={4}>
                We maintain an open source, up-to-date list of all the{' '}

                  high school hackathons
                {' '}
                happening soon. Check out all those events! (& totally go to
                one.)
              </Text>
            </Box>
            <Box>
              <ResourcesLine />
              <Subhline mt={5}>
                Running an event?

                We can help.
                <SubhlineIcon
                  glyph="bank-circle"
                  color="red.5"
                  aria-label="hack club bank icon"
                  size={32}
                  ml={2}
                  mt={-2}
                />
              </Subhline>
              <Text color="slate" fontSize={4}>
                Running a hackathon is tough.{' '}
                Hack Club Bank offers a straightforward
                financial platform for high school events.
              </Text>
            </Box>
          </Features>
          <MegaQuote mt={6}>
            <GlowingIcon glyph="quote" size={24} />
            <Text fontSize={[5, 6]} mt={[null, 5]} bold>
              Before I started Hack Club in sophomore year, I didn’t believe in
              myself. I didn’t think I could do big things.
            </Text>
            <Flex align="center" mt={[4, 5]}>
              <Avatar src="/hackers/megan.png" size={48} mr={3} />
              <Box align="left" fontSize={3}>
                <Text.span bold>Megan Cui</Text.span>, Cincinnati, OH

                <Text fontSize={2} color="smoke">
                  (@megan on Slack)
                </Text>
              </Box>
            </Flex>
          </MegaQuote>
        </Container>
      </Box>

    </Box.main>
  </Layout>
)
<commit_msg>Continue homepage<commit_after>import React from 'react'
import styled, { css } from 'styled-components'
import {
  Avatar,
  BackgroundImage,
  Box,
  Container,
  Flex,
  Heading,
  LargeButton as Button,
  Link as A,
  OutlineButton,
  Text,
  theme
} from '@hackclub/design-system'
import { Link } from 'gatsby'
import Layout from 'components/Layout'
import Helmet from 'react-helmet'
import Nav from 'components/Nav'
import Footer from 'components/Footer'
import Sheet from 'components/Sheet'
import GlowingIcon from 'components/GlowingIcon'
import {
  ColoredHeadline,
  Subhline,
  Featline,
  Lead,
  AnimatedHighlight
} from 'components/Content'
import { timeTo } from 'helpers'
import { springPromo } from 'data.json'
// import Announcement from 'components/home/Announcement'

const cta = {
  chevronRight: true,
  color: 'white',
  scale: true
}
const CTA = styled(Button.withComponent(Link)).attrs(cta)`
  background-image: ${theme.gradient('pink.5', 'red.6')};
`
const StartCTA = styled(Button.withComponent(Link)).attrs({
  ...cta,
  fontSize: [4, 5],
  px: [4, 5]
})`
  background-image: ${theme.gradient('orange.5', 'red.5')};
`
OutlineButton.link = OutlineButton.withComponent(Link)

const HeadlineIcon = styled(GlowingIcon)`
  top: ${theme.space[1]}px;
  ${theme.mediaQueries.md} {
    top: ${theme.space[2]}px;
    width: 64px;
    height: 64px;
  }
`
const SubhlineIcon = styled(GlowingIcon)`
  top: ${theme.space[1]}px;
  ${theme.mediaQueries.md} {
    top: ${theme.space[2]}px;
    width: 48px;
    height: 48px;
  }
`

/*
const Megaline = styled(Heading.h1).attrs({
  fontSize: [6, 7, 8],
  mx: 'auto'
})`
  line-height: 1.125;
  color: ${theme.colors.success};
  @supports (-webkit-background-clip: text) {
    background-image: linear-gradient(
      to bottom right,
      ${theme.colors.cyan[5]} 25%,
      ${theme.colors.teal[5]} 50%,
      ${theme.colors.green[5]}
    );
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
  }
  ${theme.mediaQueries.md} {
    line-height: 1;
  }
`
*/

const Quote = styled(Sheet).attrs({ maxWidth: 48, bg: 'primary', fontSize: 3 })`
  border-radius: ${theme.radii[2]};
  position: relative;
  ${GlowingIcon} {
    opacity: 0.75;
    position: absolute;
    left: 0;
    top: 0;
    ${theme.mediaQueries.md} {
      width: 32px;
      height: 32px;
    }
  }
`
const MegaQuote = styled(Quote).attrs({
  px: [3, 4, 5],
  pt: 6,
  pb: [4, 5],
  color: 'white'
})`
  background-image: radial-gradient(
    ellipse farthest-corner at top left,
    ${theme.colors.pink[5]},
    ${theme.colors.fuschia[5]},
    ${theme.colors.indigo[5]}
  );
  &:before {
    color: ${theme.colors.pink[2]};
  }
  ${Text} {
    line-height: 1.125;
    ${theme.mediaQueries.md} {
      line-height: 1.25;
    }
  }
`

const Features = styled(Box)`
  display: grid;
  grid-gap: ${theme.space[3]}px;
  ${theme.mediaQueries.md} {
    grid-gap: ${theme.space[4]}px;
    grid-template-columns: repeat(2, 1fr);
  }
`
const FeatureLine = styled(Box).attrs({
  bg: 'primary',
  width: 1,
  mt: 2,
  mb: -2
})`
  border-radius: ${theme.radius};
  height: 4px;
`
const Photo = styled(Sheet.withComponent(BackgroundImage)).attrs({
  role: 'img',
  p: 0
})`
  min-height: 18rem;
  position: relative;
  ${theme.mediaQueries.md} {
    min-height: 25rem;
  }
  &:after {
    content: attr(aria-label);
    box-sizing: border-box;
    background-color: rgba(0, 0, 0, 0.875);
    border-radius: 0 0 ${theme.radii[2]} ${theme.radii[2]};
    bottom: 0;
    color: ${theme.colors.white};
    display: block;
    font-size: ${theme.fontSizes[2]}px;
    padding: ${theme.space[2]}px ${theme.space[3]}px;
    position: absolute;
    width: 100%;
    max-width: 100%;
    @supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) {
      background-color: rgba(0, 0, 0, 0.75);
      -webkit-backdrop-filter: saturate(180%) blur(16px);
    }
    ${theme.mediaQueries.reduceTransparency} {
      -webkit-backdrop-filter: auto !important;
    }
  }
`
const CommunityLine = styled(FeatureLine)`
  background-image: linear-gradient(
    to right,
    ${theme.colors.orange[5]},
    ${theme.colors.pink[5]},
    ${theme.colors.red[5]}
  );
`
const ResourcesLine = styled(FeatureLine)`
  background-image: linear-gradient(
    to right,
    ${theme.colors.fuschia[5]},
    ${theme.colors.violet[5]},
    ${theme.colors.blue[5]}
  );
`

const promoBG = css`
  background-image: radial-gradient(
    ellipse farthest-corner at top left,
    rgb(26, 211, 191),
    rgb(17, 195, 109)
  );
`
const Promo = styled(Box.withComponent('section')).attrs({
  bg: 'teal.6',
  align: 'center',
  pt: [4, 5, 6]
})`
  ${promoBG};
`
const PromoMegaline = styled(Heading.h1).attrs({
  color: 'white',
  fontSize: [7, 8, 9],
  pb: 2
})`
  letter-spacing: -0.015em;
  line-height: 1;
  + ${Lead} {
    line-height: 1.25;
    letter-spacing: -0.005em;
  }
`
const PromoSmallCTA = styled(Button.withComponent(Link)).attrs({
  ...cta,
  bg: 'teal.6'
})`
  ${promoBG};
`

export default () => (
  <Layout>
    <Helmet>
      <meta
        name="google-site-verification"
        content="f7cxVyFnrTxN9Q-HnpP-ueNWuWF5VgIEKF0C3tSnsnc"
      />
    </Helmet>

    <Promo>
      <Container maxWidth={72} px={3} py={[5, 6]}>
        <PromoMegaline mt={4} pb={1}>
          Start a coding club at your high school this spring.
        </PromoMegaline>
        <Lead
          fontSize={[3, 4, 5]}
          color="white"
          maxWidth={42}
          mt={[3, 4]}
          mb={[4, 5]}
        >
          Hack Club is a global, nonprofit network of high school coding clubs.
          Apply now for{' '}

            early admissions—open for {timeTo(springPromo.deadline)}

          .
        </Lead>
        {/* <OutlineButton.link bg="teal.1" to="/community" m={[1, 2]}>
            Join the community
          </OutlineButton.link> */}
        <StartCTA to="/start" m={[1, 2]}>
          Start your club
        </StartCTA>
      </Container>
    </Promo>
    <Box bg="white" color="black" align="center" py={[5, 6, 7]}>
      <Container px={3}>
        <Text fontSize={4} mb={4} mx="auto" maxWidth={48}>

            We’re high schoolers running weekly afterschool coding clubs.
          {' '}
          For 2 weeks, we’re running an exclusive campaign to help next-gen{' '}
          <AnimatedHighlight>
            leaders start their clubs before the year ends
          </AnimatedHighlight>
          . With a spring pilot, you’ll start off great next fall with runway
          experience & members.
        </Text>
        <PromoSmallCTA bg="teal.7" to="/start" chevronRight>
          Start your club
        </PromoSmallCTA>
        <Text fontSize={[1, 2]} color="slate" mt={2}>
          Start a club, or bring yours—existing clubs are welcome too!
        </Text>
      </Container>
    </Box>
    <Box bg="snow" color="black" py={[5, 6, 7]}>
      <Container px={3}>
        <ColoredHeadline
          fontSize={[6, 7, 8]}
          colors={['orange.5', 'pink.5', 'red.5']}
        >
          Join an incredible global community of hackers.
          <HeadlineIcon
            glyph="like-fill"
            color="pink.5"
            aria-label="heart icon"
            size={36}
            ml={2}
            mt={-4}
          />
        </ColoredHeadline>
        <Text fontSize={4} mt={0} mb={3} style={{ maxWidth: '48rem' }}>
          Hack Club is an online community of thousands of other young makers.
          We’re artists, writers, tinkerers, filmmakers, volunteers.
          We make & learn together.{' '}
          You’ve found your place.
        </Text>
        <Text fontSize={4} mb={4} style={{ maxWidth: '48rem' }}>
          Have a coding question? Looking for project feedback? You’ll find some
          fabulous people to talk to in our global Slack (Discord-style online
          groupchat) with 3,000+ members, active at all hours.
        </Text>
        <CTA to="/community">Sign me up</CTA>
        <Features mt={[4, 5]}>
          <Box>
            <CommunityLine />
            <Featline mt={5}>Join forces with the best hackers.</Featline>
            <Lead color="slate">
              Making projects on your own can be isolating—we’ve been there. In
              the Slack community, you’ll find friends, supporters, and
              collaborators for your work.
            </Lead>
          </Box>
          <Box>
            <CommunityLine />
            <Featline mt={5}>Meet some truly incredible people.</Featline>
            <Lead color="slate">
              You’re going to meet super talented people, who organize
              hackathons, start coding clubs, build apps, lead camps, classes,
              and more.
            </Lead>
          </Box>
          <Photo
            src="/photos/dena_cover.jpg"
            aria-label="A Hack Club meeting near Toronto, Canada"
          />
          <Photo
            src="/photos/hackpenn_crew.jpg"
            aria-label="Organizers of PA’s largest high school hackathon met in our Slack"
          />
        </Features>
      </Container>
    </Box>
    <Box bg="white" color="black" py={[5, 6, 7]}>
      <Container px={3}>
        <ColoredHeadline
          fontSize={[6, 7, 8]}
          colors={['pink.5', 'fuschia.5', 'indigo.5']}
        >
          Grow as a programmer & human with our resources.
        </ColoredHeadline>
        <Text fontSize={4} mb={4} style={{ maxWidth: '48rem' }}>
          We offer of{' '}
          free, open-source coding tutorials. We write
          about{' '}

            running coding clubs
          {' '}
          and hackathons. We run seasonal Challenges,
          themed coding competitions with cash prizes. We’re deeply committed to
          improving the world of high school hacking.
        </Text>
        <Features mt={[4, 5, 6]}>
          <Box>
            <ResourcesLine />
            <Subhline mt={5}>
              Learn as you build at hackathons & events.
            </Subhline>
            <Text color="slate" fontSize={4}>
              We maintain an open source, up-to-date list of all the{' '}

                high school hackathons
              {' '}
              happening soon. Check out all those events! (& totally go to one.)
            </Text>
          </Box>
          <Box>
            <ResourcesLine />
            <Subhline mt={5}>
              Running an event?

              We can help.
              <SubhlineIcon
                glyph="bank-circle"
                color="red.5"
                aria-label="hack club bank icon"
                size={32}
                ml={2}
                mt={-2}
              />
            </Subhline>
            <Text color="slate" fontSize={4}>
              Running a hackathon is tough.{' '}
              Hack Club Bank offers a straightforward
              financial platform for high school events.
            </Text>
          </Box>
        </Features>
        <MegaQuote mt={6}>
          <GlowingIcon glyph="quote" size={24} />
          <Text fontSize={[5, 6]} mt={[null, 5]} bold>
            Before I started Hack Club in sophomore year, I didn’t believe in
            myself. I didn’t think I could do big things.
          </Text>
          <Flex align="center" mt={[4, 5]}>
            <Avatar src="/hackers/megan.png" size={48} mr={3} />
            <Box align="left" fontSize={3}>
              <Text.span bold>Megan Cui</Text.span>, Cincinnati, OH

              <Text fontSize={2} color="smoke">
                (@megan on Slack)
              </Text>
            </Box>
          </Flex>
        </MegaQuote>
      </Container>
    </Box>

  </Layout>
)
<|endoftext|>


<commit_before>import React from 'react';
import Link from 'gatsby-link';

import RandomOwl from '../images/random-image-005.jpg';
import Swizec from '../images/swizec.jpg';
import { Iframe } from '../elements';

const MDLink = ({ node }) => (

        <Link to={node.fields.slug}>
        {node.frontmatter.title} - {node.timeToRead} min read
        </Link>

)

const ListContentPages = ({ data }) => (

Setlist

            {data.allMarkdownRemark.edges.map(MDLink)}

);

const Welcome = () => (

Hello new friend 👋

Welcome to Swizec's Intro to React Workshop. Today you will build your first webapp React and Friends.

Your day starts at the very beginning: Why React? What problem does it solve? What makes it tick? What's the ecosystem like? Why are components the future?

By the end of the day you'll have built your first React app.

Something like this 👇

Morty's Mindblowers — it shows gifs from Imgur's frontpage stitched together with cutscenes from a Rick & Morty episode where Morty discovers deleted memories.

);

const WhoSwiz = () => (

Swizec Teller

I'm Swizec, I'll be helping you out today

You can find out stuff about me if you ask Google. But generally speaking I've:

been coding for over 20 years

published Why Programmers Work at Night, that was fun

published Data Visualization with D3.js, dare ask me about publishers

published 3 editions of React + D3, that's been great

helped over 10,000 people become better engineers

made this interactive ES6 cheatsheet

);

const Start = () => (

Let's get down to business

This is an interactive workshop. If you have a question, ask. If something doesn't make sense, ask. If something is confusing, ask. If I'm not making sense, ask. If your code doesn't work, ask.

You will write code today. The code will live on your computer.

We will take breaks.

All code works with React 16 and is written in modern ES6+. Code assumes a development environment created with create-react-app. This gives us some special powers. I will point them out.

);

const IndexPage = ({ data }) => (

        <img src={RandomOwl} title={`Literally first hit for "random image"`}/>

        <Welcome />
        <WhoSwiz />

        <Start />

Here's the setlist for today 👇

        <ListContentPages data={data} />

);

export const query = graphql`
  query IndexQuery {
    allMarkdownRemark {
      totalCount
      edges {
        node {
          id
          timeToRead
          frontmatter {
            title
          }
          fields {
            slug
          }
        }
      }
    }
  }
`;

export default IndexPage
<commit_msg>Use video for mortys mindblowers<commit_after>import React from 'react';
import Link from 'gatsby-link';

import RandomOwl from '../images/random-image-005.jpg';
import MortysMindblowers from '../images/mortysmindblowers.mp4';
import Swizec from '../images/swizec.jpg';

const MDLink = ({ node }) => (

        <Link to={node.fields.slug}>
        {node.frontmatter.title} - {node.timeToRead} min read
        </Link>

)

const ListContentPages = ({ data }) => (

Setlist

            {data.allMarkdownRemark.edges.map(MDLink)}

);

const Welcome = () => (

Hello new friend 👋

Welcome to Swizec's Intro to React Workshop. Today you will build your first webapp React and Friends.

Your day starts at the very beginning: Why React? What problem does it solve? What makes it tick? What's the ecosystem like? Why are components the future?

By the end of the day you'll have built your first React app.

Something like this 👇

        <video src={MortysMindblowers} controls autoPlay mute loop style={{width: '100%'}} />

Morty's Mindblowers shows an endless stream of gifs from Imgur's frontpage stitched together with cutscenes from a Rick & Morty episode where Morty discovers deleted memories.

);

const WhoSwiz = () => (

Swizec Teller

I'm Swizec, I'll be helping you out today

You can find out stuff about me if you ask Google. But generally speaking I've:

been coding for over 20 years

published Why Programmers Work at Night, that was fun

published Data Visualization with D3.js, dare ask me about publishers

published 3 editions of React + D3, that's been great

helped over 10,000 people become better engineers

made this interactive ES6 cheatsheet

);

const Start = () => (

Let's get down to business

This is an interactive workshop. If you have a question, ask. If something doesn't make sense, ask. If something is confusing, ask. If I'm not making sense, ask. If your code doesn't work, ask.

You will write code today. The code will live on your computer.

We will take breaks.

All code works with React 16 and is written in modern ES6+. Code assumes a development environment created with create-react-app. This gives us some special powers. I will point them out.

);

const IndexPage = ({ data }) => (

        <img src={RandomOwl} title={`Literally first hit for "random image"`}/>

        <Welcome />
        <WhoSwiz />

        <Start />

Here's the setlist for today 👇

        <ListContentPages data={data} />

);

export const query = graphql`
  query IndexQuery {
    allMarkdownRemark {
      totalCount
      edges {
        node {
          id
          timeToRead
          frontmatter {
            title
          }
          fields {
            slug
          }
        }
      }
    }
  }
`;

export default IndexPage
<|endoftext|>


<commit_before>import React from 'react';
import {
  SprkStack,
  SprkStackItem,
  SprkCard,
  SprkButton,
} from '@sparkdesignsystem/spark-react';
import Layout from '../components/layouts/Layout';
import componentsMedia from '../images/components.svg';
import developersMedia from '../images/developers.svg';
import fundamentalsMedia from '../images/fundamentals.svg';
import newsMedia from '../images/news-and-updates.png';

const teaserDesigners = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Get Started',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: '/installing-spark/developers',
  },
  media: {
    href: 'https://sparkdesignsystem.com/',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: 'https://sparkdesignsystem.com/assets/toolkit/images/desktop.jpg',
    mediaVariant: 'img',
  },
  title: 'Getting Started For Designers',
  titleFirst: false,
};

const teaserDevelopers = {
  bodyText: `
    Lorem ipsum dolor sit amet, doctus
    invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Get Started',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: 'https://sparkdesignsystem.com/',
  },
  media: {
    href: 'https://sparkdesignsystem.com/',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: developersMedia,
    mediaVariant: 'img',
  },
  title: 'Getting Started For Developers',
  titleFirst: false,
};

const teaserComponents = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te.
    Facilisi perpetua.
  `,
  cta: {
    text: 'See All Components',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: '/using-spark/components/button',
  },
  media: {
    href: '/using-spark/components/button',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: componentsMedia,
    mediaVariant: 'img',
  },
  title: 'Components',
  titleFirst: false,
};

const teaserFundamentals = {
  bodyText: `
    Lorem ipsum dolor sit amet, doctus
    invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Learn More',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: '/using-spark/foundations/sass-variables',
  },
  media: {
    href: '/using-spark/foundations/sass-variables',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: fundamentalsMedia,
    mediaVariant: 'img',
  },
  title: 'Foundations',
  titleFirst: false,
};

const teaserDocumentaion = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Learn More',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: 'https://sparkdesignsystem.com/',
  },
  media: {
    href: 'https://sparkdesignsystem.com/',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: '',
    mediaVariant: 'img',
  },
  title: 'Documentation',
  titleFirst: false,
};

const teaserNews = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te.
    Facilisi perpetua.
  `,
  cta: {
    text: 'See Latest Updates',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: 'https://sparkdesignsystem.com/',
  },
  media: {
    href: 'https://sparkdesignsystem.com/',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: newsMedia,
    mediaVariant: 'img',
  },
  title: 'News and Updates',
  titleFirst: false,
};

const spacingBtwSections = 'huge';
const spacingBtwHeadingAndContent = 'large';

const IndexPage = () => (
  <Layout hasSideBar={false}>
    <SprkStack itemSpacing={spacingBtwSections}>
      <SprkStackItem>
        <SprkStack
          itemSpacing={spacingBtwHeadingAndContent}
        >
          <SprkStackItem>

              Spark Design System

          </SprkStackItem>

          <SprkStackItem>

              Lorem ipsum dolor sit amet, consectetur
              adipiscing elit. Sed gravida urna quis nulla ultrices,
              sed efficitur risus elementum. Vivamus
              semper ex a lorem sodales, rhoncus rhoncus augue cursus.

          </SprkStackItem>
        </SprkStack>
      </SprkStackItem>

      <SprkStackItem>

          <SprkCard
            variant="teaser"
            teaserConfig={teaserDesigners}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserDevelopers}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserComponents}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserFundamentals}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserDocumentaion}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserNews}
          />

      </SprkStackItem>

      <SprkStackItem>
        <SprkStack itemSpacing={spacingBtwHeadingAndContent}>
          <SprkStackItem>

              Want To Contribute?

          </SprkStackItem>

          <SprkStackItem>
            <SprkButton variant="secondary">
              Learn More
            </SprkButton>
          </SprkStackItem>
        </SprkStack>
      </SprkStackItem>
    </SprkStack>
  </Layout>
);

export default IndexPage;
<commit_msg>change news + updates to releases<commit_after>import React from 'react';
import {
  SprkStack,
  SprkStackItem,
  SprkCard,
  SprkButton,
} from '@sparkdesignsystem/spark-react';
import Layout from '../components/layouts/Layout';
import componentsMedia from '../images/components.svg';
import developersMedia from '../images/developers.svg';
import fundamentalsMedia from '../images/fundamentals.svg';
import newsMedia from '../images/news-and-updates.png';

const teaserDesigners = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Get Started',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: '/installing-spark/developers',
  },
  media: {
    href: 'https://sparkdesignsystem.com/',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: 'https://sparkdesignsystem.com/assets/toolkit/images/desktop.jpg',
    mediaVariant: 'img',
  },
  title: 'Getting Started For Designers',
  titleFirst: false,
};

const teaserDevelopers = {
  bodyText: `
    Lorem ipsum dolor sit amet, doctus
    invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Get Started',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: 'https://sparkdesignsystem.com/',
  },
  media: {
    href: 'https://sparkdesignsystem.com/',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: developersMedia,
    mediaVariant: 'img',
  },
  title: 'Getting Started For Developers',
  titleFirst: false,
};

const teaserComponents = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te.
    Facilisi perpetua.
  `,
  cta: {
    text: 'See All Components',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: '/using-spark/components/button',
  },
  media: {
    href: '/using-spark/components/button',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: componentsMedia,
    mediaVariant: 'img',
  },
  title: 'Components',
  titleFirst: false,
};

const teaserFundamentals = {
  bodyText: `
    Lorem ipsum dolor sit amet, doctus
    invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Learn More',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: '/using-spark/foundations/sass-variables',
  },
  media: {
    href: '/using-spark/foundations/sass-variables',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: fundamentalsMedia,
    mediaVariant: 'img',
  },
  title: 'Foundations',
  titleFirst: false,
};

const teaserDocumentaion = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te. Facilisi perpetua.
  `,
  cta: {
    text: 'Learn More',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: 'https://sparkdesignsystem.com/',
  },
  media: {
    href: 'https://sparkdesignsystem.com/',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: '',
    mediaVariant: 'img',
  },
  title: 'Documentation',
  titleFirst: false,
};

const teaserNews = {
  bodyText: `
    Lorem ipsum dolor sit amet,
    doctus invenirevix te.
    Facilisi perpetua.
  `,
  cta: {
    text: 'See Latest Updates',
    ctaVariant: 'button',
    buttonVariant: 'secondary',
    href: 'https://github.com/sparkdesignsystem/spark-design-system/releases',
  },
  media: {
    href: 'https://github.com/sparkdesignsystem/spark-design-system/releases',
    mediaLinkElement: 'a',
    imgAlt: 'placeholder image',
    imgSrc: newsMedia,
    mediaVariant: 'img',
  },
  title: 'Release Notes',
  titleFirst: false,
};

const spacingBtwSections = 'huge';
const spacingBtwHeadingAndContent = 'large';

const IndexPage = () => (
  <Layout hasSideBar={false}>
    <SprkStack itemSpacing={spacingBtwSections}>
      <SprkStackItem>
        <SprkStack
          itemSpacing={spacingBtwHeadingAndContent}
        >
          <SprkStackItem>

              Spark Design System

          </SprkStackItem>

          <SprkStackItem>

              Lorem ipsum dolor sit amet, consectetur
              adipiscing elit. Sed gravida urna quis nulla ultrices,
              sed efficitur risus elementum. Vivamus
              semper ex a lorem sodales, rhoncus rhoncus augue cursus.

          </SprkStackItem>
        </SprkStack>
      </SprkStackItem>

      <SprkStackItem>

          <SprkCard
            variant="teaser"
            teaserConfig={teaserDesigners}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserDevelopers}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserComponents}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserFundamentals}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserDocumentaion}
          />

          <SprkCard
            variant="teaser"
            teaserConfig={teaserNews}
          />

      </SprkStackItem>

      <SprkStackItem>
        <SprkStack itemSpacing={spacingBtwHeadingAndContent}>
          <SprkStackItem>

              Want To Contribute?

          </SprkStackItem>

          <SprkStackItem>
            <SprkButton variant="secondary">
              Learn More
            </SprkButton>
          </SprkStackItem>
        </SprkStack>
      </SprkStackItem>
    </SprkStack>
  </Layout>
);

export default IndexPage;
<|endoftext|>


<commit_before>import * as utils from '../utils';
import * as parseUtils from './utils';

function parsePages (options) {
  const pageData = {};

  return utils.readFiles(options.src.pages, options).then(fileData => {
    const relativeRoot = utils.commonRoot(fileData);
    fileData.forEach(pageFile => {
      const entryKey   = utils.keyname(pageFile.path, { stripNumbers: false });
      const keys       = utils.relativePathArray(
        pageFile.path, relativeRoot);
      utils.deepObj(keys, pageData)[entryKey] = parseUtils
        .parseLocalData(pageFile, options);
    });
    return pageData;
  });
}

export default parsePages;
<commit_msg>Tweak parse/pages for new utils.resourceKey<commit_after>import * as utils from '../utils';
import * as parseUtils from './utils';

function parsePages (options) {
  const pageData = {};

  return utils.readFiles(options.src.pages, options).then(fileData => {
    const relativeRoot = utils.commonRoot(fileData);
    fileData.forEach(pageFile => {
      const keys       = utils.relativePathArray(
        pageFile.path, relativeRoot);
      utils.deepObj(keys, pageData)[utils.resourceKey(pageFile)] = parseUtils
        .parseLocalData(pageFile, options);
    });
    return pageData;
  });
}

export default parsePages;
<|endoftext|>


<commit_before>import { assert } from 'chai';
import parserFactory from './parser';

describe('Parser', () => {
    const config = {};
    const logger = console;
    logger.debug = console.log;

    let request;

    beforeEach(() => {
        request = {
            headers: { 'X-GitHub-Event': 'pull_request_review_comment' },
            body: {
                action: 'created',
                comment: {
                    id: 'comment id',
                    body: 'comment body',
                    path: 'comment path',
                    created_at: 'comment date',
                    html_url: 'comment url',
                },
                sender: { login: 'Someone' },
                repository: { name: 'Sedy', owner: { login: 'Marmelab'} },
                pull_request: { number: 42, head: { ref: 'master' } },
                diff_hunk: 'diff hunk', // @TODO Use fixture
                position: 'diff position',
            },
        };
    });

    it('should throw exception if no argument', () => {
        assert.throws(parserFactory(config, logger).parse, TypeError);
    });

    describe('headers', () => {
        it('should return null for bad headers or `ping` event', () => {
            const shouldReturnNull = value => {
                assert.deepEqual(parserFactory(config, logger).parse(value), null);
            };

            shouldReturnNull({ headers: null });
            shouldReturnNull({ headers: [] });
            shouldReturnNull({ headers: 'bad header' });
            shouldReturnNull({ headers: { 'bad': 'header' } });
            shouldReturnNull({ headers: { 'X-GitHub-Event': 'bad event' } });
            shouldReturnNull({ headers: { 'X-GitHub-Event': 'ping' } });
        });
    });

    describe('pull request', () => {
        it('should find correct comment', () => {
            const parser = parserFactory(config, logger);

            assert.deepEqual(parser.parsePullRequestReviewComment(request).comment, {
                action: 'created',
                id: 'comment id',
                body: 'comment body',
                sender: 'Someone',
                path: 'comment path',
                diffHunk: 'diff hunk',
                position: 'diff position',
                createdDate: 'comment date',
                url: 'comment url',
            });
        });
    });

    describe('sed parsing', () => {
        it('should not match if not pattern in comment', () => {
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, []);
        });

        it('should match if one pattern in comment', () => {
            request.body.comment.body = 's/That/This/';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, [
                { from: 'That', to: 'This' },
            ]);
        });

        it('should match the deletion pattern', () => {
            request.body.comment.body = 's/To Remove//';
            assert.deepEqual(parser(config).parse(request).matches, [
                { from: 'To Remove', to: '' },
            ]);
        });

        it('should match if more than one patterns in comment', () => {
            request.body.comment.body = 's/That/This/ \ns/To Remove//';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, [
                { from: 'That', to: 'This' },
                { from: 'To Remove', to: '' },
            ]);
        });

        it('should match if sed `from` value is not ascii', () => {
            request.body.comment.body = 's/Thαt/This/';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, []);
        });

        it('should match if sed `to` value is not ascii', () => {
            request.body.comment.body = 's/That/Thιs/';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, []);
        });

        it("should not match if it isn't a created comment", () => {
            request.body.action = 'deleted';
            assert.deepEqual(parserFactory(config, logger).parse(request), null);

            request.body.action = 'edited';
            assert.deepEqual(parserFactory(config, logger).parse(request), null);
        });

        it('should not match if the pattern is an image url', () => {
            request.body.comment.body = 'https://perdu.com/os/images/lost/image.jpg';
            assert.deepEqual(parser(config).parse(request).matches, []);
        });

        it('should match sed together with image url', () => {
            request.body.comment.body = ' s/remove// https://perdu.com/os/images/lost/image.jpg s/replace/me/';
            assert.deepEqual(parser(config).parse(request).matches, [
                { from: 'remove', to: '' },
                { from: 'replace', to: 'me' },
            ]);
        });
    });
});
<commit_msg>fix test<commit_after>import { assert } from 'chai';
import parserFactory from './parser';

describe('Parser', () => {
    const config = {};
    const logger = console;
    logger.debug = console.log;

    let request;

    beforeEach(() => {
        request = {
            headers: { 'X-GitHub-Event': 'pull_request_review_comment' },
            body: {
                action: 'created',
                comment: {
                    id: 'comment id',
                    body: 'comment body',
                    path: 'comment path',
                    created_at: 'comment date',
                    html_url: 'comment url',
                },
                sender: { login: 'Someone' },
                repository: { name: 'Sedy', owner: { login: 'Marmelab'} },
                pull_request: { number: 42, head: { ref: 'master' } },
                diff_hunk: 'diff hunk', // @TODO Use fixture
                position: 'diff position',
            },
        };
    });

    it('should throw exception if no argument', () => {
        assert.throws(parserFactory(config, logger).parse, TypeError);
    });

    describe('headers', () => {
        it('should return null for bad headers or `ping` event', () => {
            const shouldReturnNull = value => {
                assert.deepEqual(parserFactory(config, logger).parse(value), null);
            };

            shouldReturnNull({ headers: null });
            shouldReturnNull({ headers: [] });
            shouldReturnNull({ headers: 'bad header' });
            shouldReturnNull({ headers: { 'bad': 'header' } });
            shouldReturnNull({ headers: { 'X-GitHub-Event': 'bad event' } });
            shouldReturnNull({ headers: { 'X-GitHub-Event': 'ping' } });
        });
    });

    describe('pull request', () => {
        it('should find correct comment', () => {
            const parser = parserFactory(config, logger);

            assert.deepEqual(parser.parsePullRequestReviewComment(request).comment, {
                action: 'created',
                id: 'comment id',
                body: 'comment body',
                sender: 'Someone',
                path: 'comment path',
                diffHunk: 'diff hunk',
                position: 'diff position',
                createdDate: 'comment date',
                url: 'comment url',
            });
        });
    });

    describe('sed parsing', () => {
        it('should not match if not pattern in comment', () => {
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, []);
        });

        it('should match if one pattern in comment', () => {
            request.body.comment.body = 's/That/This/';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, [
                { from: 'That', to: 'This' },
            ]);
        });

        it('should match the deletion pattern', () => {
            request.body.comment.body = 's/To Remove//';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, [
                { from: 'To Remove', to: '' },
            ]);
        });

        it('should match if more than one patterns in comment', () => {
            request.body.comment.body = 's/That/This/ \ns/To Remove//';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, [
                { from: 'That', to: 'This' },
                { from: 'To Remove', to: '' },
            ]);
        });

        it('should match if sed `from` value is not ascii', () => {
            request.body.comment.body = 's/Thαt/This/';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, []);
        });

        it('should match if sed `to` value is not ascii', () => {
            request.body.comment.body = 's/That/Thιs/';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, []);
        });

        it("should not match if it isn't a created comment", () => {
            request.body.action = 'deleted';
            assert.deepEqual(parserFactory(config, logger).parse(request), null);

            request.body.action = 'edited';
            assert.deepEqual(parserFactory(config, logger).parse(request), null);
        });

        it('should not match if the pattern is an image url', () => {
            request.body.comment.body = 'https://perdu.com/os/images/lost/image.jpg';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, []);
        });

        it('should match sed together with image url', () => {
            request.body.comment.body = ' s/remove// https://perdu.com/os/images/lost/image.jpg s/replace/me/';
            assert.deepEqual(parserFactory(config, logger).parse(request).matches, [
                { from: 'remove', to: '' },
                { from: 'replace', to: 'me' },
            ]);
        });
    });
});
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2014 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */

module.exports = function(api, tokens, EOF) {
  return {

    read_expr: function() {
      var expr = this.read_expr_item();
      switch(this.token) {
        // binary operations
        case '|': return ['bin', '|', expr, this.next().read_expr()];
        case '&': return ['bin', '&', expr, this.next().read_expr()];
        case '^': return ['bin', '^', expr, this.next().read_expr()];
        case '.': return ['bin', '.', expr, this.next().read_expr()];
        case '+': return ['bin', '+', expr, this.next().read_expr()];
        case '-': return ['bin', '-', expr, this.next().read_expr()];
        case '*': return ['bin', '*', expr, this.next().read_expr()];
        case '/': return ['bin', '/', expr, this.next().read_expr()];
        case '%': return ['bin', '%', expr, this.next().read_expr()];
        case tokens.T_POW:  return ['bin', '**', expr, this.next().read_expr()];
        case tokens.T_SL:   return ['bin', '<<', expr, this.next().read_expr()];
        case tokens.T_SR:   return ['bin', '>>', expr, this.next().read_expr()];

        // boolean operations
        case tokens.T_BOOLEAN_OR:
        case tokens.T_LOGICAL_OR:   return ['bool', '|', expr, this.next().read_expr()];

        case tokens.T_BOOLEAN_AND:
        case tokens.T_LOGICAL_AND:  return ['bool', '&', expr, this.next().read_expr()];

        case tokens.T_LOGICAL_XOR:      return ['bool', '^', expr, this.next().read_expr()];
        case tokens.T_IS_IDENTICAL:     return ['bool', '=', expr, this.next().read_expr()];
        case tokens.T_IS_NOT_IDENTICAL: return ['bool', '!=', expr, this.next().read_expr()];
        case tokens.T_IS_EQUAL:         return ['bool', '~', expr, this.next().read_expr()];
        case tokens.T_IS_NOT_EQUAL:     return ['bool', '!~', expr, this.next().read_expr()];
        case '<':                       return ['bool', '<', expr, this.next().read_expr()];
        case '>':                       return ['bool', '>', expr, this.next().read_expr()];

        case tokens.T_IS_SMALLER_OR_EQUAL:  return ['bool', '<=', expr, this.next().read_expr()];
        case tokens.T_IS_GREATER_OR_EQUAL:  return ['bool', '>=', expr, this.next().read_expr()];
        case tokens.T_INSTANCEOF:           return ['bool', '?', expr, this.next().read_expr()];

        // extra operations :
        case tokens.T_COALESCE: // php7 : $username = $_GET['user'] ?? 'nobody';
          return ['retif', ['sys', 'isset', expr], expr, this.next().read_expr()];
        case '?':
          var trueArg = null;
          if (this.next().token !== ':') {
            trueArg = this.read_expr();
          }
          this.expect(':').next();
          return ['retif', expr, trueArg, this.read_expr()];
      }
      return expr;
    }

    /**
     * <ebnf>
     * Reads an expression
     *  expr ::= @todo
     * </ebnf>
     */
    ,read_expr_item: function() {

      switch(this.token) {

        case '@':
          return ['silence', this.next().read_expr()];

        case '-':
        case '+':
        case '!':
        case '~':
          return ['unary', this.token, this.next().read_expr()];

        case '(':
          var expr = this.next().read_expr();
          this.expect(')').next();
          return expr;

        case '`':
          var expr = null;
          if (this.next().token === tokens.T_ENCAPSED_AND_WHITESPACE) {
            expr = this.text();
            this.next().expect('`').next();
          } else if (this.token !== '`' ) {
            expr = this.read_encaps_list();
          }
          return ['sys', 'shell', expr];

        case tokens.T_LIST:
          return this.read_assignment_list();

        case tokens.T_CLONE:
          return ['sys', 'clone', this.next().read_expr()];

        case tokens.T_INC:
          var name = this.next().read_variable();
          return ['set', name, ['bin', '+', name, ['number', 1]]];

        case tokens.T_DEC:
          var name = this.next().read_variable();
          return ['set', name, ['bin', '-', name, ['number', 1]]];

        case tokens.T_NEW:
          return this.next().read_new_expr();

        case tokens.T_ISSET:
          this.next().expect('(').next();
          // '(' isset_variables ')' { $$ = $3; }
          return ['sys', 'isset'];  // @todo

        case tokens.T_EMPTY:
          this.next().expect('(').next();
          var expr = this.read_expr();
          this.expect(')').next();
          return ['sys', 'empty', expr];

        case tokens.T_INCLUDE:
          return ['sys', 'include', this.next().read_expr()];

        case tokens.T_INCLUDE_ONCE:
          return ['sys', 'include_once', this.next().read_expr()];

        case tokens.T_REQUIRE:
          return ['sys', 'require', this.next().read_expr()];

        case tokens.T_REQUIRE_ONCE:
          return ['sys', 'require', this.next().read_expr()];

        case tokens.T_EVAL:
          this.next().expect('(').next();
          var expr = this.read_expr();
          this.expect(')').next();
          return ['sys', 'eval', expr];

        case tokens.T_INT_CAST:
          return ['cast', 'int', this.next().read_expr()];

        case tokens.T_DOUBLE_CAST:
          return ['cast', 'double', this.next().read_expr()];

        case tokens.T_STRING_CAST:
          return ['cast', 'string', this.next().read_expr()];

        case tokens.T_ARRAY_CAST:
          return ['cast', 'array', this.next().read_expr()];

        case tokens.T_OBJECT_CAST:
          return ['cast', 'object', this.next().read_expr()];

        case tokens.T_BOOL_CAST:
          return ['cast', 'boolean', this.next().read_expr()];

        case tokens.T_UNSET_CAST:
          return ['sys', 'unset', this.next().read_expr()];

        case tokens.T_EXIT:
          var expr = null;
          if ( this.next().token === '(' ) {
            if (this.next().token !== ')') {
              expr = this.read_expr();
              this.expect(')').next();
            }
          }
          return ['sys', 'exit', expr];

        case tokens.T_PRINT:
          return ['sys', 'print', this.next().read_expr()];

        case tokens.T_YIELD:
          var result = ['yield', null, null];
          if (this.next().is('expr')) {
            // reads the yield return value
            result[1] = this.read_expr();
            if (this.token === tokens.T_DOUBLE_ARROW) {
              // reads the yield returned key
              result[2] = this.read_expr();
            }
          }
          return result;

        case tokens.T_STATIC:
        case tokens.T_FUNCTION:
          // @wtf
          var isStatic = false;
          if (this.token === tokens.T_STATIC) {
            this.next();
            isStatic = true;
          }
          return this.read_function_declaration();

      }

      // SCALAR | VARIABLE
      var expr;
      if (this.is('VARIABLE')) {
        expr = this.read_variable();
        // VARIABLES SPECIFIC OPERATIONS
        switch(this.token) {
          case '=':
            if (this.next().token == '&') {
              if (this.next().token === tokens.T_NEW) {
                return ['link', expr, this.next().read_new_expr()];
              } else {
                return ['link', expr, this.read_variable()];
              }
            } else {
              return ['set', expr, this.read_expr()];
            }
          // operations :
          case tokens.T_PLUS_EQUAL:
            return ['set', expr, ['bin', '+', expr, this.next().read_expr()]];
          case tokens.T_MINUS_EQUAL:
            return ['set', expr, ['bin', '-', expr, this.next().read_expr()]];
          case tokens.T_MUL_EQUAL:
            return ['set', expr, ['bin', '*', expr, this.next().read_expr()]];
          case tokens.T_POW_EQUAL:
            return ['set', expr, ['bin', '**', expr, this.next().read_expr()]];
          case tokens.T_DIV_EQUAL:
            return ['set', expr, ['bin', '/', expr, this.next().read_expr()]];
          case tokens.T_CONCAT_EQUAL:
            // NB : convert as string and add
            return ['set', expr, ['bin', '.', expr, this.next().read_expr()]];
          case tokens.T_MOD_EQUAL:
            return ['set', expr, ['bin', '%', expr, this.next().read_expr()]];
          case tokens.T_AND_EQUAL:
            return ['set', expr, ['bin', '&', expr, this.next().read_expr()]];
          case tokens.T_OR_EQUAL:
            return ['set', expr, ['bin', '|', expr, this.next().read_expr()]];
          case tokens.T_XOR_EQUAL:
            return ['set', expr, ['bin', '^', expr, this.next().read_expr()]];
          case tokens.T_SL_EQUAL:
            return ['set', expr, ['bin', '<<', expr, this.next().read_expr()]];
          case tokens.T_SR_EQUAL:
            return ['set', expr, ['bin', '>>', expr, this.next().read_expr()]];
          case tokens.T_INC:
            this.next();
            return ['post', '+', expr];
          case tokens.T_DEC:
            this.next();
            return ['post', '-', expr];
        }
      } else if (this.is('SCALAR')) {
        expr = this.read_scalar();
      } else {
        this.error('EXPR');
      }

      // returns variable | scalar
      return expr;

    }
    /**
     * <ebnf>
     *    new_expr ::= T_NEW
     * </ebnf>
     */
    ,read_new_expr: function() {
      // @todo
      return ['new', this.token];
    }
    /**
     * <ebnf>
     *   assignment_list ::= T_LIST '(' ((variable | assignment_list) (',' (variable | assignment_list))*)? ')'
     * </ebnf>
     */
    ,read_assignment_list: function(innerList) {
      var assignList = [];
      this.expect(tokens.T_LIST).next().expect('(').next();
      while(this.token !== ')' && this.token != EOF) {
        if (this.token === tokens.T_LIST) {
          assignList.push(this.read_assignment_list(true));
        } else {
          assignList.push(this.read_variable());
        }
        if (this.token !== ',') break;
        this.next();
      }
      this.expect(')').next();
      return ['list', assignList, innerList ? false : this.read_expr()];
    }
  };
};<commit_msg>implement the new statement<commit_after>/**
 * Copyright (C) 2014 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */

module.exports = function(api, tokens, EOF) {
  return {

    read_expr: function() {
      var expr = this.read_expr_item();
      switch(this.token) {
        // binary operations
        case '|': return ['bin', '|', expr, this.next().read_expr()];
        case '&': return ['bin', '&', expr, this.next().read_expr()];
        case '^': return ['bin', '^', expr, this.next().read_expr()];
        case '.': return ['bin', '.', expr, this.next().read_expr()];
        case '+': return ['bin', '+', expr, this.next().read_expr()];
        case '-': return ['bin', '-', expr, this.next().read_expr()];
        case '*': return ['bin', '*', expr, this.next().read_expr()];
        case '/': return ['bin', '/', expr, this.next().read_expr()];
        case '%': return ['bin', '%', expr, this.next().read_expr()];
        case tokens.T_POW:  return ['bin', '**', expr, this.next().read_expr()];
        case tokens.T_SL:   return ['bin', '<<', expr, this.next().read_expr()];
        case tokens.T_SR:   return ['bin', '>>', expr, this.next().read_expr()];

        // boolean operations
        case tokens.T_BOOLEAN_OR:
        case tokens.T_LOGICAL_OR:   return ['bool', '|', expr, this.next().read_expr()];

        case tokens.T_BOOLEAN_AND:
        case tokens.T_LOGICAL_AND:  return ['bool', '&', expr, this.next().read_expr()];

        case tokens.T_LOGICAL_XOR:      return ['bool', '^', expr, this.next().read_expr()];
        case tokens.T_IS_IDENTICAL:     return ['bool', '=', expr, this.next().read_expr()];
        case tokens.T_IS_NOT_IDENTICAL: return ['bool', '!=', expr, this.next().read_expr()];
        case tokens.T_IS_EQUAL:         return ['bool', '~', expr, this.next().read_expr()];
        case tokens.T_IS_NOT_EQUAL:     return ['bool', '!~', expr, this.next().read_expr()];
        case '<':                       return ['bool', '<', expr, this.next().read_expr()];
        case '>':                       return ['bool', '>', expr, this.next().read_expr()];

        case tokens.T_IS_SMALLER_OR_EQUAL:  return ['bool', '<=', expr, this.next().read_expr()];
        case tokens.T_IS_GREATER_OR_EQUAL:  return ['bool', '>=', expr, this.next().read_expr()];
        case tokens.T_INSTANCEOF:           return ['bool', '?', expr, this.next().read_expr()];

        // extra operations :
        case tokens.T_COALESCE: // php7 : $username = $_GET['user'] ?? 'nobody';
          return ['retif', ['sys', 'isset', expr], expr, this.next().read_expr()];
        case '?':
          var trueArg = null;
          if (this.next().token !== ':') {
            trueArg = this.read_expr();
          }
          this.expect(':').next();
          return ['retif', expr, trueArg, this.read_expr()];
      }
      return expr;
    }

    /**
     * <ebnf>
     * Reads an expression
     *  expr ::= @todo
     * </ebnf>
     */
    ,read_expr_item: function() {

      switch(this.token) {

        case '@':
          return ['silence', this.next().read_expr()];

        case '-':
        case '+':
        case '!':
        case '~':
          return ['unary', this.token, this.next().read_expr()];

        case '(':
          var expr = this.next().read_expr();
          this.expect(')').next();
          return expr;

        case '`':
          var expr = null;
          if (this.next().token === tokens.T_ENCAPSED_AND_WHITESPACE) {
            expr = this.text();
            this.next().expect('`').next();
          } else if (this.token !== '`' ) {
            expr = this.read_encaps_list();
          }
          return ['sys', 'shell', expr];

        case tokens.T_LIST:
          return this.read_assignment_list();

        case tokens.T_CLONE:
          return ['sys', 'clone', this.next().read_expr()];

        case tokens.T_INC:
          var name = this.next().read_variable();
          return ['set', name, ['bin', '+', name, ['number', 1]]];

        case tokens.T_DEC:
          var name = this.next().read_variable();
          return ['set', name, ['bin', '-', name, ['number', 1]]];

        case tokens.T_NEW:
          return this.next().read_new_expr();

        case tokens.T_ISSET:
          this.next().expect('(').next();
          // '(' isset_variables ')' { $$ = $3; }
          return ['sys', 'isset'];  // @todo

        case tokens.T_EMPTY:
          this.next().expect('(').next();
          var expr = this.read_expr();
          this.expect(')').next();
          return ['sys', 'empty', expr];

        case tokens.T_INCLUDE:
          return ['sys', 'include', this.next().read_expr()];

        case tokens.T_INCLUDE_ONCE:
          return ['sys', 'include_once', this.next().read_expr()];

        case tokens.T_REQUIRE:
          return ['sys', 'require', this.next().read_expr()];

        case tokens.T_REQUIRE_ONCE:
          return ['sys', 'require', this.next().read_expr()];

        case tokens.T_EVAL:
          this.next().expect('(').next();
          var expr = this.read_expr();
          this.expect(')').next();
          return ['sys', 'eval', expr];

        case tokens.T_INT_CAST:
          return ['cast', 'int', this.next().read_expr()];

        case tokens.T_DOUBLE_CAST:
          return ['cast', 'double', this.next().read_expr()];

        case tokens.T_STRING_CAST:
          return ['cast', 'string', this.next().read_expr()];

        case tokens.T_ARRAY_CAST:
          return ['cast', 'array', this.next().read_expr()];

        case tokens.T_OBJECT_CAST:
          return ['cast', 'object', this.next().read_expr()];

        case tokens.T_BOOL_CAST:
          return ['cast', 'boolean', this.next().read_expr()];

        case tokens.T_UNSET_CAST:
          return ['sys', 'unset', this.next().read_expr()];

        case tokens.T_EXIT:
          var expr = null;
          if ( this.next().token === '(' ) {
            if (this.next().token !== ')') {
              expr = this.read_expr();
              this.expect(')').next();
            }
          }
          return ['sys', 'exit', expr];

        case tokens.T_PRINT:
          return ['sys', 'print', this.next().read_expr()];

        case tokens.T_YIELD:
          var result = ['yield', null, null];
          if (this.next().is('expr')) {
            // reads the yield return value
            result[1] = this.read_expr();
            if (this.token === tokens.T_DOUBLE_ARROW) {
              // reads the yield returned key
              result[2] = this.read_expr();
            }
          }
          return result;

        case tokens.T_STATIC:
        case tokens.T_FUNCTION:
          // @wtf
          var isStatic = false;
          if (this.token === tokens.T_STATIC) {
            this.next();
            isStatic = true;
          }
          return this.read_function_declaration();

      }

      // SCALAR | VARIABLE
      var expr;
      if (this.is('VARIABLE')) {
        expr = this.read_variable();
        // VARIABLES SPECIFIC OPERATIONS
        switch(this.token) {
          case '=':
            if (this.next().token == '&') {
              if (this.next().token === tokens.T_NEW) {
                return ['link', expr, this.next().read_new_expr()];
              } else {
                return ['link', expr, this.read_variable()];
              }
            } else {
              return [
                'set',
                expr,
                this.token === tokens.T_NEW ?
                  this.next().read_new_expr() : this.read_expr()
              ];
            }
          // operations :
          case tokens.T_PLUS_EQUAL:
            return ['set', expr, ['bin', '+', expr, this.next().read_expr()]];
          case tokens.T_MINUS_EQUAL:
            return ['set', expr, ['bin', '-', expr, this.next().read_expr()]];
          case tokens.T_MUL_EQUAL:
            return ['set', expr, ['bin', '*', expr, this.next().read_expr()]];
          case tokens.T_POW_EQUAL:
            return ['set', expr, ['bin', '**', expr, this.next().read_expr()]];
          case tokens.T_DIV_EQUAL:
            return ['set', expr, ['bin', '/', expr, this.next().read_expr()]];
          case tokens.T_CONCAT_EQUAL:
            // NB : convert as string and add
            return ['set', expr, ['bin', '.', expr, this.next().read_expr()]];
          case tokens.T_MOD_EQUAL:
            return ['set', expr, ['bin', '%', expr, this.next().read_expr()]];
          case tokens.T_AND_EQUAL:
            return ['set', expr, ['bin', '&', expr, this.next().read_expr()]];
          case tokens.T_OR_EQUAL:
            return ['set', expr, ['bin', '|', expr, this.next().read_expr()]];
          case tokens.T_XOR_EQUAL:
            return ['set', expr, ['bin', '^', expr, this.next().read_expr()]];
          case tokens.T_SL_EQUAL:
            return ['set', expr, ['bin', '<<', expr, this.next().read_expr()]];
          case tokens.T_SR_EQUAL:
            return ['set', expr, ['bin', '>>', expr, this.next().read_expr()]];
          case tokens.T_INC:
            this.next();
            return ['post', '+', expr];
          case tokens.T_DEC:
            this.next();
            return ['post', '-', expr];
        }
      } else if (this.is('SCALAR')) {
        expr = this.read_scalar();
      } else {
        this.error('EXPR');
      }

      // returns variable | scalar
      return expr;

    }
    /**
     * <ebnf>
     *    new_expr ::= T_NEW namespace_name function_argument_list
     * </ebnf>
     */
    ,read_new_expr: function() {
      var name = this.read_namespace_name();
      var args = this.read_function_argument_list();
      return ['new', name, args];
    }
    /**
     * <ebnf>
     *   assignment_list ::= T_LIST '(' ((variable | assignment_list) (',' (variable | assignment_list))*)? ')'
     * </ebnf>
     */
    ,read_assignment_list: function(innerList) {
      var assignList = [];
      this.expect(tokens.T_LIST).next().expect('(').next();
      while(this.token !== ')' && this.token != EOF) {
        if (this.token === tokens.T_LIST) {
          assignList.push(this.read_assignment_list(true));
        } else {
          assignList.push(this.read_variable());
        }
        if (this.token !== ',') break;
        this.next();
      }
      this.expect(')').next();
      return ['list', assignList, innerList ? false : this.read_expr()];
    }
  };
};<|endoftext|>


<commit_before>var p_trail = PClass.extend({

  deps: [
    'scale',
  ],

  _subscriptions: [{
    'Scale/updated': function() {
      if (this._status.x) {
        this._moveToValue(this._status.xvalue);
      }
    }
  }],

  initialize: function() {
    var self = this;
    if (!this.opts.trail.enabled) {return;}
    this._status = {xvalue: null, x: null};
    this._renderTrail();

    setTimeout(function() {
      self._moveToValue(self.opts.trail.initXValue(self.scale.x));
    }, 0);
  },

  _renderTrail: function() {
    var trail = this.$svg.append('g')
      .attr('class', 'trail');

    var markerHeight = 11;

    // Append marker definition
    var markerdef = this.$svg.append('svg:marker')
      .attr('id', 'trailArrow')
      .attr('viewBox','0 0 20 20')
      .attr('refX','20')
      .attr('refY',markerHeight)
      .attr('markerUnits','strokeWidth')
      .attr('markerWidth','15')
      .attr('markerHeight',markerHeight)
      .attr('orient','auto')
      .append('svg:path')
        .attr('class', 'trail-arrow')
        .attr('d','M 0 0 L 20 10 L 0 20 z')
        .attr('fill', '#777');

    // Append trail line
    this.trailLine = trail.append('svg:line')
      .attr('class', 'trail-line')
        .attr('x1', this.opts.width)
        .attr('x2', this.opts.width)
        .attr('y1', 0)
        .attr('y2', this.opts.height)
        .attr('marker-start', 'url(#trailArrow)');

    this.brush = d3.svg.brush()
      .x(this.scale.x)
      .extent([0, 0]);

    this.bisector = d3.bisector(function(d) {
      return d.x;
    }).left;

    // Append slider zone
    this.sliderZone = this.$svg.append('g')
      .attr('transform', h_getTranslate(0,-markerHeight))
      .attr('class', 'trail-slider-zone')
      .call(this.brush);

    this.sliderZone.select('.background')
      .attr('height', this.opts.fullHeight)
      .attr('width', this.opts.width)
      .style('cursor', 'pointer');

    this.$svg.selectAll('.extent,.resize').remove();
    this._setEvents();
  },

  _setEvents: function() {
    var self = this;
    this.brush.on('brush', function() {
      self._onBrush(this);
    });
  },

  /**
   * Triggered when the user moves the trail.
   * @param  {Event} event d3 brush event
   */
  _onBrush: function(event) {
    var x;
    if (d3.event.sourceEvent) {
      x = this.scale.x.invert(d3.mouse(event)[0]);
    } else {
      x = brush.extent()[0];
    }
    this._moveToValue(x);
  },

  /**
   * Moves the trail to supplied xvalue.
   */
  _moveToValue: function(xvalue) {
    var xdomain = this.scale.x.domain(),
        isDate = !!xvalue.getMonth;

    // if the seleted x is outside the domain,
    // select range ones.
    if (isDate) {
      if (Date.parse(xvalue) > Date.parse(xdomain[1])) {
        xvalue = xdomain[1];
      } else if (Date.parse(xvalue) < Date.parse(xdomain[0])) {
        xvalue = xdomain[0];
      }
    } else {
      if (xvalue > xdomain[1]) {
        xvalue = xdomain[1];
      } else if (xvalue < xdomain[0]) {
        xvalue = xdomain[0];
      }
    }

    // parse data (this way the user can filter by specific step)
    // eg. months, years, minutes
    xvalue = this.opts.trail.parseStep(xvalue);
    var x = Math.round(this.scale.x(xvalue));
    if (x === this._status.x) {return;} // Return if it's already selected
    var data = this._getDataFromValue(xvalue);
    this._status.x = x;
    this._status.xvalue = xvalue;
    this._moveTrail(x);
    this.trigger('Trail/moved', [data, xvalue]);
  },

  _getDataFromValue: function(xvalue) {
    var self = this;
    var trailData = _.map(this.data, function(serie) {
      var value;

      if (serie.type === 'line') {
        var index = self.bisector(serie.values, xvalue) - 1;
        if (index < 0) {index=0;}

        value = serie.values[index];
        if (!value) {
          value = {x: null, y: null};
        }
        return _.extend({}, value, {id: serie.id}, _.omit(serie, 'values', 'path'));
      } else if (serie.type === 'bar' || serie.type === 'area') {
        return _.map(serie.data, function(d) {
          return _.extend(d.values[self.bisector(d.values, xvalue)],
            {id: d.id}, _.omit(d, 'values'));
        });
      }
    });

    return trailData;
  },

  /**
   * Move the trail to the given x position.
   *
   * @param  {integer} x
   */
  _moveTrail: function(x) {
    this.trailLine.attr('x1', x).attr('x2', x);
  }

});<commit_msg>charichart hotfix<commit_after>var p_trail = PClass.extend({

  deps: [
    'scale',
  ],

  _subscriptions: [{
    'Scale/updated': function() {
      if (this._status.x) {
        this._moveToValue(this._status.xvalue);
      }
    }
  }],

  initialize: function() {
    var self = this;
    if (!this.opts.trail.enabled) {return;}
    this._status = {xvalue: null, x: null};
    this._renderTrail();

    setTimeout(function() {
      self._moveToValue(self.opts.trail.initXValue(self.scale.x));
    }, 0);
  },

  _renderTrail: function() {
    var trail = this.$svg.append('g')
      .attr('class', 'trail');

    var markerHeight = 11;

    // Append marker definition
    var markerdef = this.$svg.append('svg:marker')
      .attr('id', 'trailArrow')
      .attr('viewBox','0 0 20 20')
      .attr('refX','20')
      .attr('refY',markerHeight)
      .attr('markerUnits','strokeWidth')
      .attr('markerWidth','15')
      .attr('markerHeight',markerHeight)
      .attr('orient','auto')
      .append('svg:path')
        .attr('class', 'trail-arrow')
        .attr('d','M 0 0 L 20 10 L 0 20 z')
        .attr('fill', '#777');

    // Append trail line
    this.trailLine = trail.append('svg:line')
      .attr('class', 'trail-line')
        .attr('x1', this.opts.width)
        .attr('x2', this.opts.width)
        .attr('y1', 0)
        .attr('y2', this.opts.height)
        .attr('marker-start', 'url(#trailArrow)');

    this.brush = d3.svg.brush()
      .x(this.scale.x)
      .extent([0, 0]);

    this.bisector = d3.bisector(function(d) {
      return d.x;
    }).left;

    // Append slider zone
    this.sliderZone = this.$svg.append('g')
      .attr('transform', h_getTranslate(0,-markerHeight))
      .attr('class', 'trail-slider-zone')
      .call(this.brush);

    this.sliderZone.select('.background')
      .attr('height', this.opts.fullHeight)
      .attr('width', this.opts.width)
      .style('cursor', 'pointer');

    this.$svg.selectAll('.extent,.resize').remove();
    this._setEvents();
  },

  _setEvents: function() {
    var self = this;
    this.brush.on('brush', function() {
      self._onBrush(this);
    });
  },

  /**
   * Triggered when the user moves the trail.
   * @param  {Event} event d3 brush event
   */
  _onBrush: function(event) {
    var x;
    if (d3.event.sourceEvent) {
      x = this.scale.x.invert(d3.mouse(event)[0]);
    } else {
      x = brush.extent()[0];
    }
    this._moveToValue(x);
  },

  /**
   * Moves the trail to supplied xvalue.
   */
  _moveToValue: function(xvalue) {
    var xdomain = this.scale.x.domain(),
        isDate = !!xvalue.getMonth;

    // if the seleted x is outside the domain,
    // select range ones.
    if (isDate) {
      if (Date.parse(xvalue) > Date.parse(xdomain[1])) {
        xvalue = xdomain[1];
      } else if (Date.parse(xvalue) < Date.parse(xdomain[0])) {
        xvalue = xdomain[0];
      }
    } else {
      if (xvalue > xdomain[1]) {
        xvalue = xdomain[1];
      } else if (xvalue < xdomain[0]) {
        xvalue = xdomain[0];
      }
    }

    // parse data (this way the user can filter by specific step)
    // eg. months, years, minutes
    xvalue = this.opts.trail.parseStep(xvalue);
    var x = Math.round(this.scale.x(xvalue));
    if (x === this._status.x) {return;} // Return if it's already selected
    var data = this._getDataFromValue(xvalue);
    this._status.x = x;
    this._status.xvalue = xvalue;
    this._moveTrail(x);
    this.trigger('Trail/moved', [data, xvalue]);
  },

  _getDataFromValue: function(xvalue) {
    var self = this;
    var trailData = _.map(this.data, function(serie) {
      var value;

      if (serie.type === 'line') {
        var index = self.bisector(serie.values, xvalue);
        if (index < 0) {index=0;}

        value = serie.values[index];
        if (!value) {
          value = {x: null, y: null};
        }
        return _.extend({}, value, {id: serie.id}, _.omit(serie, 'values', 'path'));
      } else if (serie.type === 'bar' || serie.type === 'area') {
        return _.map(serie.data, function(d) {
          return _.extend(d.values[self.bisector(d.values, xvalue)],
            {id: d.id}, _.omit(d, 'values'));
        });
      }
    });

    return trailData;
  },

  /**
   * Move the trail to the given x position.
   *
   * @param  {integer} x
   */
  _moveTrail: function(x) {
    this.trailLine.attr('x1', x).attr('x2', x);
  }

});
<|endoftext|>


<commit_before>/**
 * Patterns subform - scoped submission of form content
 *
 * Copyright 2013 Marko Durkovic
 */
define([
    "jquery",
    "../registry",
    "../core/logger",
    "../core/parser",
    "./ajax",
    "./inject"
], function($, registry, logging, Parser, ajax, inject) {
    var log = logging.getLogger("subform");

    var _ = {
        name: "subform",
        trigger: ".pat-subform",

        init: function($el) {
            return $el.each(function() {
                var $el = $(this);

                $el.submit(_.submit);
                $el.find('button[type=submit]').on('click', _.submitClicked);
                return $el;
            });
        },

        destroy: function($el) {
            $el.off('submit');
        },

        scopedSubmit: function($el) {
            var $form = $el.parents('form'),
                $exclude = $form
                            .find(':input')
                            .filter(function() {
                                return !$(this).is($el.find('*'));
                            });

            // make other controls 'unsuccessful'
            log.debug('Hiding unwanted elements from submission.');
            var names = $exclude.map(function() {
                return $(this).attr('name');
            });

            $exclude.each(function() {
                $(this).attr('name', '');
            });

            if ($el.is('.pat-inject')) {
                inject.submitSubform($el);
            } else {
                // use the native handler, since there could be event handlers
                // redirecting to inject/ajax.
                $form[0].submit();
            }

            // reenable everything
            log.debug('Restoring previous state.');
            $exclude.each(function(i) {
                $(this).attr('name', names[i]);
            });
        },

        submit: function(ev) {
            ev.stopPropagation();

            var $this = $(this),
                $button = $this.find('button[type=submit][formaction]').first();
            if ($button) {
                $button.trigger('click');
            } else {
                _.scopedSubmit($this);
            }
        },

        submitClicked: function(ev) {
            ev.preventDefault();
            ev.stopPropagation();

            // make sure the submitting button is send with the form
            ajax.onClickSubmit(ev);

            var $button = $(ev.target),
                $sub = $button.parents('.pat-subform').first(),
                formaction = $button.attr('formaction');

            if (formaction) {
                // override the default action and restore afterwards
                if ($sub.is('.pat-inject')) {
                    var previousValue = $sub.data('patterns.inject');
                    $sub.data('patterns.inject', inject.extractConfig($sub, {
                        url: formaction
                    }));

                    _.scopedSubmit($sub);

                    $sub.data('patterns.inject', previousValue);
                } else {
                    $sub.parents('form').attr('action', formaction);
                    _.scopedSubmit($sub);
                }
            } else {
                _.scopedSubmit($sub);
            }

        }
    };

    registry.register(_);
    return _;
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Fix detection of buttons.<commit_after>/**
 * Patterns subform - scoped submission of form content
 *
 * Copyright 2013 Marko Durkovic
 */
define([
    "jquery",
    "../registry",
    "../core/logger",
    "../core/parser",
    "./ajax",
    "./inject"
], function($, registry, logging, Parser, ajax, inject) {
    var log = logging.getLogger("subform");

    var _ = {
        name: "subform",
        trigger: ".pat-subform",

        init: function($el) {
            return $el.each(function() {
                var $el = $(this);

                $el.submit(_.submit);
                $el.find('button[type=submit]').on('click', _.submitClicked);
                return $el;
            });
        },

        destroy: function($el) {
            $el.off('submit');
        },

        scopedSubmit: function($el) {
            var $form = $el.parents('form'),
                $exclude = $form
                            .find(':input')
                            .filter(function() {
                                return !$(this).is($el.find('*'));
                            });

            // make other controls 'unsuccessful'
            log.debug('Hiding unwanted elements from submission.');
            var names = $exclude.map(function() {
                return $(this).attr('name');
            });

            $exclude.each(function() {
                $(this).attr('name', '');
            });

            if ($el.is('.pat-inject')) {
                inject.submitSubform($el);
            } else {
                // use the native handler, since there could be event handlers
                // redirecting to inject/ajax.
                $form[0].submit();
            }

            // reenable everything
            log.debug('Restoring previous state.');
            $exclude.each(function(i) {
                $(this).attr('name', names[i]);
            });
        },

        submit: function(ev) {
            ev.stopPropagation();

            var $this = $(this),
                $button = $this.find('button[type=submit][formaction]').first();
            if ($button.length) {
                $button.trigger('click');
            } else {
                _.scopedSubmit($this);
            }
        },

        submitClicked: function(ev) {
            ev.preventDefault();
            ev.stopPropagation();

            // make sure the submitting button is send with the form
            ajax.onClickSubmit(ev);

            var $button = $(ev.target),
                $sub = $button.parents('.pat-subform').first(),
                formaction = $button.attr('formaction');

            if (formaction) {
                // override the default action and restore afterwards
                if ($sub.is('.pat-inject')) {
                    var previousValue = $sub.data('patterns.inject');
                    $sub.data('patterns.inject', inject.extractConfig($sub, {
                        url: formaction
                    }));

                    _.scopedSubmit($sub);

                    $sub.data('patterns.inject', previousValue);
                } else {
                    $sub.parents('form').attr('action', formaction);
                    _.scopedSubmit($sub);
                }
            } else {
                _.scopedSubmit($sub);
            }

        }
    };

    registry.register(_);
    return _;
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>define(['pex/gl/Context'], function(Context) {
  function Mesh(geometry, material) {
    this.gl = Context.currentContext.gl;
    this.geometry = geometry;
    this.material = material;
  }
});<commit_msg>First version of working Mesh class<commit_after>define(['pex/gl/Context', 'pex/geom/Vec3', 'pex/geom/Quat', 'pex/geom/Mat4'],
function(Context, Vec3, Quat, Mat4) {
  function Mesh(geometry, material) {
    this.gl = Context.currentContext.gl;
    this.geometry = geometry;
    this.material = material;

    this.gl = Context.currentContext.gl;
    //this.primitiveType = (primitiveType !== undefined) ? primitiveType : this.gl.TRIANGLES;
    this.primitiveType = this.gl.TRIANGLES;
    this.attributes = {};
    this.usage = this.gl.STATIC_DRAW;

    this.addAttrib("position", geometry.vertices, 3);

    this.position = Vec3.fromValues(0, 0, 0);
    this.rotation = Quat.create();
    this.scale = Vec3.fromValues(1, 1, 1);
    this.modelWorldMatrix = Mat4.create();
    this.modelViewMatrix = Mat4.create();
    this.rotationMatrix = Mat4.create();
  }

  Mesh.prototype.updateMatrices = function(camera) {
    Mat4.fromQuat(this.rotationMatrix, this.rotation);

    Mat4.identity(this.modelWorldMatrix);
    Mat4.translate(this.modelWorldMatrix, this.modelWorldMatrix, this.position);
    Mat4.mul(this.modelWorldMatrix, this.modelWorldMatrix, this.rotationMatrix);
    Mat4.scale(this.modelWorldMatrix, this.modelWorldMatrix, this.scale);

    Mat4.copy(this.modelViewMatrix, camera.getViewMatrix());
    Mat4.mul(this.modelViewMatrix, this.modelViewMatrix, this.modelWorldMatrix);
  }

  Mesh.prototype.addAttrib = function(name, data, elementSize, usage) {
    elementSize = elementSize || 3
    usage = usage || this.usage;

    var dataArr = [];
    data.forEach(function(v) {
      dataArr.push(v[0], v[1], v[2]);
    })
    var dataBuf = new Float32Array(dataArr);

    var attrib = {};
    attrib.name = name;
    attrib.data = dataArr;
    attrib.elementSize = elementSize;
    attrib.location = -1;
    attrib.buffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, attrib.buffer);
    this.gl.bufferData(this.gl.ARRAY_BUFFER, dataBuf, usage);

    this.attributes[attrib.name] = attrib;
  }

  Mesh.prototype.draw = function(camera) {
    var programUniforms = this.material.program.uniforms;
    var materialUniforms = this.material.uniforms;
    if (camera) {
      this.updateMatrices(camera);
      if (programUniforms.projectionMatrix) {
        materialUniforms.projectionMatrix = camera.getProjectionMatrix();
      }
      //if (programUniforms.viewMatrix)
      //  materialUniforms.viewMatrix = camera.getViewMatrix();
      if (programUniforms.modelViewMatrix) {
        materialUniforms.modelViewMatrix = this.modelViewMatrix;
      }
      //if (programUniforms.modelWorldMatrix)
      //  materialUniforms.modelWorldMatrix = this.modelWorldMatrix;
      //if (programUniforms.normalMatrix)
      //  materialUniforms.normalMatrix = this.material.uniforms.modelViewMatrix.dup().invert().transpose();
    }

    this.material.use();

    var program = this.material.program;
    for(var name in this.attributes) {
      var attrib = this.attributes[name];
      /*
      TODO:this should go another way
      instad of searching for mesh atribs in shader
      look for required attribs by shader inside mesh
      */
      if (attrib.location === undefined || attrib.location == -1) {
        attrib.location = this.gl.getAttribLocation(program.handle, attrib.name);
      }
      if (attrib.location >= 0) {
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, attrib.buffer);
        this.gl.vertexAttribPointer(attrib.location, attrib.elementSize, this.gl.FLOAT, false, 0, 0);
        this.gl.enableVertexAttribArray(attrib.location);
      }
    }

    //return;

    //if (this.indices) {
    //  this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.indices.buffer);
    //  this.gl.drawElements(this.primitiveType, this.indices.data.length, this.gl.UNSIGNED_SHORT, 0);
    //}
    //else if (this.attributes["position"]){
      var num = this.attributes["position"].data.length/3;
      this.gl.drawArrays(this.primitiveType, 0, num);
    //}

    //for(var name in this.attributes) {
    //  var attrib = this.attributes[name];
    //  if (attrib.location >= 0) {
    //    this.gl.disableVertexAttribArray(attrib.location);
    //  }
    //}
  }

  return Mesh;
});<|endoftext|>


<commit_before>
// wait for the DOM to be loaded
$(document).ready(function() {
    $("#Connect").click(function() {
	$.ajax({url        : "/scripts/db_connect.pl",
		type       : "post",
//		beforeSend : beforeFunc,
		data       : "url=" + $("#db_url").val(),
//		data       : "url=" + $("#db_url").serialize(),
		success    : function(res) {
		    $("#connexion_msg").html(res);
		}});
    });

});

function beforeFunc() {
    alert("url=" + $("#db_url").val())
}
<commit_msg>parse json in db connexion<commit_after>
// wait for the DOM to be loaded
$(document).ready(function() {
    $("#Connect").click(function() {
	$.ajax({url        : "/scripts/db_connect.pl",
		type       : "post",
		data       : "url=" + $("#db_url").val(),
		success    : function(res) {
		    var resObj = JSON.parse(res)
		    $("#connexion_msg").html(resObj.status);
		    $("#pipeline_diagram").html(resObj.analyses);
		}});
    });

});

function beforeFunc() {
    alert("url=" + $("#db_url").val())
}
<|endoftext|>


<commit_before>"use strict"; // strict mode syntax
require(["libs/jquery/jquery-1.11.2.js"]);
require(["libs/jquery/jquery-ui.js"]);
require(["libs/handsontable/handsontable.full.min.js"]);
require(["libs/PapaParse/papaparse.min.js"]);
require(["libs/chartjs/Chart.js"]);
require(["libs/jsfx/audio.js"], function(audio){
  require(["libs/jsfx/jsfx.js"]);
  require(["libs/jsfx/jsfxlib.js"]);
});
require(["javascript/files.js"], function(print){
  loadListener();
});
//require(["javascript/table.js"]);
require(["javascript/slickTable.js"]);
require(["javascript/chart.js"]);
require(["javascript/overlay.js"]);
require(["javascript/arrayInfo.js"]);
require(["javascript/audioPlayer.js"]);
require(["javascript/arrayCollection.js"]);
require(["javascript/global.js"]);

var player;
var overlay;
// initial data load
// (this is called after fileOpen from files.js)
var loadData = function(data){
  document.querySelector('#overlay').setAttribute('style','');
  document.querySelector('#table').innerHTML = '';
  //var table = loadTable(data.data);
  var slickTable = loadSlickTable(data.data);
  var chart = loadChart(data.data);
  player = new AudioPlayer();
  overlay = new Overlay(data);
  overlay.updateSize(chart);
  //linkTable(chart, player, overlay);
  linkSlickTable(chart,player,overlay);
  var collection = new ArrayCollection(data.data);
  player.setCollection(collection.collection);
  document.getElementById('color-expand').style.display = 'block';
  document.getElementById('data-summary').style.display = 'block';

  var summaryDiv = document.getElementById("tblSummary");
  for (var i = 0; i < collection.collection.length; i++) {
      summaryDiv.innerHTML += " Line " + (i + 1) + " : Max: " + collection.collection[i].trend.max +
        " Min: " + collection.collection[i].trend.min +
        " Average: " + collection.collection[i].trend.avg + "
";
  }
  summaryDiv.innerHTML += "Total Data Summary : Max: " + collection.max +
    " Min: " + collection.min + " Average: " + calcCollectionAvg(collection);

}

// The play button
var playStopAudioButton = function(){
  player.playToggle(document.getElementById("lineDropdown").value - 1, overlay.slider[0], overlay.slider[1]);
}

// Opens the color editor
var openColorEditor = function(){
  var editor = document.getElementById('color-editor');
  editor.style.display = editor.style.display == 'inline' ? 'none' : 'block';
}

var calcCollectionAvg = function(collection) {
  var collTotal = 0;

  for (var i = 0; i < collection.collection.length; i++){
    collTotal += collection.collection[i].trend.sum;
  }

  var totalDataPoints = 0;
  for (var i = 0; i < collection.collection.length; i++) {
      totalDataPoints += collection.collection[i].array.length;
  }

  var average = Math.round(100 * collTotal/totalDataPoints)/100;
  return average;
 }
<commit_msg>changed innerHTML to slickIndex<commit_after>"use strict"; // strict mode syntax
require(["libs/jquery/jquery-1.11.2.js"]);
require(["libs/jquery/jquery-ui.js"]);
require(["libs/handsontable/handsontable.full.min.js"]);
require(["libs/PapaParse/papaparse.min.js"]);
require(["libs/chartjs/Chart.js"]);
require(["libs/jsfx/audio.js"], function(audio){
  require(["libs/jsfx/jsfx.js"]);
  require(["libs/jsfx/jsfxlib.js"]);
});
require(["javascript/files.js"], function(print){
  loadListener();
});
//require(["javascript/table.js"]);
require(["javascript/slickTable.js"]);
require(["javascript/chart.js"]);
require(["javascript/overlay.js"]);
require(["javascript/arrayInfo.js"]);
require(["javascript/audioPlayer.js"]);
require(["javascript/arrayCollection.js"]);
require(["javascript/global.js"]);

var player;
var overlay;
// initial data load
// (this is called after fileOpen from files.js)
var loadData = function(data){
  document.querySelector('#overlay').setAttribute('style','');
  document.querySelector('#slickTable').innerHTML = '';
  var slickTable = loadSlickTable(data.data);
  var chart = loadChart(data.data);
  player = new AudioPlayer();
  overlay = new Overlay(data);
  overlay.updateSize(chart);
  linkSlickTable(chart,player,overlay);
  var collection = new ArrayCollection(data.data);
  player.setCollection(collection.collection);
  document.getElementById('color-expand').style.display = 'block';
  document.getElementById('data-summary').style.display = 'block';

  var summaryDiv = document.getElementById("tblSummary");
  for (var i = 0; i < collection.collection.length; i++) {
      summaryDiv.innerHTML += " Line " + (i + 1) + " : Max: " + collection.collection[i].trend.max +
        " Min: " + collection.collection[i].trend.min +
        " Average: " + collection.collection[i].trend.avg + "
";
  }
  summaryDiv.innerHTML += "Total Data Summary : Max: " + collection.max +
    " Min: " + collection.min + " Average: " + calcCollectionAvg(collection);

}

// The play button
var playStopAudioButton = function(){
  player.playToggle(document.getElementById("lineDropdown").value - 1, overlay.slider[0], overlay.slider[1]);
}

// Opens the color editor
var openColorEditor = function(){
  var editor = document.getElementById('color-editor');
  editor.style.display = editor.style.display == 'inline' ? 'none' : 'block';
}

var calcCollectionAvg = function(collection) {
  var collTotal = 0;

  for (var i = 0; i < collection.collection.length; i++){
    collTotal += collection.collection[i].trend.sum;
  }

  var totalDataPoints = 0;
  for (var i = 0; i < collection.collection.length; i++) {
      totalDataPoints += collection.collection[i].array.length;
  }

  var average = Math.round(100 * collTotal/totalDataPoints)/100;
  return average;
 }
<|endoftext|>