<commit_before>// @ts-check

import Bluebird from "bluebird"
import "artsy-newrelic"
import xapp from "artsy-xapp"
import cors from "cors"
import depthLimit from "graphql-depth-limit"
import morgan from "artsy-morgan"
import express from "express"
import forceSSL from "express-force-ssl"
import graphqlHTTP from "express-graphql"
import bodyParser from "body-parser"
import schema from "./schema"
import legacyLoaders from "./lib/loaders/legacy"
import createLoaders from "./lib/loaders"
import config from "./config"
import { info, error } from "./lib/loggers"
import graphqlErrorHandler from "./lib/graphql-error-handler"
import moment from "moment"
import "moment-timezone"
import Tracer from "datadog-tracer"
import { forIn, has, assign } from "lodash"
import uuid from "uuid/v1"
import { fetchLoggerSetup, fetchLoggerRequestDone } from "lib/loaders/api/logger"
import { timestamp } from "./lib/helpers"
import { getNamedType, GraphQLObjectType } from "graphql"

global.Promise = Bluebird

const { PORT, NODE_ENV, GRAVITY_API_URL, GRAVITY_ID, GRAVITY_SECRET, QUERY_DEPTH_LIMIT } = process.env

const app = express()
const port = PORT || 3000
const queryLimit = parseInt(QUERY_DEPTH_LIMIT, 10) || 10 // Default to ten.
const isProduction = NODE_ENV === "production"

if (isProduction) {
  app.set("forceSSLOptions", { trustXFPHeader: true }).use(forceSSL)
  app.set("trust proxy", 1)
}

xapp.on("error", err => {
  error(err)
  process.exit()
})

xapp.init(
  {
    url: GRAVITY_API_URL,
    id: GRAVITY_ID,
    secret: GRAVITY_SECRET,
  },
  () => (config.GRAVITY_XAPP_TOKEN = xapp.token)
)

app.get("/favicon.ico", (_req, res) => {
  res
    .status(200)
    .set({ "Content-Type": "image/x-icon" })
    .end()
})

app.all("/graphql", (_req, res) => res.redirect("/"))

app.use(bodyParser.json())

function parse_args() {
  return "( ... )"
}

function drop_params(query) {
  return query.replace(/(\()([^\)]*)(\))/g, parse_args)
}

function pushFinishedSpan(finishedSpans, span) {
  const endTime = timestamp()
  finishedSpans.push({ span, endTime })
}

function processFinishedSpans(finishedSpans) {
  console.log(finishedSpans.length)
  let i = 0
  const iter = () => {
    const entry = finishedSpans[i]
    if (entry) {
      const { span, endTime } = entry
      span.finish(endTime)
      i++
      setImmediate(iter)
    }
  }
  setImmediate(iter)
}

function trace(res, span, finishedSpans) {
  span.addTags({
    "http.status_code": res.statusCode,
  })
  pushFinishedSpan(finishedSpans, span)
  processFinishedSpans(finishedSpans)
}

app.use((req, res, next) => {
  const tracer = new Tracer({ service: "metaphysics" })
  const span = tracer.startSpan("metaphysics.query")
  span.addTags({
    type: "web",
    "span.kind": "server",
    "http.method": req.method,
    "http.url": req.url,
  })

  if (req.body && req.body.query) {
    const query = drop_params(req.body.query)
    span.addTags({ resource: query })
  } else {
    span.addTags({ resource: req.path })
  }

  assign(req, { span })

  const finishedSpans = []
  assign(req, { finishedSpans })

  const finish = trace.bind(null, res, span, finishedSpans)
  res.on("finish", finish)
  res.on("close", finish)

  next()
})

function wrapResolve(typeName, fieldName, resolver) {
  return function (root, opts, req, { rootValue }) {
    const parentSpan = rootValue.span
    const span = parentSpan
      .tracer()
      .startSpan("metaphysics.resolver." + typeName + "." + fieldName, { childOf: parentSpan.context() })
    span.addTags({
      resource: typeName + ": " + fieldName,
      type: "web",
      "span.kind": "server",
    })

    // Set the parent context to this span for any sub resolvers.
    rootValue.span = span // eslint-disable-line no-param-reassign

    const result = resolver.apply(this, arguments)

    // Return parent context to our parent for any resolvers called after this one.
    rootValue.span = parentSpan // eslint-disable-line no-param-reassign

    if (result instanceof Promise) {
      return result.finally(function () {
        pushFinishedSpan(rootValue.finishedSpans, span)
      })
    }

    pushFinishedSpan(rootValue.finishedSpans, span)
    return result
  }
}

// Walk the schema and for all object type fields with resolvers wrap them in our tracing resolver.
forIn(schema._typeMap, function (value, key) {
  const typeName = key
  if (has(value, "_fields")) {
    forIn(value._fields, function (field, fieldName) {
      if (field.resolve instanceof Function && getNamedType(field.type) instanceof GraphQLObjectType) {
        field.resolve = wrapResolve(typeName, fieldName, field.resolve) // eslint-disable-line no-param-reassign
      }
    })
  }
})

app.use(
  "/",
  cors(),
  morgan,
  graphqlHTTP(request => {
    info("----------")

    legacyLoaders.clearAll()

    const accessToken = request.headers["x-access-token"]
    const userID = request.headers["x-user-id"]
    const timezone = request.headers["x-timezone"]
    const requestID = request.headers["x-request-id"] || uuid()

    const span = request.span
    const traceContext = span.context()
    const traceId = traceContext.traceId
    const parentSpanId = traceContext.spanId
    const requestIDs = { requestID, traceId, parentSpanId }

    if (!isProduction) {
      fetchLoggerSetup(requestID)
    }

    // Accepts a tz database timezone string. See http://www.iana.org/time-zones,
    // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
    let defaultTimezone
    if (moment.tz.zone(timezone)) {
      defaultTimezone = timezone
    }

    return {
      schema,
      graphiql: true,
      rootValue: {
        accessToken,
        userID,
        defaultTimezone,
        span,
        finishedSpans: request.finishedSpans,
        ...createLoaders(accessToken, userID, requestIDs),
      },
      formatError: graphqlErrorHandler(request.body),
      validationRules: [depthLimit(queryLimit)],
      extensions: isProduction ? undefined : fetchLoggerRequestDone(requestID),
    }
  })
)

app.listen(port, () => info(`Listening on ${port}`))
<commit_msg>[tracing] Don’t instrument introspection query resolvers.<commit_after>// @ts-check

import Bluebird from "bluebird"
import "artsy-newrelic"
import xapp from "artsy-xapp"
import cors from "cors"
import depthLimit from "graphql-depth-limit"
import morgan from "artsy-morgan"
import express from "express"
import forceSSL from "express-force-ssl"
import graphqlHTTP from "express-graphql"
import bodyParser from "body-parser"
import schema from "./schema"
import legacyLoaders from "./lib/loaders/legacy"
import createLoaders from "./lib/loaders"
import config from "./config"
import { info, error } from "./lib/loggers"
import graphqlErrorHandler from "./lib/graphql-error-handler"
import moment from "moment"
import "moment-timezone"
import Tracer from "datadog-tracer"
import { forIn, has, assign } from "lodash"
import uuid from "uuid/v1"
import { fetchLoggerSetup, fetchLoggerRequestDone } from "lib/loaders/api/logger"
import { timestamp } from "./lib/helpers"
import { getNamedType, GraphQLObjectType } from "graphql"
import * as introspectionQuery from "graphql/type/introspection"

global.Promise = Bluebird

const { PORT, NODE_ENV, GRAVITY_API_URL, GRAVITY_ID, GRAVITY_SECRET, QUERY_DEPTH_LIMIT } = process.env

const app = express()
const port = PORT || 3000
const queryLimit = parseInt(QUERY_DEPTH_LIMIT, 10) || 10 // Default to ten.
const isProduction = NODE_ENV === "production"

if (isProduction) {
  app.set("forceSSLOptions", { trustXFPHeader: true }).use(forceSSL)
  app.set("trust proxy", 1)
}

xapp.on("error", err => {
  error(err)
  process.exit()
})

xapp.init(
  {
    url: GRAVITY_API_URL,
    id: GRAVITY_ID,
    secret: GRAVITY_SECRET,
  },
  () => (config.GRAVITY_XAPP_TOKEN = xapp.token)
)

app.get("/favicon.ico", (_req, res) => {
  res
    .status(200)
    .set({ "Content-Type": "image/x-icon" })
    .end()
})

app.all("/graphql", (_req, res) => res.redirect("/"))

app.use(bodyParser.json())

function parse_args() {
  return "( ... )"
}

function drop_params(query) {
  return query.replace(/(\()([^\)]*)(\))/g, parse_args)
}

function pushFinishedSpan(finishedSpans, span) {
  const endTime = timestamp()
  finishedSpans.push({ span, endTime })
}

function processFinishedSpans(finishedSpans) {
  let i = 0
  const iter = () => {
    const entry = finishedSpans[i]
    if (entry) {
      const { span, endTime } = entry
      span.finish(endTime)
      i++
      setImmediate(iter)
    }
  }
  setImmediate(iter)
}

function trace(res, span, finishedSpans) {
  span.addTags({
    "http.status_code": res.statusCode,
  })
  pushFinishedSpan(finishedSpans, span)
  processFinishedSpans(finishedSpans)
}

app.use((req, res, next) => {
  const tracer = new Tracer({ service: "metaphysics" })
  const span = tracer.startSpan("metaphysics.query")
  span.addTags({
    type: "web",
    "span.kind": "server",
    "http.method": req.method,
    "http.url": req.url,
  })

  if (req.body && req.body.query) {
    const query = drop_params(req.body.query)
    span.addTags({ resource: query })
  } else {
    span.addTags({ resource: req.path })
  }

  assign(req, { span })

  const finishedSpans = []
  assign(req, { finishedSpans })

  const finish = trace.bind(null, res, span, finishedSpans)
  res.on("finish", finish)
  res.on("close", finish)

  next()
})

function wrapResolve(typeName, fieldName, resolver) {
  return function (root, opts, req, { rootValue }) {
    const parentSpan = rootValue.span
    const span = parentSpan
      .tracer()
      .startSpan("metaphysics.resolver." + typeName + "." + fieldName, { childOf: parentSpan.context() })
    span.addTags({
      resource: typeName + ": " + fieldName,
      type: "web",
      "span.kind": "server",
    })

    // Set the parent context to this span for any sub resolvers.
    rootValue.span = span // eslint-disable-line no-param-reassign

    const result = resolver.apply(this, arguments)

    // Return parent context to our parent for any resolvers called after this one.
    rootValue.span = parentSpan // eslint-disable-line no-param-reassign

    if (result instanceof Promise) {
      return result.finally(function () {
        pushFinishedSpan(rootValue.finishedSpans, span)
      })
    }

    pushFinishedSpan(rootValue.finishedSpans, span)
    return result
  }
}

// Walk the schema and for all object type fields with resolvers wrap them in our tracing resolver.
forIn(schema._typeMap, function (type, typeName) {
  if (!introspectionQuery[type] && has(type, "_fields")) {
    forIn(type._fields, function (field, fieldName) {
      if (field.resolve instanceof Function && getNamedType(field.type) instanceof GraphQLObjectType) {
        field.resolve = wrapResolve(typeName, fieldName, field.resolve) // eslint-disable-line no-param-reassign
      }
    })
  }
})

app.use(
  "/",
  cors(),
  morgan,
  graphqlHTTP(request => {
    info("----------")

    legacyLoaders.clearAll()

    const accessToken = request.headers["x-access-token"]
    const userID = request.headers["x-user-id"]
    const timezone = request.headers["x-timezone"]
    const requestID = request.headers["x-request-id"] || uuid()

    const span = request.span
    const traceContext = span.context()
    const traceId = traceContext.traceId
    const parentSpanId = traceContext.spanId
    const requestIDs = { requestID, traceId, parentSpanId }

    if (!isProduction) {
      fetchLoggerSetup(requestID)
    }

    // Accepts a tz database timezone string. See http://www.iana.org/time-zones,
    // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
    let defaultTimezone
    if (moment.tz.zone(timezone)) {
      defaultTimezone = timezone
    }

    return {
      schema,
      graphiql: true,
      rootValue: {
        accessToken,
        userID,
        defaultTimezone,
        span,
        finishedSpans: request.finishedSpans,
        ...createLoaders(accessToken, userID, requestIDs),
      },
      formatError: graphqlErrorHandler(request.body),
      validationRules: [depthLimit(queryLimit)],
      extensions: isProduction ? undefined : fetchLoggerRequestDone(requestID),
    }
  })
)

app.listen(port, () => info(`Listening on ${port}`))
<|endoftext|>


<commit_before>/* eslint-disable object-shorthand */

// NOTE: Copied from spectacle

const defaultColors = {
  primary: "#f9c300",
  secondary: "black",
  tertiary: "white",
  quartenary: "white"
};

const defaultFonts = {
  primary: "Open Sans",
  secondary: "Lobster Two",
  tertiary: "monospace"
};

const screen = (colorArgs = defaultColors, fontArgs = defaultFonts) => {
  const colors = Object.assign({}, defaultColors, colorArgs);
  const fonts = Object.assign({}, defaultFonts, fontArgs);
  return {
    colors: colors,
    fonts: fonts,
    global: {
      body: {
        background: colors.primary,
        fontFamily: fonts.primary,
        fontWeight: "normal",
        fontSize: "2em",
        color: colors.secondary,
        overflow: "hidden"
      },
      "html, body": {
        height: "100%"
      },
      "*": {
        boxSizing: "border-box"
      }
    },
    fullscreen: {
      fill: colors.tertiary
    },
    controls: {
      prev: {
        position: "absolute",
        top: "50%",
        left: 20,
        transform: "translateY(-50%)",
        zIndex: 9999,
        background: "none",
        border: "none",
        outline: 0
      },
      prevIcon: {
        fill: colors.quartenary
      },
      next: {
        position: "absolute",
        top: "50%",
        right: 20,
        transform: "translateY(-50%)",
        zIndex: 9999,
        background: "none",
        border: "none",
        outline: 0
      },
      nextIcon: {
        fill: colors.quartenary
      }
    },
    progress: {
      pacman: {
        container: {
          position: "absolute",
          bottom: "5px",
          left: "50%",
          transition: "all 1s ease-in-out 0.2s",
          zIndex: 1000
        },
        pacman: {
          position: "absolute",
          transition: "left 0.3s ease-in-out 0.2s",
          width: "20px",
          height: "20px",
          transform: "translate(-5px, -5px)"
        },
        pacmanTop: {
          position: "absolute",
          content: " ",
          width: "20px",
          height: "10px",
          borderTopLeftRadius: "10px",
          borderTopRightRadius: "10px",
          background: colors.quartenary
        },
        pacmanBottom: {
          position: "absolute",
          content: " ",
          width: "20px",
          height: "10px",
          borderBottomLeftRadius: "10px",
          borderBottomRightRadius: "10px",
          background: colors.quartenary,
          top: "10px"
        },
        point: {
          position: "absolute",
          float: "left",
          background: "transparent",
          width: "10px",
          height: "10px",
          borderWidth: 2,
          borderStyle: "solid",
          borderColor: colors.quartenary,
          borderRadius: "50%",
          transition: "all 0.01s ease-out 0.4s"
        }
      },
      bar: {
        container: {
          position: "absolute",
          height: "10px",
          width: "100%",
          bottom: 0,
          left: 0,
          transition: "all 1s ease-in-out 0.2s",
          zIndex: 1000
        },
        bar: {
          height: "100%",
          background: colors.quartenary,
          transition: "all 0.3s ease-out"
        }
      },
      number: {
        container: {
          position: "absolute",
          bottom: 10,
          right: 10,
          zIndex: 1000,
          color: colors.quartenary
        }
      }
    },
    components: {
      blockquote: {
        textAlign: "left",
        position: "relative",
        display: "inline-block",
        margin: 0
      },
      quote: {
        borderLeft: `1px solid ${colors.primary}`,
        paddingLeft: 40,
        display: "block",
        color: colors.primary,
        fontSize: "4.9rem",
        lineHeight: 1,
        fontWeight: "bold"
      },
      cite: {
        color: colors.tertiary,
        display: "block",
        clear: "left",
        fontSize: "2rem",
        marginTop: 0
      },
      content: {
        margin: "0 auto",
        textAlign: "center"
      },
      codePane: {
        pre: {
          margin: "auto",
          fontSize: "0.8rem",
          fontWeight: "normal",
          fontFamily: fonts.tertiary,
          minWidth: "100%",
          maxWidth: 800
        },
        code: {
          textAlign: "left",
          fontWeight: "normal"
        }
      },
      code: {
        color: "black",
        fontSize: "2.66rem",
        fontFamily: fonts.tertiary,
        margin: 0,
        backgroundColor: "rgba(0,0,0,0.15)",
        padding: "0 10px",
        borderRadius: 3
      },
      heading: {
        h1: {
          color: colors.tertiary,
          fontSize: "7.05rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0,
          zoom: 1
        },
        h2: {
          color: colors.secondary,
          fontSize: "5.88rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h3: {
          color: "black",
          fontSize: "4.9rem",
          fontFamily: fonts.secondary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h4: {
          color: "black",
          fontSize: "3.82rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h5: {
          color: "black",
          fontSize: "3.19rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h6: {
          color: "black",
          fontSize: "2.66rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        }
      },
      image: {
        display: "block",
        margin: 0
      },
      link: {
        textDecoration: "none"
      },
      listItem: {
        fontSize: "2.66rem"
      },
      list: {
        textAlign: "left",
        listStylePosition: "inside",
        padding: 0
      },
      s: {
        strikethrough: {}
      },
      tableHeaderItem: {
        fontSize: "2.66rem",
        fontWeight: "bold"
      },
      tableItem: {
        fontSize: "2.66rem"
      },
      table: {
        width: "100%"
      },
      text: {
        color: "black",
        fontSize: "2.66rem",
        fontFamily: fonts.primary,
        margin: 0
      }
    }
  };
};

export default screen;
<commit_msg>Revert "change name of font in themes"<commit_after>/* eslint-disable object-shorthand */

// NOTE: Copied from spectacle

const defaultColors = {
  primary: "#f9c300",
  secondary: "black",
  tertiary: "white",
  quartenary: "white"
};

const defaultFonts = {
  primary: "Open Sans Condensed",
  secondary: "Lobster Two",
  tertiary: "monospace"
};

const screen = (colorArgs = defaultColors, fontArgs = defaultFonts) => {
  const colors = Object.assign({}, defaultColors, colorArgs);
  const fonts = Object.assign({}, defaultFonts, fontArgs);
  return {
    colors: colors,
    fonts: fonts,
    global: {
      body: {
        background: colors.primary,
        fontFamily: fonts.primary,
        fontWeight: "normal",
        fontSize: "2em",
        color: colors.secondary,
        overflow: "hidden"
      },
      "html, body": {
        height: "100%"
      },
      "*": {
        boxSizing: "border-box"
      }
    },
    fullscreen: {
      fill: colors.tertiary
    },
    controls: {
      prev: {
        position: "absolute",
        top: "50%",
        left: 20,
        transform: "translateY(-50%)",
        zIndex: 9999,
        background: "none",
        border: "none",
        outline: 0
      },
      prevIcon: {
        fill: colors.quartenary
      },
      next: {
        position: "absolute",
        top: "50%",
        right: 20,
        transform: "translateY(-50%)",
        zIndex: 9999,
        background: "none",
        border: "none",
        outline: 0
      },
      nextIcon: {
        fill: colors.quartenary
      }
    },
    progress: {
      pacman: {
        container: {
          position: "absolute",
          bottom: "5px",
          left: "50%",
          transition: "all 1s ease-in-out 0.2s",
          zIndex: 1000
        },
        pacman: {
          position: "absolute",
          transition: "left 0.3s ease-in-out 0.2s",
          width: "20px",
          height: "20px",
          transform: "translate(-5px, -5px)"
        },
        pacmanTop: {
          position: "absolute",
          content: " ",
          width: "20px",
          height: "10px",
          borderTopLeftRadius: "10px",
          borderTopRightRadius: "10px",
          background: colors.quartenary
        },
        pacmanBottom: {
          position: "absolute",
          content: " ",
          width: "20px",
          height: "10px",
          borderBottomLeftRadius: "10px",
          borderBottomRightRadius: "10px",
          background: colors.quartenary,
          top: "10px"
        },
        point: {
          position: "absolute",
          float: "left",
          background: "transparent",
          width: "10px",
          height: "10px",
          borderWidth: 2,
          borderStyle: "solid",
          borderColor: colors.quartenary,
          borderRadius: "50%",
          transition: "all 0.01s ease-out 0.4s"
        }
      },
      bar: {
        container: {
          position: "absolute",
          height: "10px",
          width: "100%",
          bottom: 0,
          left: 0,
          transition: "all 1s ease-in-out 0.2s",
          zIndex: 1000
        },
        bar: {
          height: "100%",
          background: colors.quartenary,
          transition: "all 0.3s ease-out"
        }
      },
      number: {
        container: {
          position: "absolute",
          bottom: 10,
          right: 10,
          zIndex: 1000,
          color: colors.quartenary
        }
      }
    },
    components: {
      blockquote: {
        textAlign: "left",
        position: "relative",
        display: "inline-block",
        margin: 0
      },
      quote: {
        borderLeft: `1px solid ${colors.primary}`,
        paddingLeft: 40,
        display: "block",
        color: colors.primary,
        fontSize: "4.9rem",
        lineHeight: 1,
        fontWeight: "bold"
      },
      cite: {
        color: colors.tertiary,
        display: "block",
        clear: "left",
        fontSize: "2rem",
        marginTop: 0
      },
      content: {
        margin: "0 auto",
        textAlign: "center"
      },
      codePane: {
        pre: {
          margin: "auto",
          fontSize: "0.8rem",
          fontWeight: "normal",
          fontFamily: fonts.tertiary,
          minWidth: "100%",
          maxWidth: 800
        },
        code: {
          textAlign: "left",
          fontWeight: "normal"
        }
      },
      code: {
        color: "black",
        fontSize: "2.66rem",
        fontFamily: fonts.tertiary,
        margin: 0,
        backgroundColor: "rgba(0,0,0,0.15)",
        padding: "0 10px",
        borderRadius: 3
      },
      heading: {
        h1: {
          color: colors.tertiary,
          fontSize: "7.05rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0,
          zoom: 1
        },
        h2: {
          color: colors.secondary,
          fontSize: "5.88rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h3: {
          color: "black",
          fontSize: "4.9rem",
          fontFamily: fonts.secondary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h4: {
          color: "black",
          fontSize: "3.82rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h5: {
          color: "black",
          fontSize: "3.19rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        },
        h6: {
          color: "black",
          fontSize: "2.66rem",
          fontFamily: fonts.primary,
          lineHeight: 1,
          fontWeight: "bold",
          margin: 0
        }
      },
      image: {
        display: "block",
        margin: 0
      },
      link: {
        textDecoration: "none"
      },
      listItem: {
        fontSize: "2.66rem"
      },
      list: {
        textAlign: "left",
        listStylePosition: "inside",
        padding: 0
      },
      s: {
        strikethrough: {}
      },
      tableHeaderItem: {
        fontSize: "2.66rem",
        fontWeight: "bold"
      },
      tableItem: {
        fontSize: "2.66rem"
      },
      table: {
        width: "100%"
      },
      text: {
        color: "black",
        fontSize: "2.66rem",
        fontFamily: fonts.primary,
        margin: 0
      }
    }
  };
};

export default screen;
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.util.linefeed = '\n';

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: grunt.file.readYAML('../config/config.yml'),

        watch: {
            options: {
                spawn: false,
                livereload: true
            },
            sass: {
                files: [
                    'sass/*.scss',
                    'sass/**/*.scss'
                ],
                tasks: [
                    'sass'
                ]
            },
            js: {
                files: [
                    'lib/bolt/*.js'
                ],
                tasks: [
                    'uglify:bolt'
                ]
            }
        },

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed',
                    includePaths: [
                        'node_modules/bootstrap-sass/assets/stylesheets/',
                        'node_modules/font-awesome/scss/'
                    ],
                    lineNumbers: false,
                    unixNewlines: true,
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED CSS files!\n" +
                            " * Do not edit these files, because all changes will be lost.\n" +
                            " * You can edit ../scss/app.scss & ../scss/app-old-ie.scss, and run 'grunt' to generate this file.\n" +
                            " */\n",
                    precision: 5
                },
                files: {
                    'css/bolt-old-ie.css': 'sass/app-old-ie.scss',
                    'css/bolt.css': 'sass/app.scss'
                }
            }

        },

        copy: {
            main: {
                // Includes files within path
                files: [{
                    expand: true,
                    flatten: true,
                    src: [
                        'node_modules/font-awesome/fonts/*'
                    ],
                    filter: 'isFile',
                    dest: 'fonts/'
                }]
            }
        },

        concat: {
            lib: {
                options: {
                    separator: '\n\n'
                },
                nonull: true,
                src: [
                    'lib/jquery-1.11.2/jquery.min.js',                              //  96 kb
                    'lib/jquery-ui-1.10.3/jquery-ui.custom.min.js',                 //  96 kb
                    'lib/bootstrap-file-input/bootstrap-file-input.min.js',         //   1 kb
                    'lib/jquery-tagcloud/jquery-tagcloud.min.js',                   //   1 kb
                    'lib/jquery-hotkeys/jquery-hotkeys.min.js',                     //   2 kb
                    'lib/jquery-watchchanges/jquery-watchchanges.min.js',           //   1 kb
                    'lib/jquery-cookie-1.4.0/jquery-cookie.min.js',                 //   1 kb
                    'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.min.js', //   3 kb
                    'lib/jquery-fileupload-5.26/jquery-iframe-transport.min.js',    //   2 kb
                    'lib/jquery-fileupload-5.26/jquery-fileupload.min.js',          //  15 kb
                    'lib/underscore-1.7.0/underscore-min.js',                       //  16 kb
                    'lib/backbone/backbone-min.js',                                 //  20 kb
                    'lib/bootstrap-sass.generated/bootstrap.min.js',                //   2 kb
                    'lib/magnific-popup-1.0.0/magnific-popup.min.js',               //  21 kb
                    'lib/select2-3.5.1/select2.min.js',                             //  66 kb
                    'node_modules/moment/min/moment.min.js',                        //  35 kb
                    'lib/bootbox-4.3.0/bootbox.min.js',                             //   9 kb
                    'lib/modernizr-2.8.3/modernizr.custom.min.js'                   //   5 kb
                ],
                dest: 'js/lib.min.js'
            }
        },

        cssmin: {
            lib: {
                options: {
                    compatibility: 'ie8',
                    relativeTo: './css/',
                    target: './css/'
                },
                files: {
                    'css/lib.css': [
                        'lib/jquery-ui-1.10.3/jquery-ui.custom.min.css',      // 20 kb
                        'lib/magnific-popup-1.0.0/magnific-popup.css',        //  9 kb
                        'lib/select2-3.5.1/select2.css',                      // 19 kb
                        'lib/jquery-fileupload-5.26/jquery-fileupload-ui.css' //  2 kb
                    ]
                }
            }
        },

        uglify: {
            lib: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    src: [
                        'lib/bootstrap-file-input/bootstrap-file-input.js',
                        'lib/jquery-cookie-1.4.0/jquery-cookie.js',
                        'lib/jquery-fileupload-5.26/jquery-fileupload.js',
                        'lib/jquery-fileupload-5.26/jquery-iframe-transport.js',
                        'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.js',
                        'lib/jquery-hotkeys/jquery-hotkeys.js',
                        'lib/jquery-tagcloud/jquery-tagcloud.js',
                        'lib/jquery-watchchanges/jquery-watchchanges.js'
                    ]
                }]
            },
            locale_datepicker: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'lib/datepicker',
                    src: '*.js',
                    dest: 'js/locale/datepicker',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace('datepicker-', '').replace('-', '_');
                    }
                }]
            },
            locale_moment: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'node_modules/moment/locale',
                    src: '*.js',
                    dest: 'js/locale/moment',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace(/([a-z]+)-([a-z]+)/, function (_, a, b) {
                            return a + '_' + b.toUpperCase();
                        });
                    }
                }]
            },
            bootstrap: {
                files: {
                    'lib/bootstrap-sass.generated/bootstrap.min.js': [
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/alert.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/button.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tab.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/transition.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/modal.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/popover.js'
                    ]
                }
            },
            bolt: {
                options: {
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED JS files!\n" +
                            " * You can edit files in <js/src/*.js> and run 'grunt' to generate this file.\n" +
                            " */",
                    sourceMap: true
                },
                files: {
                    'js/bolt.min.js': [
                        'lib/bolt/console.js',
                        'lib/bolt/fnc-helpers.js',
                        'lib/bolt/activity.js',
                        'lib/bolt/bind-fileupload.js',
                        'lib/bolt/make-uri-slug.js',
                        'lib/bolt/video-embed.js',
                        'lib/bolt/geolocation.js',
                        'lib/bolt/upload-files.js',
                        'lib/bolt/obj-sidebar.js',
                        'lib/bolt/obj-navpopups.js',
                        'lib/bolt/obj-moments.js',
                        'lib/bolt/obj-files.js',
                        'lib/bolt/obj-stack.js',
                        'lib/bolt/obj-folders.js',
                        'lib/bolt/obj-datetime.js',
                        'lib/bolt/extend.js',
                        'lib/bolt/init.js',
                        'lib/bolt/start.js'
                    ]
                }
            }
        },

        jshint: {
            options: {
                browser: true,          // Defines globals exposed by modern browsers
                curly: true,            // Always put curly braces around blocks
                devel: true,            // Defines globals that are usually used for logging/debugging
                immed: true,            // Prohibits the use of immediate function invocations without parentheses
                indent: 4,              // Tab width
                latedef: true,          // Prohibits the use of a variable before it was defined
                maxlen: 120,            // Maximum length of a line
                noarg: true,            // Prohibits the use of arguments.caller and arguments.callee
                nonbsp: true,           // Warns about "non-breaking whitespace" characters
                singleGroups: true,     // Prohibits the use of the grouping operator for single-expression statements
                undef: true,            // Prohibits the use of undeclared variables
                globals: {
                    // Bolt
                    bolt: true,                 // src/console.js
                    FilelistHolder: true,       // src/upload-files.js
                    Files: true,                // src/obj-files.js
                    Folders: true,              // src/obj-folders.js
                    init: true,                 // src/init.js
                    Moments: true,              // src/obj-moments.js
                    Navpopups: true,            // src/obj-navpopups.js
                    Sidebar: true,              // src/obj-sidebar.js
                    Stack: true,                // src/obj-stack.js
                    site: true,                 // src/extend.js/extend.twig
                    baseurl: true,              // src/extend.js/extend.twig
                    rootpath: true,             // src/extend.js/extend.twig
                    // Bolt global functions
                    bindFileUpload: true,       // src/bindfileuploads.js
                    bindGeolocation: true,      // src/geolocation.js
                    bindVideoEmbed: true,       // src/video-embed.js
                    getSelectedItems: true,     // src/fnc-helpers.js
                    makeUri: true,              // src/make-uri-slug.js
                    makeUriAjax: true,          // src/make-uri-slug.js
                    stopMakeUri: true,          // src/make-uri-slug.js
                    updateLatestActivity: true, // src/activity.js
                    validateContent: true,      // src/fnc-helpers.js
                    // Vendor
                    $: true,                    // jQuery
                    _: true,                    // underscore.js
                    Backbone: true,             // backbone.min.js
                    bootbox: true,              // bootbox.min.js
                    CKEDITOR: true,             // ckeditor.js
                    CodeMirror: true,           // ckeditor.js
                    google: true,               // Google
                    jQuery: true,               // jQuery
                    moment: true,               // moment.min.js
                    UAParser: true              // ua-parser.min.js
                }
            },
            src: ['lib/bolt/*.js']
        }

    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask('default', ['sass', 'jshint', 'uglify', 'cssmin', 'concat', 'watch']);

};
<commit_msg>Rename js watch task to bolt_js<commit_after>module.exports = function(grunt) {
    grunt.util.linefeed = '\n';

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: grunt.file.readYAML('../config/config.yml'),

        watch: {
            options: {
                spawn: false,
                livereload: true
            },
            sass: {
                files: [
                    'sass/*.scss',
                    'sass/**/*.scss'
                ],
                tasks: [
                    'sass'
                ]
            },
            bolt_js: {
                files: [
                    'lib/bolt/*.js'
                ],
                tasks: [
                    'uglify:bolt'
                ]
            }
        },

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed',
                    includePaths: [
                        'node_modules/bootstrap-sass/assets/stylesheets/',
                        'node_modules/font-awesome/scss/'
                    ],
                    lineNumbers: false,
                    unixNewlines: true,
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED CSS files!\n" +
                            " * Do not edit these files, because all changes will be lost.\n" +
                            " * You can edit ../scss/app.scss & ../scss/app-old-ie.scss, and run 'grunt' to generate this file.\n" +
                            " */\n",
                    precision: 5
                },
                files: {
                    'css/bolt-old-ie.css': 'sass/app-old-ie.scss',
                    'css/bolt.css': 'sass/app.scss'
                }
            }

        },

        copy: {
            main: {
                // Includes files within path
                files: [{
                    expand: true,
                    flatten: true,
                    src: [
                        'node_modules/font-awesome/fonts/*'
                    ],
                    filter: 'isFile',
                    dest: 'fonts/'
                }]
            }
        },

        concat: {
            lib: {
                options: {
                    separator: '\n\n'
                },
                nonull: true,
                src: [
                    'lib/jquery-1.11.2/jquery.min.js',                              //  96 kb
                    'lib/jquery-ui-1.10.3/jquery-ui.custom.min.js',                 //  96 kb
                    'lib/bootstrap-file-input/bootstrap-file-input.min.js',         //   1 kb
                    'lib/jquery-tagcloud/jquery-tagcloud.min.js',                   //   1 kb
                    'lib/jquery-hotkeys/jquery-hotkeys.min.js',                     //   2 kb
                    'lib/jquery-watchchanges/jquery-watchchanges.min.js',           //   1 kb
                    'lib/jquery-cookie-1.4.0/jquery-cookie.min.js',                 //   1 kb
                    'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.min.js', //   3 kb
                    'lib/jquery-fileupload-5.26/jquery-iframe-transport.min.js',    //   2 kb
                    'lib/jquery-fileupload-5.26/jquery-fileupload.min.js',          //  15 kb
                    'lib/underscore-1.7.0/underscore-min.js',                       //  16 kb
                    'lib/backbone/backbone-min.js',                                 //  20 kb
                    'lib/bootstrap-sass.generated/bootstrap.min.js',                //   2 kb
                    'lib/magnific-popup-1.0.0/magnific-popup.min.js',               //  21 kb
                    'lib/select2-3.5.1/select2.min.js',                             //  66 kb
                    'node_modules/moment/min/moment.min.js',                        //  35 kb
                    'lib/bootbox-4.3.0/bootbox.min.js',                             //   9 kb
                    'lib/modernizr-2.8.3/modernizr.custom.min.js'                   //   5 kb
                ],
                dest: 'js/lib.min.js'
            }
        },

        cssmin: {
            lib: {
                options: {
                    compatibility: 'ie8',
                    relativeTo: './css/',
                    target: './css/'
                },
                files: {
                    'css/lib.css': [
                        'lib/jquery-ui-1.10.3/jquery-ui.custom.min.css',      // 20 kb
                        'lib/magnific-popup-1.0.0/magnific-popup.css',        //  9 kb
                        'lib/select2-3.5.1/select2.css',                      // 19 kb
                        'lib/jquery-fileupload-5.26/jquery-fileupload-ui.css' //  2 kb
                    ]
                }
            }
        },

        uglify: {
            lib: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    src: [
                        'lib/bootstrap-file-input/bootstrap-file-input.js',
                        'lib/jquery-cookie-1.4.0/jquery-cookie.js',
                        'lib/jquery-fileupload-5.26/jquery-fileupload.js',
                        'lib/jquery-fileupload-5.26/jquery-iframe-transport.js',
                        'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.js',
                        'lib/jquery-hotkeys/jquery-hotkeys.js',
                        'lib/jquery-tagcloud/jquery-tagcloud.js',
                        'lib/jquery-watchchanges/jquery-watchchanges.js'
                    ]
                }]
            },
            locale_datepicker: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'lib/datepicker',
                    src: '*.js',
                    dest: 'js/locale/datepicker',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace('datepicker-', '').replace('-', '_');
                    }
                }]
            },
            locale_moment: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'node_modules/moment/locale',
                    src: '*.js',
                    dest: 'js/locale/moment',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace(/([a-z]+)-([a-z]+)/, function (_, a, b) {
                            return a + '_' + b.toUpperCase();
                        });
                    }
                }]
            },
            bootstrap: {
                files: {
                    'lib/bootstrap-sass.generated/bootstrap.min.js': [
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/alert.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/button.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tab.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/transition.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/modal.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/popover.js'
                    ]
                }
            },
            bolt: {
                options: {
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED JS files!\n" +
                            " * You can edit files in <js/src/*.js> and run 'grunt' to generate this file.\n" +
                            " */",
                    sourceMap: true
                },
                files: {
                    'js/bolt.min.js': [
                        'lib/bolt/console.js',
                        'lib/bolt/fnc-helpers.js',
                        'lib/bolt/activity.js',
                        'lib/bolt/bind-fileupload.js',
                        'lib/bolt/make-uri-slug.js',
                        'lib/bolt/video-embed.js',
                        'lib/bolt/geolocation.js',
                        'lib/bolt/upload-files.js',
                        'lib/bolt/obj-sidebar.js',
                        'lib/bolt/obj-navpopups.js',
                        'lib/bolt/obj-moments.js',
                        'lib/bolt/obj-files.js',
                        'lib/bolt/obj-stack.js',
                        'lib/bolt/obj-folders.js',
                        'lib/bolt/obj-datetime.js',
                        'lib/bolt/extend.js',
                        'lib/bolt/init.js',
                        'lib/bolt/start.js'
                    ]
                }
            }
        },

        jshint: {
            options: {
                browser: true,          // Defines globals exposed by modern browsers
                curly: true,            // Always put curly braces around blocks
                devel: true,            // Defines globals that are usually used for logging/debugging
                immed: true,            // Prohibits the use of immediate function invocations without parentheses
                indent: 4,              // Tab width
                latedef: true,          // Prohibits the use of a variable before it was defined
                maxlen: 120,            // Maximum length of a line
                noarg: true,            // Prohibits the use of arguments.caller and arguments.callee
                nonbsp: true,           // Warns about "non-breaking whitespace" characters
                singleGroups: true,     // Prohibits the use of the grouping operator for single-expression statements
                undef: true,            // Prohibits the use of undeclared variables
                globals: {
                    // Bolt
                    bolt: true,                 // src/console.js
                    FilelistHolder: true,       // src/upload-files.js
                    Files: true,                // src/obj-files.js
                    Folders: true,              // src/obj-folders.js
                    init: true,                 // src/init.js
                    Moments: true,              // src/obj-moments.js
                    Navpopups: true,            // src/obj-navpopups.js
                    Sidebar: true,              // src/obj-sidebar.js
                    Stack: true,                // src/obj-stack.js
                    site: true,                 // src/extend.js/extend.twig
                    baseurl: true,              // src/extend.js/extend.twig
                    rootpath: true,             // src/extend.js/extend.twig
                    // Bolt global functions
                    bindFileUpload: true,       // src/bindfileuploads.js
                    bindGeolocation: true,      // src/geolocation.js
                    bindVideoEmbed: true,       // src/video-embed.js
                    getSelectedItems: true,     // src/fnc-helpers.js
                    makeUri: true,              // src/make-uri-slug.js
                    makeUriAjax: true,          // src/make-uri-slug.js
                    stopMakeUri: true,          // src/make-uri-slug.js
                    updateLatestActivity: true, // src/activity.js
                    validateContent: true,      // src/fnc-helpers.js
                    // Vendor
                    $: true,                    // jQuery
                    _: true,                    // underscore.js
                    Backbone: true,             // backbone.min.js
                    bootbox: true,              // bootbox.min.js
                    CKEDITOR: true,             // ckeditor.js
                    CodeMirror: true,           // ckeditor.js
                    google: true,               // Google
                    jQuery: true,               // jQuery
                    moment: true,               // moment.min.js
                    UAParser: true              // ua-parser.min.js
                }
            },
            src: ['lib/bolt/*.js']
        }

    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask('default', ['sass', 'jshint', 'uglify', 'cssmin', 'concat', 'watch']);

};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.util.linefeed = '\n';

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: grunt.file.readYAML('../config/config.yml'),

        watch: {
            options: {
                spawn: false,
                livereload: true
            },
            sass: {
                files: [
                    'sass/*.scss',
                    'sass/**/*.scss'
                ],
                tasks: [
                    'sass'
                ]
            },
            bolt_js: {
                files: [
                    'lib/bolt/*.js'
                ],
                tasks: [
                    'uglify:bolt'
                ]
            }
        },

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed',
                    includePaths: [
                        'node_modules/bootstrap-sass/assets/stylesheets/',
                        'node_modules/font-awesome/scss/'
                    ],
                    lineNumbers: false,
                    unixNewlines: true,
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED CSS files!\n" +
                            " * Do not edit these files, because all changes will be lost.\n" +
                            " * You can edit ../scss/app.scss & ../scss/app-old-ie.scss, and run 'grunt' to generate this file.\n" +
                            " */\n",
                    precision: 5
                },
                files: {
                    'css/bolt-old-ie.css': 'sass/app-old-ie.scss',
                    'css/bolt.css': 'sass/app.scss'
                }
            }
        },

        copy: {
            main: {
                // Includes files within path
                files: [{
                    expand: true,
                    flatten: true,
                    src: [
                        'node_modules/font-awesome/fonts/*'
                    ],
                    filter: 'isFile',
                    dest: 'fonts/'
                }]
            }
        },

        concat: {
            lib: {
                options: {
                    separator: '\n\n'
                },
                nonull: true,
                src: [
                    'lib/jquery-1.11.2/jquery.min.js',                              //  96 kb
                    'lib/jquery-ui-1.10.3/jquery-ui.custom.min.js',                 //  96 kb
                    'lib/bootstrap-file-input/bootstrap-file-input.min.js',         //   1 kb
                    'lib/jquery-tagcloud/jquery-tagcloud.min.js',                   //   1 kb
                    'lib/jquery-hotkeys/jquery-hotkeys.min.js',                     //   2 kb
                    'lib/jquery-watchchanges/jquery-watchchanges.min.js',           //   1 kb
                    'lib/jquery-cookie-1.4.0/jquery-cookie.min.js',                 //   1 kb
                    'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.min.js', //   3 kb
                    'lib/jquery-fileupload-5.26/jquery-iframe-transport.min.js',    //   2 kb
                    'lib/jquery-fileupload-5.26/jquery-fileupload.min.js',          //  15 kb
                    'lib/underscore-1.7.0/underscore-min.js',                       //  16 kb
                    'lib/backbone/backbone-min.js',                                 //  20 kb
                    'lib/bootstrap-sass.generated/bootstrap.min.js',                //   2 kb
                    'lib/magnific-popup-1.0.0/magnific-popup.min.js',               //  21 kb
                    'lib/select2-3.5.1/select2.min.js',                             //  66 kb
                    'node_modules/moment/min/moment.min.js',                        //  35 kb
                    'lib/bootbox-4.3.0/bootbox.min.js',                             //   9 kb
                    'lib/modernizr-2.8.3/modernizr.custom.min.js'                   //   5 kb
                ],
                dest: 'js/lib.min.js'
            }
        },

        cssmin: {
            lib: {
                options: {
                    compatibility: 'ie8',
                    relativeTo: './css/',
                    target: './css/'
                },
                files: {
                    'css/lib.css': [
                        'lib/jquery-ui-1.10.3/jquery-ui.custom.min.css',      // 20 kb
                        'lib/magnific-popup-1.0.0/magnific-popup.css',        //  9 kb
                        'lib/select2-3.5.1/select2.css',                      // 19 kb
                        'lib/jquery-fileupload-5.26/jquery-fileupload-ui.css' //  2 kb
                    ]
                }
            }
        },

        uglify: {
            lib: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    src: [
                        'lib/bootstrap-file-input/bootstrap-file-input.js',
                        'lib/jquery-cookie-1.4.0/jquery-cookie.js',
                        'lib/jquery-fileupload-5.26/jquery-fileupload.js',
                        'lib/jquery-fileupload-5.26/jquery-iframe-transport.js',
                        'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.js',
                        'lib/jquery-hotkeys/jquery-hotkeys.js',
                        'lib/jquery-tagcloud/jquery-tagcloud.js',
                        'lib/jquery-watchchanges/jquery-watchchanges.js'
                    ]
                }]
            },
            locale_datepicker: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'lib/datepicker',
                    src: '*.js',
                    dest: 'js/locale/datepicker',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace('datepicker-', '').replace('-', '_');
                    }
                }]
            },
            locale_moment: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'node_modules/moment/locale',
                    src: '*.js',
                    dest: 'js/locale/moment',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace(/([a-z]+)-([a-z]+)/, function (_, a, b) {
                            return a + '_' + b.toUpperCase();
                        });
                    }
                }]
            },
            bootstrap: {
                files: {
                    'lib/bootstrap-sass.generated/bootstrap.min.js': [
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/alert.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/button.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tab.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/transition.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/modal.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/popover.js'
                    ]
                }
            },
            bolt: {
                options: {
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED JS files!\n" +
                            " * You can edit files in <js/src/*.js> and run 'grunt' to generate this file.\n" +
                            " */",
                    sourceMap: true
                },
                files: {
                    'js/bolt.min.js': [
                        'lib/bolt/console.js',
                        'lib/bolt/fnc-helpers.js',
                        'lib/bolt/activity.js',
                        'lib/bolt/bind-fileupload.js',
                        'lib/bolt/make-uri-slug.js',
                        'lib/bolt/video-embed.js',
                        'lib/bolt/geolocation.js',
                        'lib/bolt/upload-files.js',
                        'lib/bolt/obj-sidebar.js',
                        'lib/bolt/obj-navpopups.js',
                        'lib/bolt/obj-moments.js',
                        'lib/bolt/obj-files.js',
                        'lib/bolt/obj-stack.js',
                        'lib/bolt/obj-folders.js',
                        'lib/bolt/obj-datetime.js',
                        'lib/bolt/extend.js',
                        'lib/bolt/init.js',
                        'lib/bolt/start.js'
                    ]
                }
            }
        },

        jshint: {
            options: {
                browser: true,          // Defines globals exposed by modern browsers
                curly: true,            // Always put curly braces around blocks
                devel: true,            // Defines globals that are usually used for logging/debugging
                immed: true,            // Prohibits the use of immediate function invocations without parentheses
                indent: 4,              // Tab width
                latedef: true,          // Prohibits the use of a variable before it was defined
                maxlen: 120,            // Maximum length of a line
                noarg: true,            // Prohibits the use of arguments.caller and arguments.callee
                nonbsp: true,           // Warns about "non-breaking whitespace" characters
                singleGroups: true,     // Prohibits the use of the grouping operator for single-expression statements
                undef: true,            // Prohibits the use of undeclared variables
                globals: {
                    // Bolt
                    bolt: true,                 // src/console.js
                    FilelistHolder: true,       // src/upload-files.js
                    Files: true,                // src/obj-files.js
                    Folders: true,              // src/obj-folders.js
                    init: true,                 // src/init.js
                    Moments: true,              // src/obj-moments.js
                    Navpopups: true,            // src/obj-navpopups.js
                    Sidebar: true,              // src/obj-sidebar.js
                    Stack: true,                // src/obj-stack.js
                    site: true,                 // src/extend.js/extend.twig
                    baseurl: true,              // src/extend.js/extend.twig
                    rootpath: true,             // src/extend.js/extend.twig
                    // Bolt global functions
                    bindFileUpload: true,       // src/bindfileuploads.js
                    bindGeolocation: true,      // src/geolocation.js
                    bindVideoEmbed: true,       // src/video-embed.js
                    getSelectedItems: true,     // src/fnc-helpers.js
                    makeUri: true,              // src/make-uri-slug.js
                    makeUriAjax: true,          // src/make-uri-slug.js
                    stopMakeUri: true,          // src/make-uri-slug.js
                    updateLatestActivity: true, // src/activity.js
                    validateContent: true,      // src/fnc-helpers.js
                    // Vendor
                    $: true,                    // jQuery
                    _: true,                    // underscore.js
                    Backbone: true,             // backbone.min.js
                    bootbox: true,              // bootbox.min.js
                    CKEDITOR: true,             // ckeditor.js
                    CodeMirror: true,           // ckeditor.js
                    google: true,               // Google
                    jQuery: true,               // jQuery
                    moment: true,               // moment.min.js
                    UAParser: true              // ua-parser.min.js
                }
            },
            src: ['lib/bolt/*.js']
        }

    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask('default', ['sass', 'jshint', 'uglify', 'cssmin', 'concat', 'watch']);

};
<commit_msg>Name jshint task<commit_after>module.exports = function(grunt) {
    grunt.util.linefeed = '\n';

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        config: grunt.file.readYAML('../config/config.yml'),

        watch: {
            options: {
                spawn: false,
                livereload: true
            },
            sass: {
                files: [
                    'sass/*.scss',
                    'sass/**/*.scss'
                ],
                tasks: [
                    'sass'
                ]
            },
            bolt_js: {
                files: [
                    'lib/bolt/*.js'
                ],
                tasks: [
                    'uglify:bolt'
                ]
            }
        },

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed',
                    includePaths: [
                        'node_modules/bootstrap-sass/assets/stylesheets/',
                        'node_modules/font-awesome/scss/'
                    ],
                    lineNumbers: false,
                    unixNewlines: true,
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED CSS files!\n" +
                            " * Do not edit these files, because all changes will be lost.\n" +
                            " * You can edit ../scss/app.scss & ../scss/app-old-ie.scss, and run 'grunt' to generate this file.\n" +
                            " */\n",
                    precision: 5
                },
                files: {
                    'css/bolt-old-ie.css': 'sass/app-old-ie.scss',
                    'css/bolt.css': 'sass/app.scss'
                }
            }
        },

        copy: {
            main: {
                // Includes files within path
                files: [{
                    expand: true,
                    flatten: true,
                    src: [
                        'node_modules/font-awesome/fonts/*'
                    ],
                    filter: 'isFile',
                    dest: 'fonts/'
                }]
            }
        },

        concat: {
            lib: {
                options: {
                    separator: '\n\n'
                },
                nonull: true,
                src: [
                    'lib/jquery-1.11.2/jquery.min.js',                              //  96 kb
                    'lib/jquery-ui-1.10.3/jquery-ui.custom.min.js',                 //  96 kb
                    'lib/bootstrap-file-input/bootstrap-file-input.min.js',         //   1 kb
                    'lib/jquery-tagcloud/jquery-tagcloud.min.js',                   //   1 kb
                    'lib/jquery-hotkeys/jquery-hotkeys.min.js',                     //   2 kb
                    'lib/jquery-watchchanges/jquery-watchchanges.min.js',           //   1 kb
                    'lib/jquery-cookie-1.4.0/jquery-cookie.min.js',                 //   1 kb
                    'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.min.js', //   3 kb
                    'lib/jquery-fileupload-5.26/jquery-iframe-transport.min.js',    //   2 kb
                    'lib/jquery-fileupload-5.26/jquery-fileupload.min.js',          //  15 kb
                    'lib/underscore-1.7.0/underscore-min.js',                       //  16 kb
                    'lib/backbone/backbone-min.js',                                 //  20 kb
                    'lib/bootstrap-sass.generated/bootstrap.min.js',                //   2 kb
                    'lib/magnific-popup-1.0.0/magnific-popup.min.js',               //  21 kb
                    'lib/select2-3.5.1/select2.min.js',                             //  66 kb
                    'node_modules/moment/min/moment.min.js',                        //  35 kb
                    'lib/bootbox-4.3.0/bootbox.min.js',                             //   9 kb
                    'lib/modernizr-2.8.3/modernizr.custom.min.js'                   //   5 kb
                ],
                dest: 'js/lib.min.js'
            }
        },

        cssmin: {
            lib: {
                options: {
                    compatibility: 'ie8',
                    relativeTo: './css/',
                    target: './css/'
                },
                files: {
                    'css/lib.css': [
                        'lib/jquery-ui-1.10.3/jquery-ui.custom.min.css',      // 20 kb
                        'lib/magnific-popup-1.0.0/magnific-popup.css',        //  9 kb
                        'lib/select2-3.5.1/select2.css',                      // 19 kb
                        'lib/jquery-fileupload-5.26/jquery-fileupload-ui.css' //  2 kb
                    ]
                }
            }
        },

        uglify: {
            lib: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    src: [
                        'lib/bootstrap-file-input/bootstrap-file-input.js',
                        'lib/jquery-cookie-1.4.0/jquery-cookie.js',
                        'lib/jquery-fileupload-5.26/jquery-fileupload.js',
                        'lib/jquery-fileupload-5.26/jquery-iframe-transport.js',
                        'lib/jquery-formatdatetime-1.1.4/jquery-formatdatetime.js',
                        'lib/jquery-hotkeys/jquery-hotkeys.js',
                        'lib/jquery-tagcloud/jquery-tagcloud.js',
                        'lib/jquery-watchchanges/jquery-watchchanges.js'
                    ]
                }]
            },
            locale_datepicker: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'lib/datepicker',
                    src: '*.js',
                    dest: 'js/locale/datepicker',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace('datepicker-', '').replace('-', '_');
                    }
                }]
            },
            locale_moment: {
                options: {
                    preserveComments: 'some'
                },
                files: [{
                    expand: true,
                    ext: '.min.js',
                    cwd: 'node_modules/moment/locale',
                    src: '*.js',
                    dest: 'js/locale/moment',
                    rename: function (destBase, destPath) {
                        return destBase + '/' + destPath.replace(/([a-z]+)-([a-z]+)/, function (_, a, b) {
                            return a + '_' + b.toUpperCase();
                        });
                    }
                }]
            },
            bootstrap: {
                files: {
                    'lib/bootstrap-sass.generated/bootstrap.min.js': [
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/alert.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/button.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tab.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/transition.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/modal.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js',
                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap/popover.js'
                    ]
                }
            },
            bolt: {
                options: {
                    banner: "/**\n" +
                            " * These are Bolt's COMPILED JS files!\n" +
                            " * You can edit files in <js/src/*.js> and run 'grunt' to generate this file.\n" +
                            " */",
                    sourceMap: true
                },
                files: {
                    'js/bolt.min.js': [
                        'lib/bolt/console.js',
                        'lib/bolt/fnc-helpers.js',
                        'lib/bolt/activity.js',
                        'lib/bolt/bind-fileupload.js',
                        'lib/bolt/make-uri-slug.js',
                        'lib/bolt/video-embed.js',
                        'lib/bolt/geolocation.js',
                        'lib/bolt/upload-files.js',
                        'lib/bolt/obj-sidebar.js',
                        'lib/bolt/obj-navpopups.js',
                        'lib/bolt/obj-moments.js',
                        'lib/bolt/obj-files.js',
                        'lib/bolt/obj-stack.js',
                        'lib/bolt/obj-folders.js',
                        'lib/bolt/obj-datetime.js',
                        'lib/bolt/extend.js',
                        'lib/bolt/init.js',
                        'lib/bolt/start.js'
                    ]
                }
            }
        },

        jshint: {
            bolt_js: {
                options: {
                    browser: true,      // Defines globals exposed by modern browsers
                    curly: true,        // Always put curly braces around blocks
                    devel: true,        // Defines globals that are usually used for logging/debugging
                    immed: true,        // Prohibits the use of immediate function invocations without parentheses
                    indent: 4,          // Tab width
                    latedef: true,      // Prohibits the use of a variable before it was defined
                    maxlen: 120,        // Maximum length of a line
                    noarg: true,        // Prohibits the use of arguments.caller and arguments.callee
                    nonbsp: true,       // Warns about "non-breaking whitespace" characters
                    singleGroups: true, // Prohibits the use of the grouping operator for single-expression statements
                    undef: true,        // Prohibits the use of undeclared variables
                    globals: {
                        // Bolt
                        bolt: true,                 // src/console.js
                        FilelistHolder: true,       // src/upload-files.js
                        Files: true,                // src/obj-files.js
                        Folders: true,              // src/obj-folders.js
                        init: true,                 // src/init.js
                        Moments: true,              // src/obj-moments.js
                        Navpopups: true,            // src/obj-navpopups.js
                        Sidebar: true,              // src/obj-sidebar.js
                        Stack: true,                // src/obj-stack.js
                        site: true,                 // src/extend.js/extend.twig
                        baseurl: true,              // src/extend.js/extend.twig
                        rootpath: true,             // src/extend.js/extend.twig
                        // Bolt global functions
                        bindFileUpload: true,       // src/bindfileuploads.js
                        bindGeolocation: true,      // src/geolocation.js
                        bindVideoEmbed: true,       // src/video-embed.js
                        getSelectedItems: true,     // src/fnc-helpers.js
                        makeUri: true,              // src/make-uri-slug.js
                        makeUriAjax: true,          // src/make-uri-slug.js
                        stopMakeUri: true,          // src/make-uri-slug.js
                        updateLatestActivity: true, // src/activity.js
                        validateContent: true,      // src/fnc-helpers.js
                        // Vendor
                        $: true,                    // jQuery
                        _: true,                    // underscore.js
                        Backbone: true,             // backbone.min.js
                        bootbox: true,              // bootbox.min.js
                        CKEDITOR: true,             // ckeditor.js
                        CodeMirror: true,           // ckeditor.js
                        google: true,               // Google
                        jQuery: true,               // jQuery
                        moment: true,               // moment.min.js
                        UAParser: true              // ua-parser.min.js
                    }
                },
                src: ['lib/bolt/*.js']
            }
        }
    });

    require('load-grunt-tasks')(grunt);

    grunt.registerTask('default', ['sass', 'jshint:bolt_js', 'uglify', 'cssmin', 'concat', 'watch']);

};
<|endoftext|>


<commit_before>/*
 * portfinder.js: A simple tool to find an open port on the current machine.
 *
 * (C) 2011, Charlie Robbins
 *
 */

var fs = require('fs'),
    net = require('net'),
    path = require('path'),
    mkdirp = require('mkdirp').mkdirp;

//
// ### @basePort {Number}
// The lowest port to begin any port search from
//
exports.basePort = 8000;

//
// ### @basePath {string}
// Default path to begin any socket search from
//
exports.basePath = '/tmp/portfinder'

//
// ### function getPort (options, callback)
// #### @options {Object} Settings to use when finding the necessary port
// #### @callback {function} Continuation to respond to when complete.
// Responds with a unbound port on the current machine.
//
exports.getPort = function (options, callback) {
  if (!callback) {
    callback = options;
    options = {};
  }

  options.port   = options.port   || exports.basePort;
  options.host   = options.host   || null;
  options.server = options.server || net.createServer(function () {
    //
    // Create an empty listener for the port testing server.
    //
  });

  function onListen () {
    options.server.removeListener('error', onError);
    options.server.close();
    callback(null, options.port)
  }

  function onError (err) {
    options.server.removeListener('listening', onListen);

    if (err.code !== 'EADDRINUSE' && err.code !== 'EACCES') {
      return callback(err);
    }

    exports.getPort({
      port: exports.nextPort(options.port),
      host: options.host,
      server: options.server
    }, callback);
  }

  options.server.once('error', onError);
  options.server.once('listening', onListen);
  options.server.listen(options.port, options.host);
};

//
// ### function getSocket (options, callback)
// #### @options {Object} Settings to use when finding the necessary port
// #### @callback {function} Continuation to respond to when complete.
// Responds with a unbound socket using the specified directory and base
// name on the current machine.
//
exports.getSocket = function (options, callback) {
  if (!callback) {
    callback = options;
    options = {};
  }

  options.mod  = options.mod    || 0755;
  options.path = options.path   || exports.basePath + '.sock';

  //
  // Tests the specified socket
  //
  function testSocket () {
    fs.stat(options.path, function (err) {
      //
      // If file we're checking doesn't exist (thus, stating it emits ENOENT),
      // we should be OK with listening on this socket.
      //
      if (err) {
        if (err.code == 'ENOENT') {
          callback(null, options.path);
        }
        else {
          callback(err);
        }
      }
      else {
        //
        // This file exists, so it isn't possible to listen on it. Lets try
        // next socket.
        //
        options.path = exports.nextSocket(options.path);
        exports.getSocket(options, callback);
      }
    });
  }

  //
  // Create the target `dir` then test connection
  // against the socket.
  //
  function createAndTestSocket (dir) {
    mkdirp(dir, options.mod, function (err) {
      if (err) {
        return callback(err);
      }

      options.exists = true;
      testSocket();
    });
  }

  //
  // Check if the parent directory of the target
  // socket path exists. If it does, test connection
  // against the socket. Otherwise, create the directory
  // then test connection.
  //
  function checkAndTestSocket () {
    var dir = path.dirname(options.path);

    fs.stat(dir, function (err, stats) {
      if (err || !stats.isDirectory()) {
        return createAndTestSocket(dir);
      }

      options.exists = true;
      testSocket();
    });
  }

  //
  // If it has been explicitly stated that the
  // target `options.path` already exists, then
  // simply test the socket.
  //
  return options.exists
    ? testSocket()
    : checkAndTestSocket();
};

//
// ### function nextPort (port)
// #### @port {Number} Port to increment from.
// Gets the next port in sequence from the
// specified `port`.
//
exports.nextPort = function (port) {
  return port + 1;
};

//
// ### function nextSocket (socketPath)
// #### @socketPath {string} Path to increment from
// Gets the next socket path in sequence from the
// specified `socketPath`.
//
exports.nextSocket = function (socketPath) {
  var dir = path.dirname(socketPath),
      name = path.basename(socketPath, '.sock'),
      match = name.match(/^([a-zA-z]+)(\d*)$/i),
      index = parseInt(match[2]),
      base = match[1];

  if (isNaN(index)) {
    index = 0;
  }

  index += 1;
  return path.join(dir, base + index + '.sock');
};
<commit_msg>remove Socket* methods<commit_after>var net = require('net')

/**
 * The lowest port to begin any port search from
 * @type {number}
 */
exports.basePort = 8000

/**
 * Responds with a unbound port on the current machine.
 * @param  {Object}   options  Settings to use when finding the necessary port
 * @param  {function} cb       Function to call when complete.
 */
exports.getPort = function (options, cb) {
  if (!cb) {
    cb = options
    options = {}
  }

  if (!options.port) options.port = exports.basePort
  if (!options.server) options.server = net.createServer()

  function onListening () {
    console.log('onListening')
    options.server.removeListener('error', onError)
    options.server.close()
    cb(null, options.port)
  }

  function onError (err) {
    console.log('onError')
    options.server.removeListener('listening', onListening)

    if (err.message.indexOf('failed to listen') === -1) {
      return cb(err)
    }

    exports.getPort({
      port: exports.nextPort(options.port),
      host: options.host,
      server: options.server
    }, cb)
  }

  options.server.once('error', onError)
  options.server.once('listening', onListening)
  options.server.listen(options.port, options.host)
}

/**
 * Gets the next port in sequence from the specified `port`.
 * @param {number}  port Port to increment from.
 * @return {number}      Next port.
 */
exports.nextPort = function (port) {
  return port + 1
}
<|endoftext|>


<commit_before>'use strict';

// Vars
var _ = require('lodash');
var dust = require('dustjs-linkedin');
dust.helpers = require('dustjs-helpers').helpers;

var commonhelpers = new (require("common-dustjs-helpers").CommonDustjsHelpers)();
commonhelpers.export_to(dust);

var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
var fs = require('fs');
var path = require('path');
var glob = require('glob');
var beautifyHtml = require('js-beautify').html;
var through = require('through2');

// Consts
var PLUGIN_NAME = 'gulp-dust-crawler';

var gulpDustCrawler = function(options) {
  var pagesPath = options.pages;
  var templatesPath = options.templates;
  var componentsPath = options.components;
  var filtersPath = options.filters;
  // var helpersPath = options.helpers;

  // register filters and helpers
  var filtersFiles = glob.sync(filtersPath + '/*.js');
  // var helpersFiles = glob.sync(helpersPath + '/*.js');
  _.forEach(filtersFiles, function(filter) {
    require(process.cwd() + '/' + filter)(dust);
  })
  // _.forEach(herlpersFiles, function(helper) {
  //   require(process.cwd() + '/' + helper)(dust);
  // })

  var jsonTemplatesFiles = glob.sync(templatesPath + '/*.json');
  var jsonTemplates = [];
  var jsonComponentsFiles = glob.sync(componentsPath + '/**/*.json');
  var jsonComponents = {'components': {}};
  var jsonPagesFiles = glob.sync(pagesPath + '/*.json');
  var componentTemplates = glob.sync(componentsPath + '/**/*.dust');
  var globalTemplates = glob.sync(templatesPath + '/*.dust');

  _.forEach(globalTemplates, function(templatePath) {
    var template =  fs.readFileSync(templatePath, 'utf8');
    var templateName = templatePath.split('/').pop().split('.')[0];
    var compiled = dust.compile(template, templateName);
    dust.loadSource(compiled);
  });

  _.forEach(componentTemplates, function(component) {
    var template =  fs.readFileSync(component, 'utf8');
    var templateName = component.split('/').pop().split('.')[0];
    var compiled = dust.compile(template, templateName);
    dust.loadSource(compiled);
  });

  _.forEach(jsonComponentsFiles, function (component) {
    var parsed = JSON.parse(fs.readFileSync(component, 'utf8'));
    var componentName = component.split('/').pop().split('.')[0];
    jsonComponents.components[componentName] = parsed;
  });

  _.forEach(jsonTemplatesFiles, function (template) {
    var parsed = JSON.parse(fs.readFileSync(template, 'utf8'));
    _.merge(jsonTemplates, parsed);
  });

  var jsonDefault = _.extend({}, jsonTemplates, jsonComponents);

  return through.obj(function(file, encode, callback) {
    try {
      var templateCode = file.contents.toString(encode || 'utf8');
      var that = this;
      var jsonData = null;

      var dustRender = function(code, templateName, data, path) {
        var compiled = dust.compile(code, templateName);
        dust.loadSource(compiled);
        dust.render(templateName, data, function(err, output) {
          var tempFile = new gutil.File({
            base: file.base,
            cwd: file.cwd,
            path: path
          });

          tempFile.contents = new Buffer(beautifyHtml(output));
          that.push(tempFile);
        })
      };

      // Get pages
      _.forEach(jsonPagesFiles, function(page) {
        var pageName = page.split('/').pop().split('.')[0];
        var parsed = JSON.parse(fs.readFileSync(page, 'utf8'));
        jsonData = _.merge({}, jsonDefault, parsed);

        // Get sports
        var jsonSportFile = glob.sync(pagesPath + '/' + pageName + '/*.json');
        _.forEach(jsonSportFile, function(sport) {
          var sportName = sport.split('/').pop().split('.')[0];
          var parsed = JSON.parse(fs.readFileSync(sport, 'utf8'));
          var sportData = _.omit(parsed, 'pageState');
          var sportData = _.extend({}, jsonData, sportData);

          // Get pageState
          _.forEach(parsed.pageState, function(state) {
            _.merge(sportData, {pageState: state.name});

            // Get gameFormat
            if(state.gameFormat) {
              _.forEach(state.gameFormat, function(format) {
                var withoutName = _.omit(format, 'name');
                var sportWithGameData = _.extend({}, sportData, {gameFormat: format.name});
                _.merge(sportWithGameData, withoutName);
                dustRender(
                  templateCode,
                  pageName,
                  sportWithGameData,
                  file.path.replace('.dust', '.html')
                  .replace(
                    pageName,
                    pageName + '/' + sportName + '-' + format.name + '--' + state.name
                  )
                );

              })
            } else {
              dustRender(
                templateCode,
                pageName,
                sportData,
                file.path.replace('.dust', '.html')
                .replace(
                  pageName,
                  pageName + '/' + sportName + '--' + state.name
                )
              );
            }
          });
        });
      });

      return callback();

    } catch (err) {
      return callback(new gutil.PluginError('gulp-dust-crawler', err, options));
    }

    callback(null, file);
  });
};
module.exports = gulpDustCrawler;
<commit_msg>enable helpers<commit_after>'use strict';

// Vars
var _ = require('lodash');
var dust = require('dustjs-linkedin');
dust.helpers = require('dustjs-helpers').helpers;

var commonhelpers = new (require("common-dustjs-helpers").CommonDustjsHelpers)();
commonhelpers.export_to(dust);

var gutil = require('gulp-util');
var PluginError = gutil.PluginError;
var fs = require('fs');
var path = require('path');
var glob = require('glob');
var beautifyHtml = require('js-beautify').html;
var through = require('through2');

// Consts
var PLUGIN_NAME = 'gulp-dust-crawler';

var gulpDustCrawler = function(options) {
  var pagesPath = options.pages;
  var templatesPath = options.templates;
  var componentsPath = options.components;
  var filtersPath = options.filters;
  var helpersPath = options.helpers;

  // register filters and helpers
  var filtersFiles = glob.sync(filtersPath + '/*.js');
  var helpersFiles = glob.sync(helpersPath + '/*.js');
  _.forEach(filtersFiles, function(filter) {
    require(process.cwd() + '/' + filter)(dust);
  })
  _.forEach(herlpersFiles, function(helper) {
    require(process.cwd() + '/' + helper)(dust);
  })

  var jsonTemplatesFiles = glob.sync(templatesPath + '/*.json');
  var jsonTemplates = [];
  var jsonComponentsFiles = glob.sync(componentsPath + '/**/*.json');
  var jsonComponents = {'components': {}};
  var jsonPagesFiles = glob.sync(pagesPath + '/*.json');
  var componentTemplates = glob.sync(componentsPath + '/**/*.dust');
  var globalTemplates = glob.sync(templatesPath + '/*.dust');

  _.forEach(globalTemplates, function(templatePath) {
    var template =  fs.readFileSync(templatePath, 'utf8');
    var templateName = templatePath.split('/').pop().split('.')[0];
    var compiled = dust.compile(template, templateName);
    dust.loadSource(compiled);
  });

  _.forEach(componentTemplates, function(component) {
    var template =  fs.readFileSync(component, 'utf8');
    var templateName = component.split('/').pop().split('.')[0];
    var compiled = dust.compile(template, templateName);
    dust.loadSource(compiled);
  });

  _.forEach(jsonComponentsFiles, function (component) {
    var parsed = JSON.parse(fs.readFileSync(component, 'utf8'));
    var componentName = component.split('/').pop().split('.')[0];
    jsonComponents.components[componentName] = parsed;
  });

  _.forEach(jsonTemplatesFiles, function (template) {
    var parsed = JSON.parse(fs.readFileSync(template, 'utf8'));
    _.merge(jsonTemplates, parsed);
  });

  var jsonDefault = _.extend({}, jsonTemplates, jsonComponents);

  return through.obj(function(file, encode, callback) {
    try {
      var templateCode = file.contents.toString(encode || 'utf8');
      var that = this;
      var jsonData = null;

      var dustRender = function(code, templateName, data, path) {
        var compiled = dust.compile(code, templateName);
        dust.loadSource(compiled);
        dust.render(templateName, data, function(err, output) {
          var tempFile = new gutil.File({
            base: file.base,
            cwd: file.cwd,
            path: path
          });

          tempFile.contents = new Buffer(beautifyHtml(output));
          that.push(tempFile);
        })
      };

      // Get pages
      _.forEach(jsonPagesFiles, function(page) {
        var pageName = page.split('/').pop().split('.')[0];
        var parsed = JSON.parse(fs.readFileSync(page, 'utf8'));
        jsonData = _.merge({}, jsonDefault, parsed);

        // Get sports
        var jsonSportFile = glob.sync(pagesPath + '/' + pageName + '/*.json');
        _.forEach(jsonSportFile, function(sport) {
          var sportName = sport.split('/').pop().split('.')[0];
          var parsed = JSON.parse(fs.readFileSync(sport, 'utf8'));
          var sportData = _.omit(parsed, 'pageState');
          var sportData = _.extend({}, jsonData, sportData);

          // Get pageState
          _.forEach(parsed.pageState, function(state) {
            _.merge(sportData, {pageState: state.name});

            // Get gameFormat
            if(state.gameFormat) {
              _.forEach(state.gameFormat, function(format) {
                var withoutName = _.omit(format, 'name');
                var sportWithGameData = _.extend({}, sportData, {gameFormat: format.name});
                _.merge(sportWithGameData, withoutName);
                dustRender(
                  templateCode,
                  pageName,
                  sportWithGameData,
                  file.path.replace('.dust', '.html')
                  .replace(
                    pageName,
                    pageName + '/' + sportName + '-' + format.name + '--' + state.name
                  )
                );

              })
            } else {
              dustRender(
                templateCode,
                pageName,
                sportData,
                file.path.replace('.dust', '.html')
                .replace(
                  pageName,
                  pageName + '/' + sportName + '--' + state.name
                )
              );
            }
          });
        });
      });

      return callback();

    } catch (err) {
      return callback(new gutil.PluginError('gulp-dust-crawler', err, options));
    }

    callback(null, file);
  });
};
module.exports = gulpDustCrawler;
<|endoftext|>