<commit_before>import jsTokens, { matchToToken } from "js-tokens";
import esutils from "esutils";
import Chalk from "chalk";

let deprecationWarningShown = false;

type Location = {
  column: number,
  line: number,
};

type NodeLocation = {
  end: Location,
  start: Location,
};

/**
 * Chalk styles for token types.
 */

function getDefs(chalk) {
  return {
    keyword: chalk.cyan,
    capitalized: chalk.yellow,
    jsx_tag: chalk.yellow,
    punctuator: chalk.yellow,
    // bracket:  intentionally omitted.
    number: chalk.magenta,
    string: chalk.green,
    regex: chalk.magenta,
    comment: chalk.grey,
    invalid: chalk.white.bgRed.bold,
    gutter: chalk.grey,
    marker: chalk.red.bold,
  };
}

/**
 * RegExp to test for newlines in terminal.
 */

const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;

/**
 * RegExp to test for what seems to be a JSX tag name.
 */

const JSX_TAG = /^[a-z][\w-]*$/i;

/**
 * RegExp to test for the three types of brackets.
 */

const BRACKET = /^[()[\]{}]$/;

/**
 * Get the type of token, specifying punctuator type.
 */

function getTokenType(match) {
  const [offset, text] = match.slice(-2);
  const token = matchToToken(match);

  if (token.type === "name") {
    if (esutils.keyword.isReservedWordES6(token.value)) {
      return "keyword";
    }

    if (
      JSX_TAG.test(token.value) &&
      (text[offset - 1] === "<" || text.substr(offset - 2, 2) == "</")
    ) {
      return "jsx_tag";
    }

    if (token.value[0] !== token.value[0].toLowerCase()) {
      return "capitalized";
    }
  }

  if (token.type === "punctuator" && BRACKET.test(token.value)) {
    return "bracket";
  }

  if (
    token.type === "invalid" &&
    (token.value === "@" || token.value === "#")
  ) {
    return "punctuator";
  }

  return token.type;
}

/**
 * Highlight `text`.
 */

function highlight(defs: Object, text: string) {
  return text.replace(jsTokens, function(...args) {
    const type = getTokenType(args);
    const colorize = defs[type];
    if (colorize) {
      return args[0]
        .split(NEWLINE)
        .map(str => colorize(str))
        .join("\n");
    } else {
      return args[0];
    }
  });
}

/**
 * Extract what lines should be marked and highlighted.
 */

function getMarkerLines(
  loc: NodeLocation,
  source: Array<string>,
  opts: Object,
): { start: number, end: number, markerLines: Object } {
  const startLoc: Location = Object.assign(
    {},
    { column: 0, line: -1 },
    loc.start,
  );
  const endLoc: Location = Object.assign({}, startLoc, loc.end);
  const linesAbove = opts.linesAbove || 2;
  const linesBelow = opts.linesBelow || 3;

  const startLine = startLoc.line;
  const startColumn = startLoc.column;
  const endLine = endLoc.line;
  const endColumn = endLoc.column;

  let start = Math.max(startLine - (linesAbove + 1), 0);
  let end = Math.min(source.length, endLine + linesBelow);

  if (startLine === -1) {
    start = 0;
  }

  if (endLine === -1) {
    end = source.length;
  }

  const lineDiff = endLine - startLine;
  const markerLines = {};

  if (lineDiff) {
    for (let i = 0; i <= lineDiff; i++) {
      const lineNumber = i + startLine;

      if (!startColumn) {
        markerLines[lineNumber] = true;
      } else if (i === 0) {
        const sourceLength = source[lineNumber - 1].length;

        markerLines[lineNumber] = [startColumn, sourceLength - startColumn];
      } else if (i === lineDiff) {
        markerLines[lineNumber] = [0, endColumn];
      } else {
        const sourceLength = source[lineNumber - i].length;

        markerLines[lineNumber] = [0, sourceLength];
      }
    }
  } else {
    if (startColumn === endColumn) {
      if (startColumn) {
        markerLines[startLine] = [startColumn, 0];
      } else {
        markerLines[startLine] = true;
      }
    } else {
      markerLines[startLine] = [startColumn, endColumn - startColumn];
    }
  }

  return { start, end, markerLines };
}

export function codeFrameColumns(
  rawLines: string,
  loc: NodeLocation,
  opts: Object = {},
): string {
  const highlighted =
    (opts.highlightCode && Chalk.supportsColor) || opts.forceColor;
  let chalk = Chalk;
  if (opts.forceColor) {
    chalk = new Chalk.constructor({ enabled: true });
  }
  const maybeHighlight = (chalkFn, string) => {
    return highlighted ? chalkFn(string) : string;
  };
  const defs = getDefs(chalk);
  if (highlighted) rawLines = highlight(defs, rawLines);

  const lines = rawLines.split(NEWLINE);
  const { start, end, markerLines } = getMarkerLines(loc, lines, opts);

  const numberMaxWidth = String(end).length;

  const frame = lines
    .slice(start, end)
    .map((line, index) => {
      const number = start + 1 + index;
      const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
      const gutter = ` ${paddedNumber} | `;
      const hasMarker = markerLines[number];
      if (hasMarker) {
        let markerLine = "";
        if (Array.isArray(hasMarker)) {
          const markerSpacing = line
            .slice(0, Math.max(hasMarker[0] - 1, 0))
            .replace(/[^\t]/g, " ");
          const numberOfMarkers = hasMarker[1] || 1;

          markerLine = [
            "\n ",
            maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")),
            markerSpacing,
            maybeHighlight(defs.marker, "^").repeat(numberOfMarkers),
          ].join("");
        }
        return [
          maybeHighlight(defs.marker, ">"),
          maybeHighlight(defs.gutter, gutter),
          line,
          markerLine,
        ].join("");
      } else {
        return ` ${maybeHighlight(defs.gutter, gutter)}${line}`;
      }
    })
    .join("\n");

  if (highlighted) {
    return chalk.reset(frame);
  } else {
    return frame;
  }
}

/**
 * Create a code frame, adding line numbers, code highlighting, and pointing to a given position.
 */

export default function(
  rawLines: string,
  lineNumber: number,
  colNumber: ?number,
  opts: Object = {},
): string {
  if (!deprecationWarningShown) {
    deprecationWarningShown = true;

    const deprecationError = new Error(
      "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.",
    );
    deprecationError.name = "DeprecationWarning";

    if (process.emitWarning) {
      process.emitWarning(deprecationError);
    } else {
      console.warn(deprecationError);
    }
  }

  colNumber = Math.max(colNumber, 0);

  const location: NodeLocation = {
    start: { column: colNumber, line: lineNumber },
  };

  return codeFrameColumns(rawLines, location, opts);
}
<commit_msg>bugfix: set color level when color is forced (#7216)<commit_after>import jsTokens, { matchToToken } from "js-tokens";
import esutils from "esutils";
import Chalk from "chalk";

let deprecationWarningShown = false;

type Location = {
  column: number,
  line: number,
};

type NodeLocation = {
  end: Location,
  start: Location,
};

/**
 * Chalk styles for token types.
 */

function getDefs(chalk) {
  return {
    keyword: chalk.cyan,
    capitalized: chalk.yellow,
    jsx_tag: chalk.yellow,
    punctuator: chalk.yellow,
    // bracket:  intentionally omitted.
    number: chalk.magenta,
    string: chalk.green,
    regex: chalk.magenta,
    comment: chalk.grey,
    invalid: chalk.white.bgRed.bold,
    gutter: chalk.grey,
    marker: chalk.red.bold,
  };
}

/**
 * RegExp to test for newlines in terminal.
 */

const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;

/**
 * RegExp to test for what seems to be a JSX tag name.
 */

const JSX_TAG = /^[a-z][\w-]*$/i;

/**
 * RegExp to test for the three types of brackets.
 */

const BRACKET = /^[()[\]{}]$/;

/**
 * Get the type of token, specifying punctuator type.
 */

function getTokenType(match) {
  const [offset, text] = match.slice(-2);
  const token = matchToToken(match);

  if (token.type === "name") {
    if (esutils.keyword.isReservedWordES6(token.value)) {
      return "keyword";
    }

    if (
      JSX_TAG.test(token.value) &&
      (text[offset - 1] === "<" || text.substr(offset - 2, 2) == "</")
    ) {
      return "jsx_tag";
    }

    if (token.value[0] !== token.value[0].toLowerCase()) {
      return "capitalized";
    }
  }

  if (token.type === "punctuator" && BRACKET.test(token.value)) {
    return "bracket";
  }

  if (
    token.type === "invalid" &&
    (token.value === "@" || token.value === "#")
  ) {
    return "punctuator";
  }

  return token.type;
}

/**
 * Highlight `text`.
 */

function highlight(defs: Object, text: string) {
  return text.replace(jsTokens, function(...args) {
    const type = getTokenType(args);
    const colorize = defs[type];
    if (colorize) {
      return args[0]
        .split(NEWLINE)
        .map(str => colorize(str))
        .join("\n");
    } else {
      return args[0];
    }
  });
}

/**
 * Extract what lines should be marked and highlighted.
 */

function getMarkerLines(
  loc: NodeLocation,
  source: Array<string>,
  opts: Object,
): { start: number, end: number, markerLines: Object } {
  const startLoc: Location = Object.assign(
    {},
    { column: 0, line: -1 },
    loc.start,
  );
  const endLoc: Location = Object.assign({}, startLoc, loc.end);
  const linesAbove = opts.linesAbove || 2;
  const linesBelow = opts.linesBelow || 3;

  const startLine = startLoc.line;
  const startColumn = startLoc.column;
  const endLine = endLoc.line;
  const endColumn = endLoc.column;

  let start = Math.max(startLine - (linesAbove + 1), 0);
  let end = Math.min(source.length, endLine + linesBelow);

  if (startLine === -1) {
    start = 0;
  }

  if (endLine === -1) {
    end = source.length;
  }

  const lineDiff = endLine - startLine;
  const markerLines = {};

  if (lineDiff) {
    for (let i = 0; i <= lineDiff; i++) {
      const lineNumber = i + startLine;

      if (!startColumn) {
        markerLines[lineNumber] = true;
      } else if (i === 0) {
        const sourceLength = source[lineNumber - 1].length;

        markerLines[lineNumber] = [startColumn, sourceLength - startColumn];
      } else if (i === lineDiff) {
        markerLines[lineNumber] = [0, endColumn];
      } else {
        const sourceLength = source[lineNumber - i].length;

        markerLines[lineNumber] = [0, sourceLength];
      }
    }
  } else {
    if (startColumn === endColumn) {
      if (startColumn) {
        markerLines[startLine] = [startColumn, 0];
      } else {
        markerLines[startLine] = true;
      }
    } else {
      markerLines[startLine] = [startColumn, endColumn - startColumn];
    }
  }

  return { start, end, markerLines };
}

export function codeFrameColumns(
  rawLines: string,
  loc: NodeLocation,
  opts: Object = {},
): string {
  const highlighted =
    (opts.highlightCode && Chalk.supportsColor) || opts.forceColor;
  let chalk = Chalk;
  if (opts.forceColor) {
    chalk = new Chalk.constructor({ enabled: true, level: 1 });
  }
  const maybeHighlight = (chalkFn, string) => {
    return highlighted ? chalkFn(string) : string;
  };
  const defs = getDefs(chalk);
  if (highlighted) rawLines = highlight(defs, rawLines);

  const lines = rawLines.split(NEWLINE);
  const { start, end, markerLines } = getMarkerLines(loc, lines, opts);

  const numberMaxWidth = String(end).length;

  const frame = lines
    .slice(start, end)
    .map((line, index) => {
      const number = start + 1 + index;
      const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
      const gutter = ` ${paddedNumber} | `;
      const hasMarker = markerLines[number];
      if (hasMarker) {
        let markerLine = "";
        if (Array.isArray(hasMarker)) {
          const markerSpacing = line
            .slice(0, Math.max(hasMarker[0] - 1, 0))
            .replace(/[^\t]/g, " ");
          const numberOfMarkers = hasMarker[1] || 1;

          markerLine = [
            "\n ",
            maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")),
            markerSpacing,
            maybeHighlight(defs.marker, "^").repeat(numberOfMarkers),
          ].join("");
        }
        return [
          maybeHighlight(defs.marker, ">"),
          maybeHighlight(defs.gutter, gutter),
          line,
          markerLine,
        ].join("");
      } else {
        return ` ${maybeHighlight(defs.gutter, gutter)}${line}`;
      }
    })
    .join("\n");

  if (highlighted) {
    return chalk.reset(frame);
  } else {
    return frame;
  }
}

/**
 * Create a code frame, adding line numbers, code highlighting, and pointing to a given position.
 */

export default function(
  rawLines: string,
  lineNumber: number,
  colNumber: ?number,
  opts: Object = {},
): string {
  if (!deprecationWarningShown) {
    deprecationWarningShown = true;

    const deprecationError = new Error(
      "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.",
    );
    deprecationError.name = "DeprecationWarning";

    if (process.emitWarning) {
      process.emitWarning(deprecationError);
    } else {
      console.warn(deprecationError);
    }
  }

  colNumber = Math.max(colNumber, 0);

  const location: NodeLocation = {
    start: { column: colNumber, line: lineNumber },
  };

  return codeFrameColumns(rawLines, location, opts);
}
<|endoftext|>


<commit_before>// Copyright (C) 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview
 * Registers a language handler for Haskell.
 *
 *
 * To use, include prettify.js and this file in your HTML page.
 * Then put your code in an HTML tag like
 *
(my lisp code)

 * The lang-cl class identifies the language as common lisp.
 * This file supports the following language extensions:
 *     lang-cl - Common Lisp
 *     lang-el - Emacs Lisp
 *     lang-lisp - Lisp
 *     lang-scm - Scheme
 *
 *
 * I used http://www.informatik.uni-freiburg.de/~thiemann/haskell/haskell98-report-html/syntax-iso.html
 * as the basis, but ignore the way the ncomment production nests since this
 * makes the lexical grammar irregular.  It might be possible to support
 * ncomments using the lookbehind filter.
 *
 *
 * @author mikesamuel@gmail.com
 */

PR.registerLangHandler(
    PR.createSimpleLexer(
        [
         // Whitespace
         // whitechar    ->    newline | vertab | space | tab | uniWhite
         // newline      ->    return linefeed | return | linefeed | formfeed
         [PR.PR_PLAIN,       /^[\t\n\x0B\x0C\r ]+/, null, '\t\n\x0B\x0C\r '],
         // Single line double and single-quoted strings.
         // char         ->    ' (graphic<' | \> | space | escape<\&>) '
         // string       ->    " {graphic<" | \> | space | escape | gap}"
         // escape       ->    \ ( charesc | ascii | decimal | o octal
         //                        | x hexadecimal )
         // charesc      ->    a | b | f | n | r | t | v | \ | " | ' | &
         [PR.PR_STRING,      /^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,
          null, '"'],
         [PR.PR_STRING,      /^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/,
          null, "'"],
         // decimal      ->    digit{digit}
         // octal        ->    octit{octit}
         // hexadecimal  ->    hexit{hexit}
         // integer      ->    decimal
         //               |    0o octal | 0O octal
         //               |    0x hexadecimal | 0X hexadecimal
         // float        ->    decimal . decimal [exponent]
         //               |    decimal exponent
         // exponent     ->    (e | E) [+ | -] decimal
         [PR.PR_LITERAL,
          /^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,
          null, '0123456789']
        ],
        [
         // Haskell does not have a regular lexical grammar due to the nested
         // ncomment.
         // comment      ->    dashes [ any<symbol> {any}] newline
         // ncomment     ->    opencom ANYseq {ncomment ANYseq}closecom
         // dashes       ->    '--' {'-'}
         // opencom      ->    '{-'
         // closecom     ->    '-}'
         [PR.PR_COMMENT,     /^(?:(?:--+(?:[^\r\n\x0C_:\"\'\(\),;\[\]`\{\}][^\r\n\x0C_]*)?(?=[\x0C\r\n]|$))|(?:\{-(?:[^-]|-+[^-\}])*-\}))/],
         // reservedid   ->    case | class | data | default | deriving | do
         //               |    else | if | import | in | infix | infixl | infixr
         //               |    instance | let | module | newtype | of | then
         //               |    type | where | _
         [PR.PR_KEYWORD,     /^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/, null],
         // qvarid       ->    [ modid . ] varid
         // qconid       ->    [ modid . ] conid
         // varid        ->    (small {small | large | digit | ' })<reservedid>
         // conid        ->    large {small | large | digit | ' }
         // modid        ->    conid
         // small        ->    ascSmall | uniSmall | _
         // ascSmall     ->    a | b | ... | z
         // uniSmall     ->    any Unicode lowercase letter
         // large        ->    ascLarge | uniLarge
         // ascLarge     ->    A | B | ... | Z
         // uniLarge     ->    any uppercase or titlecase Unicode letter
         [PR.PR_PLAIN,  /^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/],
         // matches the symbol production
         [PR.PR_PUNCTUATION, /^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/]
        ]),
    ['hs']);
<commit_msg>bug 67: haskell line comments could not contain curly brackets.<commit_after>// Copyright (C) 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview
 * Registers a language handler for Haskell.
 *
 *
 * To use, include prettify.js and this file in your HTML page.
 * Then put your code in an HTML tag like
 *
(my lisp code)

 * The lang-cl class identifies the language as common lisp.
 * This file supports the following language extensions:
 *     lang-cl - Common Lisp
 *     lang-el - Emacs Lisp
 *     lang-lisp - Lisp
 *     lang-scm - Scheme
 *
 *
 * I used http://www.informatik.uni-freiburg.de/~thiemann/haskell/haskell98-report-html/syntax-iso.html
 * as the basis, but ignore the way the ncomment production nests since this
 * makes the lexical grammar irregular.  It might be possible to support
 * ncomments using the lookbehind filter.
 *
 *
 * @author mikesamuel@gmail.com
 */

PR.registerLangHandler(
    PR.createSimpleLexer(
        [
         // Whitespace
         // whitechar    ->    newline | vertab | space | tab | uniWhite
         // newline      ->    return linefeed | return | linefeed | formfeed
         [PR.PR_PLAIN,       /^[\t\n\x0B\x0C\r ]+/, null, '\t\n\x0B\x0C\r '],
         // Single line double and single-quoted strings.
         // char         ->    ' (graphic<' | \> | space | escape<\&>) '
         // string       ->    " {graphic<" | \> | space | escape | gap}"
         // escape       ->    \ ( charesc | ascii | decimal | o octal
         //                        | x hexadecimal )
         // charesc      ->    a | b | f | n | r | t | v | \ | " | ' | &
         [PR.PR_STRING,      /^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,
          null, '"'],
         [PR.PR_STRING,      /^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/,
          null, "'"],
         // decimal      ->    digit{digit}
         // octal        ->    octit{octit}
         // hexadecimal  ->    hexit{hexit}
         // integer      ->    decimal
         //               |    0o octal | 0O octal
         //               |    0x hexadecimal | 0X hexadecimal
         // float        ->    decimal . decimal [exponent]
         //               |    decimal exponent
         // exponent     ->    (e | E) [+ | -] decimal
         [PR.PR_LITERAL,
          /^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,
          null, '0123456789']
        ],
        [
         // Haskell does not have a regular lexical grammar due to the nested
         // ncomment.
         // comment      ->    dashes [ any<symbol> {any}] newline
         // ncomment     ->    opencom ANYseq {ncomment ANYseq}closecom
         // dashes       ->    '--' {'-'}
         // opencom      ->    '{-'
         // closecom     ->    '-}'
         [PR.PR_COMMENT,     /^(?:(?:--+(?:[^\r\n\x0C]*)?)|(?:\{-(?:[^-]|-+[^-\}])*-\}))/],
         // reservedid   ->    case | class | data | default | deriving | do
         //               |    else | if | import | in | infix | infixl | infixr
         //               |    instance | let | module | newtype | of | then
         //               |    type | where | _
         [PR.PR_KEYWORD,     /^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/, null],
         // qvarid       ->    [ modid . ] varid
         // qconid       ->    [ modid . ] conid
         // varid        ->    (small {small | large | digit | ' })<reservedid>
         // conid        ->    large {small | large | digit | ' }
         // modid        ->    conid
         // small        ->    ascSmall | uniSmall | _
         // ascSmall     ->    a | b | ... | z
         // uniSmall     ->    any Unicode lowercase letter
         // large        ->    ascLarge | uniLarge
         // ascLarge     ->    A | B | ... | Z
         // uniLarge     ->    any uppercase or titlecase Unicode letter
         [PR.PR_PLAIN,  /^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/],
         // matches the symbol production
         [PR.PR_PUNCTUATION, /^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/]
        ]),
    ['hs']);
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  confirmation_email: function(req, competitor, mailOptions) {
    mailOptions.html = [
      'Hallo ' + competitor.firtname + ' ' + competitor.name + ',',
      'Vielen Dank für Deine Anmeldung.',
      'Du kannst Deine Angaben jederzeit unter folgendem Link einsehen und allenfalls korrigieren:',
      'http://' + req.headers.host + '/#!/competitor/' + competitor._id,
      'Nach dem Wettkampf kannst Du unter diesem Link auch Deine Resultate einsehen.',
    ].join('\n\n');
    mailOptions.subject = 'Anmeldebestätigung';
    return mailOptions;
  }
};
<commit_msg>Mailtemplate korrigiert<commit_after>'use strict';

module.exports = {
  confirmation_email: function(req, competitor, mailOptions) {
    mailOptions.html = [
      'Hallo ' + competitor.firstname + ' ' + competitor.name + ',',
      'Vielen Dank für Deine Anmeldung.',
      'Du kannst Deine Angaben jederzeit unter folgendem Link einsehen und allenfalls korrigieren:',
      'http://' + req.headers.host + '/#!/competitor/' + competitor._id,
      'Nach dem Wettkampf kannst Du unter diesem Link auch Deine Resultate einsehen.',
    ].join('\n\n');
    mailOptions.subject = 'Anmeldebestätigung';
    return mailOptions;
  }
};
<|endoftext|>


<commit_before>const Helmet = require("react-helmet").default;
const React = require("react");
const styled = require("styled-components").default;
const injectGlobal = require("styled-components").injectGlobal;
const ThemeProvider = require("styled-components").ThemeProvider;

const Headline = require("../headline");
const Favicon = require("./favicon");
const Link = require("../link");
const Text = require("../text");
const themes = require("../themes");

module.exports.default = Cover;
module.exports.head = () => Helmet.rewind();

function Cover() {
  return (
    <ThemeProvider theme={themes().dark}>
      <React.Fragment>
        <Helmet
          title="patternplate"
          link={[
            {
              rel: "icon",
              type: "text/svg",
              href: Favicon.svg
            },
            {
              rel: "icon",
              type: "image/png",
              href: Favicon.png
            }
          ]}
          meta={[
            {
              name: "viewport",
              content:
                "width=device-width, initial-scale=1.0, user-scalable=yes"
            }
          ]}
        />
        <StageContainer>
          <Frame>

              <Logo />
              <Stage>
                <StageSlot>
                  <StageHeadline>
                    Create better <nobr>Design Systems</nobr>
                  </StageHeadline>
                  <StageText>
                    patternplate connects Design and Engineering to establish a
                    real Source of Truth for your team.
                  </StageText>
                </StageSlot>
                <StageSlot>
                  <StageImage src="https://patternplate.github.io/media/images/screenshot-site.svg" />
                </StageSlot>
              </Stage>

          </Frame>
        </StageContainer>
        <ThemeProvider theme={themes().light}>
          <Principles>
            <Frame width="75%">
              <Principle>
                <Principle.Title order={2}>Come as you are</Principle.Title>
                <Principle.Text>

Not a CLI, not an app. Both.

                    Work in the environment you are comfortable with and expend
                    your time for great design and engineering work instead of
                    struggling with tools made for other disciplines.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  A Living <nobr>Single Source of Truth</nobr>
                </Principle.Title>
                <Principle.Text>

Your work is so much more than its parts.

                    Meld code and documentation into something more valuable – a
                    real <nobr>Source of Truth</nobr> that is always up to date
                    by design.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  Bring Order to Chaos
                </Principle.Title>
                <Principle.Text>

Make sense of your design universe with meta data.

                    Describe your tokens and components with a fixed schema to
                    help everyone to find, evaluate and understand your work.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  Stay in touch with your work
                </Principle.Title>
                <Principle.Text>

Manipulate your design system directly.

                    Edit your components, tokens and documentation and see your
                    changes reflected directly in patternplate interface.

                </Principle.Text>
              </Principle>
            </Frame>
          </Principles>
        </ThemeProvider>
        <ButtonRow>
          <Frame>
            <ButtonRowContent>
              <StageButton href="./doc/docs/why?guides-enabled=true">
                <Text>Show me how</Text>
              </StageButton>
              <GithubButton
                target="_blank"
                href="https://github.com/patternplate/patternplate"
              >
                <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
                  <path d="M512 0C229.25 0 0 229.25 0 512c0 226.25 146.688 418.125 350.156 485.812 25.594 4.688 34.938-11.125 34.938-24.625 0-12.188-0.469-52.562-0.719-95.312C242 908.812 211.906 817.5 211.906 817.5c-23.312-59.125-56.844-74.875-56.844-74.875-46.531-31.75 3.53-31.125 3.53-31.125 51.406 3.562 78.47 52.75 78.47 52.75 45.688 78.25 119.875 55.625 149 42.5 4.654-33 17.904-55.625 32.5-68.375C304.906 725.438 185.344 681.5 185.344 485.312c0-55.938 19.969-101.562 52.656-137.406-5.219-13-22.844-65.094 5.062-135.562 0 0 42.938-13.75 140.812 52.5 40.812-11.406 84.594-17.031 128.125-17.219 43.5 0.188 87.312 5.875 128.188 17.281 97.688-66.312 140.688-52.5 140.688-52.5 28 70.531 10.375 122.562 5.125 135.5 32.812 35.844 52.625 81.469 52.625 137.406 0 196.688-119.75 240-233.812 252.688 18.438 15.875 34.75 47 34.75 94.75 0 68.438-0.688 123.625-0.688 140.5 0 13.625 9.312 29.562 35.25 24.562C877.438 930 1024 738.125 1024 512 1024 229.25 794.75 0 512 0z" />
                </svg>
              </GithubButton>
            </ButtonRowContent>
          </Frame>
        </ButtonRow>
      </React.Fragment>
    </ThemeProvider>
  );
}

injectGlobal`
  body {
    margin: 0 0 100px 0;
    overflow-x: hidden;
  }
`;

const Frame = styled.div`
  box-sizing: border-box;
  width: ${props => props.width || "100%"};
  min-width: 320px;
  max-width: 1440px;
  margin: 0 auto;
`;

const Stage = styled.div`
  display: grid;
  grid-column-gap: 15px;
  position: relative;
  @media screen and (min-width: 720px) {
    grid-template-columns: 1.5fr 1fr;
    grid-column-gap: 5vw;
  }
  @media screen and (min-width: 840px) {
    grid-template-columns: 1.5fr 1.3fr;
  }
`;

const StageSlot = styled.div`
  position: relative;
  padding: 20px 30px;
`;

const StageContainer = styled.div`
  width: 100%;
  background-image: linear-gradient(-45deg, #4504da, #ff0353);
  min-height: calc(100vh + 100px);
  color: #ffffff;
  overflow: hidden;
`;

const Logo = styled.svg.attrs({
  viewBox: "0 0 100 100",
  children: [
    <path
      key="1"
      d="M50 75a3.75 3.75 0 0 1-2-.56l-26.85-16.7a2.55 2.55 0 1 1 2.69-4.32L50 69.72l26.15-16.3a2.55 2.55 0 1 1 2.69 4.32L52 74.48a3.76 3.76 0 0 1-2 .52z"
    />,
    <path
      key="2"
      d="M50 65a3.69 3.69 0 0 1-1.95-.55L21.69 48a3.54 3.54 0 0 1 0-6l26.36-16.44a3.71 3.71 0 0 1 3.9 0L78.31 42a3.54 3.54 0 0 1 0 6L51.95 64.44A3.68 3.68 0 0 1 50 65zM26.3 45L50 59.77 73.7 45 50 30.23z"
    />
  ]
})`
  width: 10vw;
  height: 10vw;
  min-width: 80px;
  max-width: 240px;
  min-height: 80px;
  max-height: 240px;
  fill: currentColor;
  color: inherit;
  margin: 15px 0 0 15px;
  @media screen and (min-width: 1024px) {
    margin: 15px 0 0 5px;
  }
`;

const StageHeadline = styled(Headline)`
  font-size: 40px;
  margin: 0 0 1em 0;

  @media screen and (min-width: 480px) {
    font-size: 60px;
    max-width: 15ch;
  }

  @media screen and (min-width: 1240px) {
    font-size: 72px;
  }
`;

const StageText = styled(Text)`
  max-width: 25ch;
  font-weight: 200;
  line-height: 1.3em;
  margin-bottom: 2em;
  font-size: 25px;
  @media screen and (min-width: 1240px) {
    font-size: 35px;
  }
`;

const StageImage = styled.img`
  width: 150%;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: -10px -10px 20px rgba(0, 0, 0, 0.15);

  @media screen and (min-width: 720px) {
    bottom: -20px;
    top: 0;
    width: auto;
  }
`;

const ButtonRow = styled.div`
  position: fixed;
  z-index: 1;
  right: 0;
  left: 0;
  bottom: 0;
  background: #fff;
  box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.1);
  padding: 20px 30px;
`;

const ButtonRowContent = styled.div`
  display: flex;
  align-items: center;
`;

const StageButton = styled(Link)`
  display: inline-flex;
  align-items: center;
  font-size: 24px;
  line-height: auto;
  padding: 0.6em;
  border: 1px solid currentColor;
  text-decoration: none;
  background: #100133;
  color: #fff;
  border-radius: 3px;
  margin-right: 20px;
`;

const GithubButton = styled(Link)`
  height: 40px;
  width: 40px;
  fill: color;
  color: #100133;
  svg {
    width: 100%;
    pointer-events: none;
  }
`;

const Principles = styled.div`
  background: #fff;
  color: #000;
  padding: 40px 0;
  @media screen and (min-width: 600px) {
    padding-top: 125px;
  }

  ${Frame} {
    box-sizing: border-box;
    display: grid;
    grid-column-gap: 20px;
    grid-row-gap: 20px;
    grid-auto-columns: 1fr;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  }
`;

const Principle = props => (
  <PrincipleContainer>{props.children}</PrincipleContainer>
);

Principle.Title = styled(Headline)`
  margin: 0;
  grid-row: headline;
`;

Principle.Text = styled(Text)`
  grid-row: text;
`;

const PrincipleContainer = styled.div`
  box-sizing: border-box;
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 20px 15px;
  /* &::before {
    content: '';
    grid-row-start: headline;
    grid-row-end: text;
  } */
`;
<commit_msg>docs: finalize principles section<commit_after>const Helmet = require("react-helmet").default;
const React = require("react");
const styled = require("styled-components").default;
const injectGlobal = require("styled-components").injectGlobal;
const ThemeProvider = require("styled-components").ThemeProvider;

const Headline = require("../headline");
const Favicon = require("./favicon");
const Link = require("../link");
const Text = require("../text");
const themes = require("../themes");

module.exports.default = Cover;
module.exports.head = () => Helmet.rewind();

function Cover() {
  return (
    <ThemeProvider theme={themes().dark}>
      <React.Fragment>
        <Helmet
          title="patternplate"
          link={[
            {
              rel: "icon",
              type: "text/svg",
              href: Favicon.svg
            },
            {
              rel: "icon",
              type: "image/png",
              href: Favicon.png
            }
          ]}
          meta={[
            {
              name: "viewport",
              content:
                "width=device-width, initial-scale=1.0, user-scalable=yes"
            }
          ]}
        />
        <StageContainer>
          <Frame>

              <Logo />
              <Stage>
                <StageSlot>
                  <StageHeadline>
                    Create better <nobr>Design Systems</nobr>
                  </StageHeadline>
                  <StageText>
                    patternplate connects Design and Engineering to establish a
                    real Source of Truth for your team.
                  </StageText>
                </StageSlot>
                <StageSlot>
                  <StageImage src="https://patternplate.github.io/media/images/screenshot-site.svg" />
                </StageSlot>
              </Stage>

          </Frame>
        </StageContainer>
        <ThemeProvider theme={themes().light}>
          <Principles>
            <Frame width="75%">
              <Principle>
                <Principle.Title order={2}>Come as you are</Principle.Title>
                <Principle.Text>

Not a CLI, not an app. Both.

                    Work in the environment you are comfortable with and expend
                    your time for great design and engineering work instead of
                    struggling with tools made for other disciplines.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  Establish a Source of Truth
                </Principle.Title>
                <Principle.Text>

Your work is so much more than its parts.

                    Meld code and documentation into something more valuable – a
                    real <nobr>Source of Truth</nobr> that is always up to date
                    by design.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  Bring Order to Chaos
                </Principle.Title>
                <Principle.Text>

Make sense of your design universe with meta data.

                    Describe your tokens and components with a fixed schema to
                    help everyone to understand, use and remix your work.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  Stay in touch with your work
                </Principle.Title>
                <Principle.Text>

Manipulate your design system directly.

                    Edit your components, tokens and documentation and see how patternplate
                    updates your Design System without reloading.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  Be as free as the web
                </Principle.Title>
                <Principle.Text>

 HTML, CSS and JavaScript – that's all it takes.

                    We supports component-specific stacks,
                    so you don't have to commit to a single technology.

                    Wan't to integrate a Vue component in a React Design Sytem?
                    Thats perfectly possible with patternplate.

                </Principle.Text>
              </Principle>
              <Principle>
                <Principle.Title order={2}>
                  Real components. Period.
                </Principle.Title>
                <Principle.Text>

Show and tell with code instead of faking it.

                    patternplate uses real-world, production-level code
                    components for demos and examples.

                    This saves you from wasting time polishing
                    components that never see the light of day and
                    makes the relation between Design System and product transparent.

                </Principle.Text>
              </Principle>
            </Frame>
          </Principles>
        </ThemeProvider>
        <ButtonRow>
          <Frame>
            <ButtonRowContent>
              <StageButton href="./doc/docs/why?guides-enabled=true">
                <Text>Show me how</Text>
              </StageButton>
              <GithubButton
                target="_blank"
                href="https://github.com/patternplate/patternplate"
              >
                <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
                  <path d="M512 0C229.25 0 0 229.25 0 512c0 226.25 146.688 418.125 350.156 485.812 25.594 4.688 34.938-11.125 34.938-24.625 0-12.188-0.469-52.562-0.719-95.312C242 908.812 211.906 817.5 211.906 817.5c-23.312-59.125-56.844-74.875-56.844-74.875-46.531-31.75 3.53-31.125 3.53-31.125 51.406 3.562 78.47 52.75 78.47 52.75 45.688 78.25 119.875 55.625 149 42.5 4.654-33 17.904-55.625 32.5-68.375C304.906 725.438 185.344 681.5 185.344 485.312c0-55.938 19.969-101.562 52.656-137.406-5.219-13-22.844-65.094 5.062-135.562 0 0 42.938-13.75 140.812 52.5 40.812-11.406 84.594-17.031 128.125-17.219 43.5 0.188 87.312 5.875 128.188 17.281 97.688-66.312 140.688-52.5 140.688-52.5 28 70.531 10.375 122.562 5.125 135.5 32.812 35.844 52.625 81.469 52.625 137.406 0 196.688-119.75 240-233.812 252.688 18.438 15.875 34.75 47 34.75 94.75 0 68.438-0.688 123.625-0.688 140.5 0 13.625 9.312 29.562 35.25 24.562C877.438 930 1024 738.125 1024 512 1024 229.25 794.75 0 512 0z" />
                </svg>
              </GithubButton>
            </ButtonRowContent>
          </Frame>
        </ButtonRow>
      </React.Fragment>
    </ThemeProvider>
  );
}

injectGlobal`
  body {
    margin: 0 0 100px 0;
    overflow-x: hidden;
  }
`;

const Frame = styled.div`
  box-sizing: border-box;
  width: ${props => props.width || "100%"};
  min-width: 320px;
  max-width: 1440px;
  margin: 0 auto;
`;

const Stage = styled.div`
  display: grid;
  grid-column-gap: 15px;
  position: relative;
  @media screen and (min-width: 720px) {
    grid-template-columns: 1.5fr 1fr;
    grid-column-gap: 5vw;
  }
  @media screen and (min-width: 840px) {
    grid-template-columns: 1.5fr 1.3fr;
  }
`;

const StageSlot = styled.div`
  position: relative;
  padding: 20px 30px;
`;

const StageContainer = styled.div`
  width: 100%;
  background-image: linear-gradient(-45deg, #4504da, #ff0353);
  min-height: calc(100vh + 100px);
  color: #ffffff;
  overflow: hidden;
`;

const Logo = styled.svg.attrs({
  viewBox: "0 0 100 100",
  children: [
    <path
      key="1"
      d="M50 75a3.75 3.75 0 0 1-2-.56l-26.85-16.7a2.55 2.55 0 1 1 2.69-4.32L50 69.72l26.15-16.3a2.55 2.55 0 1 1 2.69 4.32L52 74.48a3.76 3.76 0 0 1-2 .52z"
    />,
    <path
      key="2"
      d="M50 65a3.69 3.69 0 0 1-1.95-.55L21.69 48a3.54 3.54 0 0 1 0-6l26.36-16.44a3.71 3.71 0 0 1 3.9 0L78.31 42a3.54 3.54 0 0 1 0 6L51.95 64.44A3.68 3.68 0 0 1 50 65zM26.3 45L50 59.77 73.7 45 50 30.23z"
    />
  ]
})`
  width: 10vw;
  height: 10vw;
  min-width: 80px;
  max-width: 240px;
  min-height: 80px;
  max-height: 240px;
  fill: currentColor;
  color: inherit;
  margin: 15px 0 0 15px;
  @media screen and (min-width: 1024px) {
    margin: 15px 0 0 5px;
  }
`;

const StageHeadline = styled(Headline)`
  font-size: 40px;
  margin: 0 0 1em 0;

  @media screen and (min-width: 480px) {
    font-size: 60px;
    max-width: 15ch;
  }

  @media screen and (min-width: 1240px) {
    font-size: 72px;
  }
`;

const StageText = styled(Text)`
  max-width: 25ch;
  font-weight: 200;
  line-height: 1.3em;
  margin-bottom: 2em;
  font-size: 25px;
  @media screen and (min-width: 1240px) {
    font-size: 35px;
  }
`;

const StageImage = styled.img`
  width: 150%;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: -10px -10px 20px rgba(0, 0, 0, 0.15);

  @media screen and (min-width: 720px) {
    bottom: -20px;
    top: 0;
    width: auto;
  }
`;

const ButtonRow = styled.div`
  position: fixed;
  z-index: 1;
  right: 0;
  left: 0;
  bottom: 0;
  background: #fff;
  box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.1);
  padding: 20px 30px;
`;

const ButtonRowContent = styled.div`
  display: flex;
  align-items: center;
`;

const StageButton = styled(Link)`
  display: inline-flex;
  align-items: center;
  font-size: 24px;
  line-height: auto;
  padding: 0.6em;
  border: 1px solid currentColor;
  text-decoration: none;
  background: #100133;
  color: #fff;
  border-radius: 3px;
  margin-right: 20px;
`;

const GithubButton = styled(Link)`
  height: 40px;
  width: 40px;
  fill: color;
  color: #100133;
  svg {
    width: 100%;
    pointer-events: none;
  }
`;

const Principles = styled.div`
  background: #fff;
  color: #000;
  padding: 40px 0;
  @media screen and (min-width: 600px) {
    padding-top: 125px;
  }

  ${Frame} {
    box-sizing: border-box;
    display: grid;
    grid-column-gap: 20px;
    grid-row-gap: 20px;
    grid-auto-columns: 1fr;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  }
`;

const Principle = props => (
  <PrincipleContainer>{props.children}</PrincipleContainer>
);

Principle.Title = styled(Headline)`
  margin: 0;
  grid-row: headline;
`;

Principle.Text = styled(Text)`
  grid-row: text;
`;

const PrincipleContainer = styled.div`
  box-sizing: border-box;
  border: 1px solid rgba(0, 0, 0, 0.1);
  padding: 20px 15px;
  /* &::before {
    content: '';
    grid-row-start: headline;
    grid-row-end: text;
  } */
`;
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Resolver
////////////////////////////////////////////////////////////////////////////////

// XXX the whole resolver heavily relies on these statements to be true:
// - every unit version ever used was added to the resolver with addUnitVersion
// - every constraint ever used was instantiated with getConstraint
// - every constraint was added exactly once
// - every unit version was added exactly once
// - if two unit versions are the same, their refs point at the same object
// - if two constraints are the same, their refs point at the same object
ConstraintSolver.Resolver = function () {
  var self = this;

  // Maps unit name string to an array of version definitions
  self.unitsVersions = {};

  // Maps unit name string to the greatest version string we have
  self._latestVersion = {};

  // Refs to all constraints. Mapping String -> instance
  self._constraints = {};
};

ConstraintSolver.Resolver.prototype.addUnitVersion = function (unitVersion) {
  var self = this;

  check(unitVersion, ConstraintSolver.UnitVersion);

  if (! _.has(self.unitsVersions, unitVersion.name)) {
    self.unitsVersions[unitVersion.name] = [];
    self._latestVersion[unitVersion.name] = unitVersion.version;
  }

  self.unitsVersions[unitVersion.name].push(unitVersion);

  if (semver.lt(self._latestVersion[unitVersion.name], unitVersion.version))
    self._latestVersion[unitVersion.name] = unitVersion.version;
};

// name - String - "someUnit"
// versionConstraint - String - "=1.2.3" or "2.1.0"
ConstraintSolver.Resolver.prototype.getConstraint =
  function (name, versionConstraint) {
  var self = this;

  check(name, String);
  check(versionConstraint, String);

  var idString = JSON.stringify([name, versionConstraint]);

  if (_.has(self._constraints, idString))
    return self._constraints[idString];

  return self._constraints[idString] =
    new ConstraintSolver.Constraint(name, versionConstraint);
};

ConstraintSolver.Resolver.prototype.resolve =
  function (dependencies, constraints, choices, options) {
  var self = this;

  constraints = constraints || [];
  choices = choices || [];
  options = _.extend({
    costFunction: function (choices) { return 0; },
    estimateCostFunction: function (state) {
      return 0;
    }
  }, options);

  dependencies = _.uniq(dependencies);
  constraints = _.uniq(constraints);

  var rootDependencies = _.clone(dependencies);

  var exactDepsConstraints = _.filter(constraints, function (c) {
    return c.exact && _.contains(dependencies, c.name);
  });

  var exactDepsVersions = _.map(exactDepsConstraints, function (c) {
    return c.getSatisfyingUnitVersion(self);
  });

  var exactDepsNames = _.pluck(exactDepsVersions, "name");

  // Remove them from dependencies.
  dependencies = _.difference(dependencies, exactDepsNames);

  // Take exact dependencies and propagate them.
  // Will also pick these versions into choices as we have no choice but take
  // them.
  _.each(exactDepsVersions, function (uv) {
    var propagatedExactTransDeps =
      self._propagateExactTransDeps(uv, dependencies, constraints, choices);
    dependencies = propagatedExactTransDeps.dependencies;
    constraints = propagatedExactTransDeps.constraints;
    choices = propagatedExactTransDeps.choices;
  });

  if (options.stopAfterFirstPropagation)
    return choices;

  var pq = new PriorityQueue();

  var startState = {
    dependencies: dependencies,
    constraints: constraints,
    choices: choices
  };

  var opts = { rootDependencies: rootDependencies };
  var costFunction = options.costFunction;
  var estimateCostFunction = options.estimateCostFunction;

  pq.push(startState, [estimateCostFunction(startState, opts), 0]);

  var someError = null;
  var solution = null;
  while (! pq.empty()) {
    var currentState = pq.pop();
    var tentativeCost =
      costFunction(currentState.choices, opts) +
      estimateCostFunction(currentState, opts);

    if (tentativeCost === Infinity)
      break;

    if (_.isEmpty(currentState.dependencies)) {
      solution = currentState.choices;
      break;
    }

    var neighborsObj = self._stateNeighbors(currentState);

    if (! neighborsObj.success) {
      someError = someError || neighborsObj.failureMsg;
    } else {
      _.each(neighborsObj.neighbors, function (state) {
        var tentativeCost =
          costFunction(state.choices, opts) +
          estimateCostFunction(state, opts);

        pq.push(state, [tentativeCost, -state.choices.length]);
      });
    }
  }

  if (solution)
    return solution;

  // XXX should be much much better
  if (someError)
    throw new Error(someError);

  throw new Error("Couldn't resolve, I am sorry");
};

// dependencies: [String] - remaining dependencies
// constraints: [ConstraintSolver.Constraint] - constraints to satisfy
// choices: [ConstraintSolver.UnitVersion] - current fixed set of choices
//
// returns {
//   success: Boolean,
//   failureMsg: String,
//   choices: [ConstraintSolver.UnitVersion]
// }
//
// NOTE: assumes that exact dependencies are already propagated
ConstraintSolver.Resolver.prototype._stateNeighbors =
  function (state) {
  var self = this;

  var dependencies = state.dependencies;
  var constraints = state.constraints;
  var choices = state.choices;

  var candidateName = dependencies[0];
  dependencies = dependencies.slice(1);

  var candidateConstraints = _.filter(constraints, function (c) {
    return c.name === candidateName;
  });
  var candidateVersions =
    _.filter(self.unitsVersions[candidateName], function (uv) {
      return unitVersionDoesntValidateConstraints(uv, candidateConstraints);
    });

  if (_.isEmpty(candidateVersions))
    return { success: false,
             failureMsg: "Cannot choose satisfying versions of package -- "
                         + candidateName };

  var lastInvalidNeighbor = null;

  var neighbors = _.chain(candidateVersions).map(function (uv) {
    var nDependencies = _.clone(dependencies);
    var nConstraints = _.clone(constraints);
    var nChoices = _.clone(choices);

    nChoices.push(uv);
    var propagatedExactTransDeps =
      self._propagateExactTransDeps(uv, nDependencies, nConstraints, nChoices);

    nDependencies = propagatedExactTransDeps.dependencies;
    nConstraints = propagatedExactTransDeps.constraints;
    nChoices = propagatedExactTransDeps.choices;

    return {
      dependencies: nDependencies,
      constraints: nConstraints,
      choices: nChoices
    };
  }).filter(function (state) {
    var isValid =
      choicesDontValidateConstraints(state.choices, state.constraints);

    if (! isValid)
      lastInvalidNeighbor = state;

    return isValid;
  }).value();

  if (! neighbors.length)
    return { success: false,
             failureMsg: "None of the versions unit produces a sensible result -- "
               + candidateName,
             triedUnitVersions: candidateVersions,
             lastInvalidNeighbor: lastInvalidNeighbor };

  return { success: true, neighbors: neighbors };
};

// Propagates exact dependencies (depencies which have exact constraints) from
// the given unit version taking into account the existing set of dependencies
// and constraints.
// Assumes that the unit versions graph without passed unit version is already
// propagated (i.e. doesn't try to propagate anything not related to the passed
// unit version).
ConstraintSolver.Resolver.prototype._propagateExactTransDeps =
  function (uv, dependencies, constraints, choices) {
  var self = this;

  // XXX representing a queue as an array with push/shift operations is not
  // efficient as Array.shift is O(N). Replace if it becomes a problem.
  var queue = [];
  // Boolean map to avoid adding the same stuff to queue over and over again.
  // Keeps the time complexity the same but can save some memory.
  var isEnqueued = {};

  queue.push(uv);
  isEnqueued[uv.name] = true;

  while (queue.length > 0) {
    uv = queue[0];
    queue.shift();

    choices = _.union(choices, [uv]);

    var exactTransitiveDepsVersions =
      uv.exactTransitiveDependenciesVersions(self);
    var inexactTransitiveDeps = uv.inexactTransitiveDependencies(self);
    var transitiveConstraints = _.chain(exactTransitiveDepsVersions).union([uv])
      .map(function (uv) { return uv.constraints; }).flatten().uniq().value();

    dependencies = _.union(dependencies, inexactTransitiveDeps);
    constraints = _.union(constraints, transitiveConstraints);
    choices = _.union(choices, exactTransitiveDepsVersions);

    // Since exact transitive deps are put into choices, there is no need to
    // keep them in dependencies.
    dependencies = _.difference(dependencies, _.pluck(choices, "name"));

    // There could be new combination of exact constraint/dependency outgoing
    // from existing state and the new node.
    // XXX we don't need to look for all previously considered combinations.
    // Looking for newNode.dependencies+exact constraints and
    // newNode.exactConstraints+dependencies is enough.
    var exactDeps = _.chain(uv.dependencies).map(function (dep) {
      return _.find(constraints, function (c) {
        return c.name === uv.name && c.exact;
      });
    }).filter(_.identity).map(function (c) {
      return c.getSatisfyingUnitVersion(self);
    }).union(_.chain(uv.constraints).filter(function (c) {
      return c.exact;
    }).map(function (c) {
      return c.getSatisfyingUnitVersion(self);
    }).value()).difference(choices).value();

    // Enqueue all new exact dependencies.
    _.each(exactDeps, function (dep) {
      if (_.has(isEnqueued, dep.name))
        return;
      queue.push(dep);
      isEnqueued[dep.name] = true;
    });
  }

  return {
    dependencies: dependencies,
    constraints: constraints,
    choices: choices
  };
};

unitVersionDoesntValidateConstraints = function (uv, constraints) {
  return _.all(constraints, function (c) {
    return c.name !== uv.name || c.isSatisfied(uv);
  });
};

var choicesDontValidateConstraints = function (choices, constraints) {
  return _.all(choices, function (uv) {
    return unitVersionDoesntValidateConstraints(uv, constraints);
  });
};

////////////////////////////////////////////////////////////////////////////////
// UnitVersion
////////////////////////////////////////////////////////////////////////////////

ConstraintSolver.UnitVersion = function (name, unitVersion, ecv) {
  var self = this;

  check(name, String);
  check(unitVersion, String);
  check(ecv, String);
  check(self, ConstraintSolver.UnitVersion);

  self.name = name;
  self.version = unitVersion;
  // array of Strings - names of dependencies
  self.dependencies = [];
  // array of ConstraintSolver.Constraint's
  self.constraints = [];
  // a string in a form of "1.2.0"
  self.ecv = ecv;
};

_.extend(ConstraintSolver.UnitVersion.prototype, {
  addDependency: function (name) {
    var self = this;

    check(name, String);
    if (_.contains(self.dependencies, name))
      throw new Error("Dependency already exists -- " + name);
    self.dependencies.push(name);
  },
  addConstraint: function (constraint) {
    var self = this;

    check(constraint, ConstraintSolver.Constraint);
    if (_.contains(self.constraints, constraint))
      throw new Error("Constraint already exists -- " + constraint.toString());

    self.constraints.push(constraint);
  },
  exactConstraints: function () {
    var self = this;
    return _.filter(self.constraints, function (c) { return c.exact; });
  },
  looseConstraints: function () {
    var self = this;
    return _.filter(self.constraints, function (c) { return !c.exact; });
  },

  // Returns a list of transitive exact constraints, those could be found as
  // transitive dependencies.
  _exactTransitiveConstraints: function (resolver) {
    var self = this;

    // Get all dependencies we depend on and have constraints to pick an exact
    // version simultaneously as constraints.
    var exactDeps = _.filter(self.exactConstraints(), function (c) {
      return _.contains(self.dependencies, c.name);
    });

    // Merge all their's transitive exact dependencies
    var exactTransitiveConstraints = _.clone(exactDeps);

    _.each(exactDeps, function (c) {
      var unitVersion = c.getSatisfyingUnitVersion(resolver);
      // TODO: error handling in case a satisfying dependency wasn't found
      // xcxc
      if (!unitVersion)
        console.log("FAIL: ", c);

      // Collect the transitive dependencies of the direct exact dependencies.
      exactTransitiveConstraints = _.union(exactTransitiveConstraints,
                unitVersion._exactTransitiveConstraints(resolver));
    });

    return exactTransitiveConstraints;
  },

  exactTransitiveDependenciesVersions: function (resolver) {
    var self = this;
    return _.map(self._exactTransitiveConstraints(resolver), function (c) {
      return c.getSatisfyingUnitVersion(resolver);
    });
  },
  inexactTransitiveDependencies: function (resolver) {
    var self = this;
    var exactTransitiveConstraints = self._exactTransitiveConstraints(resolver);

    return _.chain(exactTransitiveConstraints).map(function (c) {
      var unitVersion = c.getSatisfyingUnitVersion(resolver);
      // TODO: error handling in case unitVersion wasn't found

      return unitVersion.dependencies;
    }).flatten().union(self.dependencies).uniq()
      .difference(_.pluck(exactTransitiveConstraints, "name")).value();
  },
  toString: function () {
    var self = this;
    return self.name + "@" + self.version;
  }
});

////////////////////////////////////////////////////////////////////////////////
// Constraint
////////////////////////////////////////////////////////////////////////////////

// Can be called either:
//    new PackageVersion.Constraint("packageA", "=2.1.0")
// or:
//    new PackageVersion.Constraint("pacakgeA@=2.1.0")
ConstraintSolver.Constraint = function (name, versionString) {
  var self = this;

  if (versionString) {
    _.extend(self, PackageVersion.parseVersionConstraint(versionString));
    self.name = name;
  } else {
    _.extend(self, PackageVersion.parseConstraint(name));
  }
};

ConstraintSolver.Constraint.prototype.toString = function () {
  var self = this;
  return self.name + "@" + (self.exact ? "=" : "") + self.version;
};

var semver = Npm.require('semver');

ConstraintSolver.Constraint.prototype.isSatisfied = function (unitVersion) {
  var self = this;
  check(unitVersion, ConstraintSolver.UnitVersion);

  if (self.exact)
    return self.version === unitVersion.version;

  return semver.lte(self.version, unitVersion.version) &&
    semver.lte(unitVersion.ecv, self.version);
};

// Returns any unit version satisfying the constraint in the resolver
ConstraintSolver.Constraint.prototype.getSatisfyingUnitVersion =
  function (resolver) {
  var self = this;
  var unitVersion = _.find(resolver.unitsVersions[self.name],
                           _.bind(self.isSatisfied, self));
  return unitVersion;
};
<commit_msg>Formatting fix<commit_after>////////////////////////////////////////////////////////////////////////////////
// Resolver
////////////////////////////////////////////////////////////////////////////////

// XXX the whole resolver heavily relies on these statements to be true:
// - every unit version ever used was added to the resolver with addUnitVersion
// - every constraint ever used was instantiated with getConstraint
// - every constraint was added exactly once
// - every unit version was added exactly once
// - if two unit versions are the same, their refs point at the same object
// - if two constraints are the same, their refs point at the same object
ConstraintSolver.Resolver = function () {
  var self = this;

  // Maps unit name string to an array of version definitions
  self.unitsVersions = {};

  // Maps unit name string to the greatest version string we have
  self._latestVersion = {};

  // Refs to all constraints. Mapping String -> instance
  self._constraints = {};
};

ConstraintSolver.Resolver.prototype.addUnitVersion = function (unitVersion) {
  var self = this;

  check(unitVersion, ConstraintSolver.UnitVersion);

  if (! _.has(self.unitsVersions, unitVersion.name)) {
    self.unitsVersions[unitVersion.name] = [];
    self._latestVersion[unitVersion.name] = unitVersion.version;
  }

  self.unitsVersions[unitVersion.name].push(unitVersion);

  if (semver.lt(self._latestVersion[unitVersion.name], unitVersion.version))
    self._latestVersion[unitVersion.name] = unitVersion.version;
};

// name - String - "someUnit"
// versionConstraint - String - "=1.2.3" or "2.1.0"
ConstraintSolver.Resolver.prototype.getConstraint =
  function (name, versionConstraint) {
  var self = this;

  check(name, String);
  check(versionConstraint, String);

  var idString = JSON.stringify([name, versionConstraint]);

  if (_.has(self._constraints, idString))
    return self._constraints[idString];

  return self._constraints[idString] =
    new ConstraintSolver.Constraint(name, versionConstraint);
};

ConstraintSolver.Resolver.prototype.resolve =
  function (dependencies, constraints, choices, options) {
  var self = this;

  constraints = constraints || [];
  choices = choices || [];
  options = _.extend({
    costFunction: function (choices) { return 0; },
    estimateCostFunction: function (state) {
      return 0;
    }
  }, options);

  dependencies = _.uniq(dependencies);
  constraints = _.uniq(constraints);

  var rootDependencies = _.clone(dependencies);

  var exactDepsConstraints = _.filter(constraints, function (c) {
    return c.exact && _.contains(dependencies, c.name);
  });

  var exactDepsVersions = _.map(exactDepsConstraints, function (c) {
    return c.getSatisfyingUnitVersion(self);
  });

  var exactDepsNames = _.pluck(exactDepsVersions, "name");

  // Remove them from dependencies.
  dependencies = _.difference(dependencies, exactDepsNames);

  // Take exact dependencies and propagate them.
  // Will also pick these versions into choices as we have no choice but take
  // them.
  _.each(exactDepsVersions, function (uv) {
    var propagatedExactTransDeps =
      self._propagateExactTransDeps(uv, dependencies, constraints, choices);
    dependencies = propagatedExactTransDeps.dependencies;
    constraints = propagatedExactTransDeps.constraints;
    choices = propagatedExactTransDeps.choices;
  });

  if (options.stopAfterFirstPropagation)
    return choices;

  var pq = new PriorityQueue();

  var startState = {
    dependencies: dependencies,
    constraints: constraints,
    choices: choices
  };

  var opts = { rootDependencies: rootDependencies };
  var costFunction = options.costFunction;
  var estimateCostFunction = options.estimateCostFunction;

  pq.push(startState, [estimateCostFunction(startState, opts), 0]);

  var someError = null;
  var solution = null;
  while (! pq.empty()) {
    var currentState = pq.pop();
    var tentativeCost =
      costFunction(currentState.choices, opts) +
      estimateCostFunction(currentState, opts);

    if (tentativeCost === Infinity)
      break;

    if (_.isEmpty(currentState.dependencies)) {
      solution = currentState.choices;
      break;
    }

    var neighborsObj = self._stateNeighbors(currentState);

    if (! neighborsObj.success) {
      someError = someError || neighborsObj.failureMsg;
    } else {
      _.each(neighborsObj.neighbors, function (state) {
        var tentativeCost =
          costFunction(state.choices, opts) +
          estimateCostFunction(state, opts);

        pq.push(state, [tentativeCost, -state.choices.length]);
      });
    }
  }

  if (solution)
    return solution;

  // XXX should be much much better
  if (someError)
    throw new Error(someError);

  throw new Error("Couldn't resolve, I am sorry");
};

// dependencies: [String] - remaining dependencies
// constraints: [ConstraintSolver.Constraint] - constraints to satisfy
// choices: [ConstraintSolver.UnitVersion] - current fixed set of choices
//
// returns {
//   success: Boolean,
//   failureMsg: String,
//   choices: [ConstraintSolver.UnitVersion]
// }
//
// NOTE: assumes that exact dependencies are already propagated
ConstraintSolver.Resolver.prototype._stateNeighbors =
  function (state) {
  var self = this;

  var dependencies = state.dependencies;
  var constraints = state.constraints;
  var choices = state.choices;

  var candidateName = dependencies[0];
  dependencies = dependencies.slice(1);

  var candidateConstraints = _.filter(constraints, function (c) {
    return c.name === candidateName;
  });
  var candidateVersions =
    _.filter(self.unitsVersions[candidateName], function (uv) {
      return unitVersionDoesntValidateConstraints(uv, candidateConstraints);
    });

  if (_.isEmpty(candidateVersions))
    return { success: false,
             failureMsg: "Cannot choose satisfying versions of package -- "
                         + candidateName };

  var lastInvalidNeighbor = null;

  var neighbors = _.chain(candidateVersions).map(function (uv) {
    var nDependencies = _.clone(dependencies);
    var nConstraints = _.clone(constraints);
    var nChoices = _.clone(choices);

    nChoices.push(uv);
    var propagatedExactTransDeps =
      self._propagateExactTransDeps(uv, nDependencies, nConstraints, nChoices);

    nDependencies = propagatedExactTransDeps.dependencies;
    nConstraints = propagatedExactTransDeps.constraints;
    nChoices = propagatedExactTransDeps.choices;

    return {
      dependencies: nDependencies,
      constraints: nConstraints,
      choices: nChoices
    };
  }).filter(function (state) {
    var isValid =
      choicesDontValidateConstraints(state.choices, state.constraints);

    if (! isValid)
      lastInvalidNeighbor = state;

    return isValid;
  }).value();

  if (! neighbors.length)
    return { success: false,
             failureMsg: "None of the versions unit produces a sensible result -- "
               + candidateName,
             triedUnitVersions: candidateVersions,
             lastInvalidNeighbor: lastInvalidNeighbor };

  return { success: true, neighbors: neighbors };
};

// Propagates exact dependencies (depencies which have exact constraints) from
// the given unit version taking into account the existing set of dependencies
// and constraints.
// Assumes that the unit versions graph without passed unit version is already
// propagated (i.e. doesn't try to propagate anything not related to the passed
// unit version).
ConstraintSolver.Resolver.prototype._propagateExactTransDeps =
  function (uv, dependencies, constraints, choices) {
  var self = this;

  // XXX representing a queue as an array with push/shift operations is not
  // efficient as Array.shift is O(N). Replace if it becomes a problem.
  var queue = [];
  // Boolean map to avoid adding the same stuff to queue over and over again.
  // Keeps the time complexity the same but can save some memory.
  var isEnqueued = {};

  queue.push(uv);
  isEnqueued[uv.name] = true;

  while (queue.length > 0) {
    uv = queue[0];
    queue.shift();

    choices = _.union(choices, [uv]);

    var exactTransitiveDepsVersions =
      uv.exactTransitiveDependenciesVersions(self);
    var inexactTransitiveDeps = uv.inexactTransitiveDependencies(self);
    var transitiveConstraints = _.chain(exactTransitiveDepsVersions).union([uv])
      .map(function (uv) { return uv.constraints; }).flatten().uniq().value();

    dependencies = _.union(dependencies, inexactTransitiveDeps);
    constraints = _.union(constraints, transitiveConstraints);
    choices = _.union(choices, exactTransitiveDepsVersions);

    // Since exact transitive deps are put into choices, there is no need to
    // keep them in dependencies.
    dependencies = _.difference(dependencies, _.pluck(choices, "name"));

    // There could be new combination of exact constraint/dependency outgoing
    // from existing state and the new node.
    // We don't need to look for all previously considered combinations.
    // Looking for newNode.dependencies+exact constraints and
    // newNode.exactConstraints+dependencies is enough.
    var exactDeps = _.chain(uv.dependencies).map(function (dep) {
      return _.find(constraints, function (c) {
        return c.name === uv.name && c.exact;
      });
    }).filter(_.identity).map(function (c) {
      return c.getSatisfyingUnitVersion(self);
    }).union(_.chain(uv.constraints).filter(function (c) { return c.exact; })
              .map(function (c) { return c.getSatisfyingUnitVersion(self); })
              .value()
            ).difference(choices).value();

    // Enqueue all new exact dependencies.
    _.each(exactDeps, function (dep) {
      if (_.has(isEnqueued, dep.name))
        return;
      queue.push(dep);
      isEnqueued[dep.name] = true;
    });
  }

  return {
    dependencies: dependencies,
    constraints: constraints,
    choices: choices
  };
};

unitVersionDoesntValidateConstraints = function (uv, constraints) {
  return _.all(constraints, function (c) {
    return c.name !== uv.name || c.isSatisfied(uv);
  });
};

var choicesDontValidateConstraints = function (choices, constraints) {
  return _.all(choices, function (uv) {
    return unitVersionDoesntValidateConstraints(uv, constraints);
  });
};

////////////////////////////////////////////////////////////////////////////////
// UnitVersion
////////////////////////////////////////////////////////////////////////////////

ConstraintSolver.UnitVersion = function (name, unitVersion, ecv) {
  var self = this;

  check(name, String);
  check(unitVersion, String);
  check(ecv, String);
  check(self, ConstraintSolver.UnitVersion);

  self.name = name;
  self.version = unitVersion;
  // array of Strings - names of dependencies
  self.dependencies = [];
  // array of ConstraintSolver.Constraint's
  self.constraints = [];
  // a string in a form of "1.2.0"
  self.ecv = ecv;
};

_.extend(ConstraintSolver.UnitVersion.prototype, {
  addDependency: function (name) {
    var self = this;

    check(name, String);
    if (_.contains(self.dependencies, name))
      throw new Error("Dependency already exists -- " + name);
    self.dependencies.push(name);
  },
  addConstraint: function (constraint) {
    var self = this;

    check(constraint, ConstraintSolver.Constraint);
    if (_.contains(self.constraints, constraint))
      throw new Error("Constraint already exists -- " + constraint.toString());

    self.constraints.push(constraint);
  },
  exactConstraints: function () {
    var self = this;
    return _.filter(self.constraints, function (c) { return c.exact; });
  },
  looseConstraints: function () {
    var self = this;
    return _.filter(self.constraints, function (c) { return !c.exact; });
  },

  // Returns a list of transitive exact constraints, those could be found as
  // transitive dependencies.
  _exactTransitiveConstraints: function (resolver) {
    var self = this;

    // Get all dependencies we depend on and have constraints to pick an exact
    // version simultaneously as constraints.
    var exactDeps = _.filter(self.exactConstraints(), function (c) {
      return _.contains(self.dependencies, c.name);
    });

    // Merge all their's transitive exact dependencies
    var exactTransitiveConstraints = _.clone(exactDeps);

    _.each(exactDeps, function (c) {
      var unitVersion = c.getSatisfyingUnitVersion(resolver);
      // TODO: error handling in case a satisfying dependency wasn't found
      // xcxc
      if (!unitVersion)
        console.log("FAIL: ", c);

      // Collect the transitive dependencies of the direct exact dependencies.
      exactTransitiveConstraints = _.union(exactTransitiveConstraints,
                unitVersion._exactTransitiveConstraints(resolver));
    });

    return exactTransitiveConstraints;
  },

  exactTransitiveDependenciesVersions: function (resolver) {
    var self = this;
    return _.map(self._exactTransitiveConstraints(resolver), function (c) {
      return c.getSatisfyingUnitVersion(resolver);
    });
  },
  inexactTransitiveDependencies: function (resolver) {
    var self = this;
    var exactTransitiveConstraints = self._exactTransitiveConstraints(resolver);

    return _.chain(exactTransitiveConstraints).map(function (c) {
      var unitVersion = c.getSatisfyingUnitVersion(resolver);
      // TODO: error handling in case unitVersion wasn't found

      return unitVersion.dependencies;
    }).flatten().union(self.dependencies).uniq()
      .difference(_.pluck(exactTransitiveConstraints, "name")).value();
  },
  toString: function () {
    var self = this;
    return self.name + "@" + self.version;
  }
});

////////////////////////////////////////////////////////////////////////////////
// Constraint
////////////////////////////////////////////////////////////////////////////////

// Can be called either:
//    new PackageVersion.Constraint("packageA", "=2.1.0")
// or:
//    new PackageVersion.Constraint("pacakgeA@=2.1.0")
ConstraintSolver.Constraint = function (name, versionString) {
  var self = this;

  if (versionString) {
    _.extend(self, PackageVersion.parseVersionConstraint(versionString));
    self.name = name;
  } else {
    _.extend(self, PackageVersion.parseConstraint(name));
  }
};

ConstraintSolver.Constraint.prototype.toString = function () {
  var self = this;
  return self.name + "@" + (self.exact ? "=" : "") + self.version;
};

var semver = Npm.require('semver');

ConstraintSolver.Constraint.prototype.isSatisfied = function (unitVersion) {
  var self = this;
  check(unitVersion, ConstraintSolver.UnitVersion);

  if (self.exact)
    return self.version === unitVersion.version;

  return semver.lte(self.version, unitVersion.version) &&
    semver.lte(unitVersion.ecv, self.version);
};

// Returns any unit version satisfying the constraint in the resolver
ConstraintSolver.Constraint.prototype.getSatisfyingUnitVersion =
  function (resolver) {
  var self = this;
  var unitVersion = _.find(resolver.unitsVersions[self.name],
                           _.bind(self.isSatisfied, self));
  return unitVersion;
};
<|endoftext|>


<commit_before>// ==========================================================================
// Project:  Ember Metal
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================
/*globals ember_assert */

require('ember-metal/core');
require('ember-metal/platform');
require('ember-metal/utils');
require('ember-metal/accessors');

var USE_ACCESSORS = Ember.USE_ACCESSORS;
var GUID_KEY = Ember.GUID_KEY;
var META_KEY = Ember.META_KEY;
var meta = Ember.meta;
var o_create = Ember.platform.create;
var o_defineProperty = Ember.platform.defineProperty;
var SIMPLE_PROPERTY, WATCHED_PROPERTY;

// ..........................................................
// DESCRIPTOR
//

var SIMPLE_DESC = {
  writable: true,
  configurable: true,
  enumerable: true,
  value: null
};

/**
  @private
  @constructor

  Objects of this type can implement an interface to responds requests to
  get and set.  The default implementation handles simple properties.

  You generally won't need to create or subclass this directly.
*/
var Dc = Ember.Descriptor = function() {};

var setup = Dc.setup = function(obj, keyName, value) {
  SIMPLE_DESC.value = value;
  o_defineProperty(obj, keyName, SIMPLE_DESC);
  SIMPLE_DESC.value = null;
};

var Dp = Ember.Descriptor.prototype;

/**
  Called whenever we want to set the property value.  Should set the value
  and return the actual set value (which is usually the same but may be
  different in the case of computed properties.)

  @param {Object} obj
    The object to set the value on.

  @param {String} keyName
    The key to set.

  @param {Object} value
    The new value

  @returns {Object} value actual set value
*/
Dp.set = function(obj, keyName, value) {
  obj[keyName] = value;
  return value;
};

/**
  Called whenever we want to get the property value.  Should retrieve the
  current value.

  @param {Object} obj
    The object to get the value on.

  @param {String} keyName
    The key to retrieve

  @returns {Object} the current value
*/
Dp.get = function(obj, keyName) {
  return w_get(obj, keyName, obj);
};

/**
  This is called on the descriptor to set it up on the object.  The
  descriptor is responsible for actually defining the property on the object
  here.

  The passed `value` is the transferValue returned from any previous
  descriptor.

  @param {Object} obj
    The object to set the value on.

  @param {String} keyName
    The key to set.

  @param {Object} value
    The transfer value from any previous descriptor.

  @returns {void}
*/
Dp.setup = setup;

/**
  This is called on the descriptor just before another descriptor takes its
  place.  This method should at least return the 'transfer value' of the
  property - which is the value you want to passed as the input to the new
  descriptor's setup() method.

  It is not generally necessary to actually 'undefine' the property as a new
  property descriptor will redefine it immediately after this method returns.

  @param {Object} obj
    The object to set the value on.

  @param {String} keyName
    The key to set.

  @returns {Object} transfer value
*/
Dp.teardown = function(obj, keyName) {
  return obj[keyName];
};

Dp.val = function(obj, keyName) {
  return obj[keyName];
};

// ..........................................................
// SIMPLE AND WATCHED PROPERTIES
//

// if accessors are disabled for the app then this will act as a guard when
// testing on browsers that do support accessors.  It will throw an exception
// if you do foo.bar instead of Ember.get(foo, 'bar')

// The exception to this is that any objects managed by Ember but not a descendant
// of Ember.Object will not throw an exception, instead failing silently. This
// prevent errors with other libraries that may attempt to access special
// properties on standard objects like Array. Usually this happens when copying
// an object by looping over all properties.

if (!USE_ACCESSORS) {
  Ember.Descriptor.MUST_USE_GETTER = function() {
    if (this instanceof Ember.Object) {
      ember_assert('Must use Ember.get() to access this property', false);
    }
  };

  Ember.Descriptor.MUST_USE_SETTER = function() {
    if (this instanceof Ember.Object) {
      if (this.isDestroyed) {
        ember_assert('You cannot set observed properties on destroyed objects', false);
      } else {
        ember_assert('Must use Ember.set() to access this property', false);
      }
    }
  };
}

var WATCHED_DESC = {
  configurable: true,
  enumerable:   true,
  set: Ember.Descriptor.MUST_USE_SETTER
};

function w_get(obj, keyName, values) {
  values = values || meta(obj, false).values;

  if (values) {
    var ret = values[keyName];
    if (ret !== undefined) { return ret; }
    if (obj.unknownProperty) { return obj.unknownProperty(keyName); }
  }

}

function w_set(obj, keyName, value) {
  var m = meta(obj), watching;

  watching = m.watching[keyName]>0 && value!==m.values[keyName];
  if (watching) Ember.propertyWillChange(obj, keyName);
  m.values[keyName] = value;
  if (watching) Ember.propertyDidChange(obj, keyName);
  return value;
}

var WATCHED_GETTERS = {};
function mkWatchedGetter(keyName) {
  var ret = WATCHED_GETTERS[keyName];
  if (!ret) {
    ret = WATCHED_GETTERS[keyName] = function() {
      return w_get(this, keyName);
    };
  }
  return ret;
}

var WATCHED_SETTERS = {};
function mkWatchedSetter(keyName) {
  var ret = WATCHED_SETTERS[keyName];
  if (!ret) {
    ret = WATCHED_SETTERS[keyName] = function(value) {
      return w_set(this, keyName, value);
    };
  }
  return ret;
}

/**
  @private

  Private version of simple property that invokes property change callbacks.
*/
WATCHED_PROPERTY = new Ember.Descriptor();

if (Ember.platform.hasPropertyAccessors) {
  WATCHED_PROPERTY.get = w_get ;
  WATCHED_PROPERTY.set = w_set ;

  if (USE_ACCESSORS) {
    WATCHED_PROPERTY.setup = function(obj, keyName, value) {
      WATCHED_DESC.get = mkWatchedGetter(keyName);
      WATCHED_DESC.set = mkWatchedSetter(keyName);
      o_defineProperty(obj, keyName, WATCHED_DESC);
      WATCHED_DESC.get = WATCHED_DESC.set = null;
      if (value !== undefined) meta(obj).values[keyName] = value;
    };

  } else {
    WATCHED_PROPERTY.setup = function(obj, keyName, value) {
      WATCHED_DESC.get = mkWatchedGetter(keyName);
      o_defineProperty(obj, keyName, WATCHED_DESC);
      WATCHED_DESC.get = null;
      if (value !== undefined) meta(obj).values[keyName] = value;
    };
  }

  WATCHED_PROPERTY.teardown = function(obj, keyName) {
    var ret = meta(obj).values[keyName];
    delete meta(obj).values[keyName];
    return ret;
  };

// NOTE: if platform does not have property accessors then we just have to
// set values and hope for the best.  You just won't get any warnings...
} else {

  WATCHED_PROPERTY.set = function(obj, keyName, value) {
    var m = meta(obj), watching;

    watching = m.watching[keyName]>0 && value!==obj[keyName];
    if (watching) Ember.propertyWillChange(obj, keyName);
    obj[keyName] = value;
    if (watching) Ember.propertyDidChange(obj, keyName);
    return value;
  };

}

/**
  The default descriptor for simple properties.  Pass as the third argument
  to Ember.defineProperty() along with a value to set a simple value.

  @static
  @default Ember.Descriptor
*/
Ember.SIMPLE_PROPERTY = new Ember.Descriptor();
SIMPLE_PROPERTY = Ember.SIMPLE_PROPERTY;

SIMPLE_PROPERTY.unwatched = WATCHED_PROPERTY.unwatched = SIMPLE_PROPERTY;
SIMPLE_PROPERTY.watched   = WATCHED_PROPERTY.watched   = WATCHED_PROPERTY;

// ..........................................................
// DEFINING PROPERTIES API
//

function hasDesc(descs, keyName) {
  if (keyName === 'toString') return 'function' !== typeof descs.toString;
  else return !!descs[keyName];
}

/**
  @private

  NOTE: This is a low-level method used by other parts of the API.  You almost
  never want to call this method directly.  Instead you should use Ember.mixin()
  to define new properties.

  Defines a property on an object.  This method works much like the ES5
  Object.defineProperty() method except that it can also accept computed
  properties and other special descriptors.

  Normally this method takes only three parameters.  However if you pass an
  instance of Ember.Descriptor as the third param then you can pass an optional
  value as the fourth parameter.  This is often more efficient than creating
  new descriptor hashes for each property.

  ## Examples

      // ES5 compatible mode
      Ember.defineProperty(contact, 'firstName', {
        writable: true,
        configurable: false,
        enumerable: true,
        value: 'Charles'
      });

      // define a simple property
      Ember.defineProperty(contact, 'lastName', Ember.SIMPLE_PROPERTY, 'Jolley');

      // define a computed property
      Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
        return this.firstName+' '+this.lastName;
      }).property('firstName', 'lastName').cacheable());
*/
Ember.defineProperty = function(obj, keyName, desc, val) {
  var m = meta(obj, false), descs = m.descs, watching = m.watching[keyName]>0;

  if (val === undefined) {
    val = hasDesc(descs, keyName) ? descs[keyName].teardown(obj, keyName) : obj[keyName];
  } else if (hasDesc(descs, keyName)) {
    descs[keyName].teardown(obj, keyName);
  }

  if (!desc) desc = SIMPLE_PROPERTY;

  if (desc instanceof Ember.Descriptor) {
    m = meta(obj, true);
    descs = m.descs;

    desc = (watching ? desc.watched : desc.unwatched) || desc;
    descs[keyName] = desc;
    desc.setup(obj, keyName, val, watching);

  // compatibility with ES5
  } else {
    if (descs[keyName]) meta(obj).descs[keyName] = null;
    o_defineProperty(obj, keyName, desc);
  }

  // if key is being watched, override chains that
  // were initialized with the prototype
  if (watching) Ember.overrideChains(obj, keyName, m);

  return this;
};

/**
  Creates a new object using the passed object as its prototype.  On browsers
  that support it, this uses the built in Object.create method.  Else one is
  simulated for you.

  This method is a better choice thant Object.create() because it will make
  sure that any observers, event listeners, and computed properties are
  inherited from the parent as well.

  @param {Object} obj
    The object you want to have as the prototype.

  @returns {Object} the newly created object
*/
Ember.create = function(obj, props) {
  var ret = o_create(obj, props);
  if (GUID_KEY in ret) Ember.generateGuid(ret, 'ember');
  if (META_KEY in ret) Ember.rewatch(ret); // setup watch chains if needed.
  return ret;
};

/**
  @private

  Creates a new object using the passed object as its prototype.  This method
  acts like `Ember.create()` in every way except that bindings, observers, and
  computed properties will be activated on the object.

  The purpose of this method is to build an object for use in a prototype
  chain. (i.e. to be set as the `prototype` property on a constructor
  function).  Prototype objects need to inherit bindings, observers and
  other configuration so they pass it on to their children.  However since
  they are never 'live' objects themselves, they should not fire or make
  other changes when various properties around them change.

  You should use this method anytime you want to create a new object for use
  in a prototype chain.

  @param {Object} obj
    The base object.

  @param {Object} hash
    Optional hash of properties to define on the object.

  @returns {Object} new object
*/
Ember.createPrototype = function(obj, props) {
  var ret = o_create(obj, props);
  meta(ret, true).proto = ret;
  if (GUID_KEY in ret) Ember.generateGuid(ret, 'ember');
  if (META_KEY in ret) Ember.rewatch(ret); // setup watch chains if needed.
  return ret;
};
<commit_msg>fix problem when defineProperty is just redefining an existing property as in the case of Ember.watch<commit_after>// ==========================================================================
// Project:  Ember Metal
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================
/*globals ember_assert */

require('ember-metal/core');
require('ember-metal/platform');
require('ember-metal/utils');
require('ember-metal/accessors');

var USE_ACCESSORS = Ember.USE_ACCESSORS;
var GUID_KEY = Ember.GUID_KEY;
var META_KEY = Ember.META_KEY;
var meta = Ember.meta;
var o_create = Ember.platform.create;
var o_defineProperty = Ember.platform.defineProperty;
var SIMPLE_PROPERTY, WATCHED_PROPERTY;

// ..........................................................
// DESCRIPTOR
//

var SIMPLE_DESC = {
  writable: true,
  configurable: true,
  enumerable: true,
  value: null
};

/**
  @private
  @constructor

  Objects of this type can implement an interface to responds requests to
  get and set.  The default implementation handles simple properties.

  You generally won't need to create or subclass this directly.
*/
var Dc = Ember.Descriptor = function() {};

var setup = Dc.setup = function(obj, keyName, value) {
  SIMPLE_DESC.value = value;
  o_defineProperty(obj, keyName, SIMPLE_DESC);
  SIMPLE_DESC.value = null;
};

var Dp = Ember.Descriptor.prototype;

/**
  Called whenever we want to set the property value.  Should set the value
  and return the actual set value (which is usually the same but may be
  different in the case of computed properties.)

  @param {Object} obj
    The object to set the value on.

  @param {String} keyName
    The key to set.

  @param {Object} value
    The new value

  @returns {Object} value actual set value
*/
Dp.set = function(obj, keyName, value) {
  obj[keyName] = value;
  return value;
};

/**
  Called whenever we want to get the property value.  Should retrieve the
  current value.

  @param {Object} obj
    The object to get the value on.

  @param {String} keyName
    The key to retrieve

  @returns {Object} the current value
*/
Dp.get = function(obj, keyName) {
  return w_get(obj, keyName, obj);
};

/**
  This is called on the descriptor to set it up on the object.  The
  descriptor is responsible for actually defining the property on the object
  here.

  The passed `value` is the transferValue returned from any previous
  descriptor.

  @param {Object} obj
    The object to set the value on.

  @param {String} keyName
    The key to set.

  @param {Object} value
    The transfer value from any previous descriptor.

  @returns {void}
*/
Dp.setup = setup;

/**
  This is called on the descriptor just before another descriptor takes its
  place.  This method should at least return the 'transfer value' of the
  property - which is the value you want to passed as the input to the new
  descriptor's setup() method.

  It is not generally necessary to actually 'undefine' the property as a new
  property descriptor will redefine it immediately after this method returns.

  @param {Object} obj
    The object to set the value on.

  @param {String} keyName
    The key to set.

  @returns {Object} transfer value
*/
Dp.teardown = function(obj, keyName) {
  return obj[keyName];
};

Dp.val = function(obj, keyName) {
  return obj[keyName];
};

// ..........................................................
// SIMPLE AND WATCHED PROPERTIES
//

// if accessors are disabled for the app then this will act as a guard when
// testing on browsers that do support accessors.  It will throw an exception
// if you do foo.bar instead of Ember.get(foo, 'bar')

// The exception to this is that any objects managed by Ember but not a descendant
// of Ember.Object will not throw an exception, instead failing silently. This
// prevent errors with other libraries that may attempt to access special
// properties on standard objects like Array. Usually this happens when copying
// an object by looping over all properties.

if (!USE_ACCESSORS) {
  Ember.Descriptor.MUST_USE_GETTER = function() {
    if (this instanceof Ember.Object) {
      ember_assert('Must use Ember.get() to access this property', false);
    }
  };

  Ember.Descriptor.MUST_USE_SETTER = function() {
    if (this instanceof Ember.Object) {
      if (this.isDestroyed) {
        ember_assert('You cannot set observed properties on destroyed objects', false);
      } else {
        ember_assert('Must use Ember.set() to access this property', false);
      }
    }
  };
}

var WATCHED_DESC = {
  configurable: true,
  enumerable:   true,
  set: Ember.Descriptor.MUST_USE_SETTER
};

function w_get(obj, keyName, values) {
  values = values || meta(obj, false).values;

  if (values) {
    var ret = values[keyName];
    if (ret !== undefined) { return ret; }
    if (obj.unknownProperty) { return obj.unknownProperty(keyName); }
  }

}

function w_set(obj, keyName, value) {
  var m = meta(obj), watching;

  watching = m.watching[keyName]>0 && value!==m.values[keyName];
  if (watching) Ember.propertyWillChange(obj, keyName);
  m.values[keyName] = value;
  if (watching) Ember.propertyDidChange(obj, keyName);
  return value;
}

var WATCHED_GETTERS = {};
function mkWatchedGetter(keyName) {
  var ret = WATCHED_GETTERS[keyName];
  if (!ret) {
    ret = WATCHED_GETTERS[keyName] = function() {
      return w_get(this, keyName);
    };
  }
  return ret;
}

var WATCHED_SETTERS = {};
function mkWatchedSetter(keyName) {
  var ret = WATCHED_SETTERS[keyName];
  if (!ret) {
    ret = WATCHED_SETTERS[keyName] = function(value) {
      return w_set(this, keyName, value);
    };
  }
  return ret;
}

/**
  @private

  Private version of simple property that invokes property change callbacks.
*/
WATCHED_PROPERTY = new Ember.Descriptor();

if (Ember.platform.hasPropertyAccessors) {
  WATCHED_PROPERTY.get = w_get ;
  WATCHED_PROPERTY.set = w_set ;

  if (USE_ACCESSORS) {
    WATCHED_PROPERTY.setup = function(obj, keyName, value) {
      WATCHED_DESC.get = mkWatchedGetter(keyName);
      WATCHED_DESC.set = mkWatchedSetter(keyName);
      o_defineProperty(obj, keyName, WATCHED_DESC);
      WATCHED_DESC.get = WATCHED_DESC.set = null;
      if (value !== undefined) meta(obj).values[keyName] = value;
    };

  } else {
    WATCHED_PROPERTY.setup = function(obj, keyName, value) {
      WATCHED_DESC.get = mkWatchedGetter(keyName);
      o_defineProperty(obj, keyName, WATCHED_DESC);
      WATCHED_DESC.get = null;
      if (value !== undefined) meta(obj).values[keyName] = value;
    };
  }

  WATCHED_PROPERTY.teardown = function(obj, keyName) {
    var ret = meta(obj).values[keyName];
    delete meta(obj).values[keyName];
    return ret;
  };

// NOTE: if platform does not have property accessors then we just have to
// set values and hope for the best.  You just won't get any warnings...
} else {

  WATCHED_PROPERTY.set = function(obj, keyName, value) {
    var m = meta(obj), watching;

    watching = m.watching[keyName]>0 && value!==obj[keyName];
    if (watching) Ember.propertyWillChange(obj, keyName);
    obj[keyName] = value;
    if (watching) Ember.propertyDidChange(obj, keyName);
    return value;
  };

}

/**
  The default descriptor for simple properties.  Pass as the third argument
  to Ember.defineProperty() along with a value to set a simple value.

  @static
  @default Ember.Descriptor
*/
Ember.SIMPLE_PROPERTY = new Ember.Descriptor();
SIMPLE_PROPERTY = Ember.SIMPLE_PROPERTY;

SIMPLE_PROPERTY.unwatched = WATCHED_PROPERTY.unwatched = SIMPLE_PROPERTY;
SIMPLE_PROPERTY.watched   = WATCHED_PROPERTY.watched   = WATCHED_PROPERTY;

// ..........................................................
// DEFINING PROPERTIES API
//

function hasDesc(descs, keyName) {
  if (keyName === 'toString') return 'function' !== typeof descs.toString;
  else return !!descs[keyName];
}

/**
  @private

  NOTE: This is a low-level method used by other parts of the API.  You almost
  never want to call this method directly.  Instead you should use Ember.mixin()
  to define new properties.

  Defines a property on an object.  This method works much like the ES5
  Object.defineProperty() method except that it can also accept computed
  properties and other special descriptors.

  Normally this method takes only three parameters.  However if you pass an
  instance of Ember.Descriptor as the third param then you can pass an optional
  value as the fourth parameter.  This is often more efficient than creating
  new descriptor hashes for each property.

  ## Examples

      // ES5 compatible mode
      Ember.defineProperty(contact, 'firstName', {
        writable: true,
        configurable: false,
        enumerable: true,
        value: 'Charles'
      });

      // define a simple property
      Ember.defineProperty(contact, 'lastName', Ember.SIMPLE_PROPERTY, 'Jolley');

      // define a computed property
      Ember.defineProperty(contact, 'fullName', Ember.computed(function() {
        return this.firstName+' '+this.lastName;
      }).property('firstName', 'lastName').cacheable());
*/
Ember.defineProperty = function(obj, keyName, desc, val) {
  var m = meta(obj, false), descs = m.descs, watching = m.watching[keyName]>0, override = true;

  if (val === undefined) {
    override = false;
    val = hasDesc(descs, keyName) ? descs[keyName].teardown(obj, keyName) : obj[keyName];
  } else if (hasDesc(descs, keyName)) {
    descs[keyName].teardown(obj, keyName);
  }

  if (!desc) desc = SIMPLE_PROPERTY;

  if (desc instanceof Ember.Descriptor) {
    m = meta(obj, true);
    descs = m.descs;

    desc = (watching ? desc.watched : desc.unwatched) || desc;
    descs[keyName] = desc;
    desc.setup(obj, keyName, val, watching);

  // compatibility with ES5
  } else {
    if (descs[keyName]) meta(obj).descs[keyName] = null;
    o_defineProperty(obj, keyName, desc);
  }

  // if key is being watched, override chains that
  // were initialized with the prototype
  if (override && watching) Ember.overrideChains(obj, keyName, m);

  return this;
};

/**
  Creates a new object using the passed object as its prototype.  On browsers
  that support it, this uses the built in Object.create method.  Else one is
  simulated for you.

  This method is a better choice thant Object.create() because it will make
  sure that any observers, event listeners, and computed properties are
  inherited from the parent as well.

  @param {Object} obj
    The object you want to have as the prototype.

  @returns {Object} the newly created object
*/
Ember.create = function(obj, props) {
  var ret = o_create(obj, props);
  if (GUID_KEY in ret) Ember.generateGuid(ret, 'ember');
  if (META_KEY in ret) Ember.rewatch(ret); // setup watch chains if needed.
  return ret;
};

/**
  @private

  Creates a new object using the passed object as its prototype.  This method
  acts like `Ember.create()` in every way except that bindings, observers, and
  computed properties will be activated on the object.

  The purpose of this method is to build an object for use in a prototype
  chain. (i.e. to be set as the `prototype` property on a constructor
  function).  Prototype objects need to inherit bindings, observers and
  other configuration so they pass it on to their children.  However since
  they are never 'live' objects themselves, they should not fire or make
  other changes when various properties around them change.

  You should use this method anytime you want to create a new object for use
  in a prototype chain.

  @param {Object} obj
    The base object.

  @param {Object} hash
    Optional hash of properties to define on the object.

  @returns {Object} new object
*/
Ember.createPrototype = function(obj, props) {
  var ret = o_create(obj, props);
  meta(ret, true).proto = ret;
  if (GUID_KEY in ret) Ember.generateGuid(ret, 'ember');
  if (META_KEY in ret) Ember.rewatch(ret); // setup watch chains if needed.
  return ret;
};
<|endoftext|>