Merge pull request #7897 from FreeCodeCamp/staging

Release staging
This commit is contained in:
Berkeley Martinez
2016-04-04 16:34:37 -07:00
47 changed files with 1528 additions and 2899 deletions

View File

@ -2,15 +2,15 @@ language: node_js
node_js: node_js:
- '4.2.1' - '4.2.1'
env: env:
- CXX=g++-4.8 - CXX=g++-4.8
addons: addons:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- g++-4.8 - g++-4.8
sudo: false sudo: false

View File

@ -107,15 +107,15 @@ Free Code Camp Issue Mods and staff are on hand to assist with Pull Request rela
There are two methods of creating a Pull for Free Code Camp: There are two methods of creating a Pull for Free Code Camp:
- Editing files via the GitHub Interface - Editing files via the GitHub Interface
- Editing files on a local clone - Editing files on a local clone
**Important: ALWAYS EDIT ON A BRANCH** **Important: ALWAYS EDIT ON A BRANCH**
Take away only one thing from this document, it should be this: Never, **EVER** make edits to the `staging` branch. ALWAYS make a new branch BEFORE you edit files. This is critical, because if your PR is not accepted, your copy of staging will be forever sullied and the only way to fix it is to delete your fork and re-fork. Take away only one thing from this document, it should be this: Never, **EVER** make edits to the `staging` branch. ALWAYS make a new branch BEFORE you edit files. This is critical, because if your PR is not accepted, your copy of staging will be forever sullied and the only way to fix it is to delete your fork and re-fork.
_**Method 1: Editing via your Local Fork (Recommended)**_ _**Method 1: Editing via your Local Fork (Recommended)**_
This is the recommended method. Read about How to Setup and Maintain a Local Instance of Free Code Camp. This is the recommended method. Read about How to Setup and Maintain a Local Instance of Free Code Camp.
1. Perform the maintenance step of rebasing `staging`. 1. Perform the maintenance step of rebasing `staging`.
2. Ensure you are on the `staging` branch using `git status`: 2. Ensure you are on the `staging` branch using `git status`:
```bash ```bash
@ -127,7 +127,7 @@ nothing to commit, working directory clean
``` ```
3. If you are not on staging or your working directory is not clean, resolve any outstanding files/commits and checkout staging `git checkout staging` 3. If you are not on staging or your working directory is not clean, resolve any outstanding files/commits and checkout staging `git checkout staging`
4. Create a branch off of `staging` with git: `git checkout -B branch/name-here` 4. Create a branch off of `staging` with git: `git checkout -B branch/name-here`
**Note:** Branch naming is important. Use a name like `fix/short-fix-description` or `feature/short-feature-description`. Review the [Contribution Guidelines](#contribution-guidelines) for more detail. **Note:** Branch naming is important. Use a name like `fix/short-fix-description` or `feature/short-feature-description`. Review the [Contribution Guidelines](#contribution-guidelines) for more detail.
5. Edit your file(s) locally with the editor of your choice 5. Edit your file(s) locally with the editor of your choice
6. Check your `git status` to see unstaged files. 6. Check your `git status` to see unstaged files.
@ -137,21 +137,21 @@ nothing to commit, working directory clean
10. Push your commits to your GitHub Fork: `git push -u origin branch/name-here` 10. Push your commits to your GitHub Fork: `git push -u origin branch/name-here`
11. Go to [Common Steps](#common-steps) 11. Go to [Common Steps](#common-steps)
_**Method 2: Editing via the GitHub Interface**_ _**Method 2: Editing via the GitHub Interface**_
Note: Editing via the GitHub Interface is not recommended, since it is not possible to update your fork via GitHub's interface without deleting and recreating your fork. Note: Editing via the GitHub Interface is not recommended, since it is not possible to update your fork via GitHub's interface without deleting and recreating your fork.
Read the [Wiki article](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-To-Create-A-Pull-Request-for-Free-Code-Camp#editing-via-the-github-interface) for further information Read the [Wiki article](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-To-Create-A-Pull-Request-for-Free-Code-Camp#editing-via-the-github-interface) for further information
## Common Steps ## Common Steps
1. Once the edits have been committed, you will be prompted to create a pull request on your fork's Github Page. 1. Once the edits have been committed, you will be prompted to create a pull request on your fork's GitHub Page.
2. By default, all pull requests should be against the FCC main repo, `staging` branch. 2. By default, all pull requests should be against the FCC main repo, `staging` branch.
3. Submit a [pull request](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Pull-Request-Contribute) from your branch to Free Code Camp's `staging` branch. 3. Submit a [pull request](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Pull-Request-Contribute) from your branch to Free Code Camp's `staging` branch.
3. The title (also called the subject) of your PR should be descriptive of your changes and succinctly indicates what is being fixed. 3. The title (also called the subject) of your PR should be descriptive of your changes and succinctly indicates what is being fixed.
- **Do not add the issue number in the PR title**. - **Do not add the issue number in the PR title**.
- Examples: `Add Test Cases to Bonfire Drop It` `Correct typo in Waypoint Size Your Images` - Examples: `Add Test Cases to Bonfire Drop It` `Correct typo in Waypoint Size Your Images`
4. In the body of your PR include a more detailed summary of the changes you made and why. 4. In the body of your PR include a more detailed summary of the changes you made and why.
- If the PR is meant to fix an existing bug/issue, then, at the end of your PR's commit message, append the keyword `closes` and #xxxx (where xxxx is the issue number). Example: `closes #1337`. - If the PR is meant to fix an existing bug/issue, then, at the end of your PR's commit message, append the keyword `closes` and #xxxx (where xxxx is the issue number). Example: `closes #1337`.
This tells GitHub to close the existing issue, if the PR is merged. This tells GitHub to close the existing issue, if the PR is merged.
5. Indicate if you have tested on a local copy of the site or not. 5. Indicate if you have tested on a local copy of the site or not.
@ -159,7 +159,7 @@ Read the [Wiki article](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-To
**If your PR is accepted** **If your PR is accepted**
Once your PR is accepted, you may delete the branch you created to submit it. This keeps your working fork clean. Once your PR is accepted, you may delete the branch you created to submit it. This keeps your working fork clean.
You can do this with a press of a button on the GitHub PR interface. You can delete the local copy of the branch with: `git branch -D branch/to-delete-name` You can do this with a press of a button on the GitHub PR interface. You can delete the local copy of the branch with: `git branch -D branch/to-delete-name`
@ -174,8 +174,8 @@ If you have a local copy of the repo, you can make the requested changes and ame
Be sure to post in the PR conversation that you have made the requested changes. Be sure to post in the PR conversation that you have made the requested changes.
##Other resources ##Other resources
- [Searching for Your Issue on Github](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Searching-for-Your-Issue-on-Github) - [Searching for Your Issue on GitHub](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Searching-for-Your-Issue-on-GitHub)
- [Creating a New Github Issue](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Creating-a-New-Github-Issue) - [Creating a New GitHub Issue](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Creating-a-New-GitHub-Issue)
- [Select Issues for Contributing Using Labels](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Select-Issues-for-Contributing-Using-Labels) - [Select Issues for Contributing Using Labels](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Select-Issues-for-Contributing-Using-Labels)
- [How to clone the FreeCodeCamp website on a Windows pc](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-to-clone-the-FreeCodeCamp-website-on-a-Windows-pc) - [How to clone the FreeCodeCamp website on a Windows pc](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-to-clone-the-FreeCodeCamp-website-on-a-Windows-pc)
- [How to log in to your local FCC site - using GitHub](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-To-Log-In-To-Your-Local-FCC-Site) - [How to log in to your local FCC site - using GitHub](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-To-Log-In-To-Your-Local-FCC-Site)

View File

@ -97,7 +97,7 @@ iframe.iphone {
height: 500px; height: 500px;
} }
@media (min-width: 1200px) and (max-width: 1250px){ @media (min-width: 1200px) and (max-width: 1250px){
right: 22px; right: 22px;
} }
} }
@ -108,6 +108,6 @@ iframe.iphone {
z-index: -1; z-index: -1;
right: -195px; right: -195px;
@media (min-width: 1200px) and (max-width: 1250px){ @media (min-width: 1200px) and (max-width: 1250px){
right: -207px; right: -207px;
} }
} }

View File

@ -32,7 +32,7 @@
} }
&.btn-lg { &.btn-lg {
padding-left: (@bs-height-lg + @padding-large-horizontal); padding-left: (@bs-height-lg + @padding-large-horizontal);
:first-child { > :first-child {
line-height: @bs-height-lg; line-height: @bs-height-lg;
width: @bs-height-lg; width: @bs-height-lg;
font-size: 1.8em; font-size: 1.8em;
@ -40,7 +40,7 @@
} }
&.btn-sm { &.btn-sm {
padding-left: (@bs-height-sm + @padding-small-horizontal); padding-left: (@bs-height-sm + @padding-small-horizontal);
:first-child { > :first-child {
line-height: @bs-height-sm; line-height: @bs-height-sm;
width: @bs-height-sm; width: @bs-height-sm;
font-size: 1.4em; font-size: 1.4em;
@ -48,7 +48,7 @@
} }
&.btn-xs { &.btn-xs {
padding-left: (@bs-height-xs + @padding-small-horizontal); padding-left: (@bs-height-xs + @padding-small-horizontal);
:first-child { > :first-child {
line-height: @bs-height-xs; line-height: @bs-height-xs;
width: @bs-height-xs; width: @bs-height-xs;
font-size: 1.2em; font-size: 1.2em;
@ -61,7 +61,7 @@
height: (@bs-height-base + 2); height: (@bs-height-base + 2);
width: (@bs-height-base + 2); width: (@bs-height-base + 2);
padding: 0; padding: 0;
:first-child { > :first-child {
border: none; border: none;
text-align: center; text-align: center;
width: 100%!important; width: 100%!important;
@ -86,29 +86,14 @@
} }
} }
.btn-social(@color-bg, @color: @color-bg) { .btn-social(@color-bg, @color: #fff) {
background-color: @color-bg; background-color: @color-bg;
.button-variant(@color, @color-bg, rgba(0,0,0,.2)); .button-variant(@color, @color-bg, rgba(0,0,0,.2));
} }
.btn-adn { .btn-social(#d87a68); }
.btn-bitbucket { .btn-social(#205081); }
.btn-dropbox { .btn-social(#1087dd); }
.btn-facebook { .btn-social(#3b5998); } .btn-facebook { .btn-social(#3b5998); }
.btn-flickr { .btn-social(#ff0084); }
.btn-foursquare { .btn-social(#f94877); }
.btn-github { .btn-social(#444444); } .btn-github { .btn-social(#444444); }
.btn-google-plus { .btn-social(#dd4b39); } .btn-google { .btn-social(#dd4b39); }
.btn-instagram { .btn-social(#3f729b); }
.btn-linkedin { .btn-social(#007bb6); } .btn-linkedin { .btn-social(#007bb6); }
.btn-microsoft { .btn-social(#2672ec); }
.btn-openid { .btn-social(#f7931e); }
.btn-pinterest { .btn-social(#cb2027); }
.btn-reddit { .btn-social(#eff7ff, #000); }
.btn-soundcloud { .btn-social(#ff5500); }
.btn-tumblr { .btn-social(#2c4762); }
.btn-twitter { .btn-social(#55acee); } .btn-twitter { .btn-social(#55acee); }
.btn-vimeo { .btn-social(#1ab7ea); }
.btn-vk { .btn-social(#587ea3); }
.btn-yahoo { .btn-social(#720e9e); }

View File

@ -562,4 +562,4 @@
<glyph unicode="&#xf23e;" horiz-adv-x="1792" /> <glyph unicode="&#xf23e;" horiz-adv-x="1792" />
<glyph unicode="&#xf500;" horiz-adv-x="1792" /> <glyph unicode="&#xf500;" horiz-adv-x="1792" />
</font> </font>
</defs></svg> </defs></svg>

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

View File

@ -56,30 +56,30 @@
animation-timing-function: steps(8, start); animation-timing-function: steps(8, start);
} }
.@{ionicons-prefix}loading-a:before { .@{ionicons-prefix}loading-a:before {
&:extend(.@{ionicons-prefix}load-a:before); &:extend(.@{ionicons-prefix}load-a:before);
} }
.@{ionicons-prefix}loading-b:before { .@{ionicons-prefix}loading-b:before {
&:extend(.@{ionicons-prefix}load-b:before); &:extend(.@{ionicons-prefix}load-b:before);
} }
.@{ionicons-prefix}loading-c:before { .@{ionicons-prefix}loading-c:before {
&:extend(.@{ionicons-prefix}load-c:before); &:extend(.@{ionicons-prefix}load-c:before);
} }
.@{ionicons-prefix}loading-d:before { .@{ionicons-prefix}loading-d:before {
&:extend(.@{ionicons-prefix}load-d:before); &:extend(.@{ionicons-prefix}load-d:before);
} }
.@{ionicons-prefix}looping:before { .@{ionicons-prefix}looping:before {
&:extend(.@{ionicons-prefix}loop:before); &:extend(.@{ionicons-prefix}loop:before);
} }
.@{ionicons-prefix}refreshing:before { .@{ionicons-prefix}refreshing:before {
&:extend(.@{ionicons-prefix}refresh:before); &:extend(.@{ionicons-prefix}refresh:before);
} }
.@{ionicons-prefix}ios7-reloading:before { .@{ionicons-prefix}ios7-reloading:before {
&:extend(.@{ionicons-prefix}ios7-reload:before); &:extend(.@{ionicons-prefix}ios7-reload:before);
} }

View File

@ -134,12 +134,12 @@
position:absolute; position:absolute;
display: block; display: block;
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.map-accordion { .map-accordion {
width:700px; width:700px;
margin:155px auto 0; margin:155px auto 0;
position:relative; position:relative;
#nested { #nested {
margin:0 10px; margin:0 10px;
@ -256,7 +256,7 @@
} }
} }
} }
.map-aside-action-item { .map-aside-action-item {
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;

View File

@ -13,7 +13,7 @@
}, },
{ {
"className": "ion-social-github", "className": "ion-social-github",
"content": " Github ", "content": " GitHub ",
"href": "http://github.com/freecodecamp", "href": "http://github.com/freecodecamp",
"target": "_blank" "target": "_blank"
}, },

View File

@ -1,6 +1,6 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Col, Row } from 'react-bootstrap'; import { Col } from 'react-bootstrap';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import Lecture from './Lecture.jsx'; import Lecture from './Lecture.jsx';
@ -55,18 +55,16 @@ export class Hike extends React.Component {
return ( return (
<Col xs={ 12 }> <Col xs={ 12 }>
<Row> <header className='text-center'>
<header className='text-center'> <h4>{ title }</h4>
<h4>{ title }</h4> </header>
</header> <hr />
<hr /> <div className='spacer' />
<div className='spacer' /> <section
<section className={ 'text-center' }
className={ 'text-center' } title={ title }>
title={ title }> { this.renderBody(shouldShowQuestions) }
{ this.renderBody(shouldShowQuestions) } </section>
</section>
</Row>
</Col> </Col>
); );
} }

View File

@ -1,7 +1,6 @@
import React, { PropTypes } from 'react'; import React, { PropTypes } from 'react';
import { compose } from 'redux'; import { compose } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Row } from 'react-bootstrap';
import PureComponent from 'react-pure-render/component'; import PureComponent from 'react-pure-render/component';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
// import debug from 'debug'; // import debug from 'debug';
@ -59,17 +58,14 @@ export class Hikes extends PureComponent {
render() { render() {
const { hikes } = this.props; const { hikes } = this.props;
const preventOverflow = { overflow: 'hidden' };
return ( return (
<div> <div>
<Row style={ preventOverflow }> {
{ // render sub-route
// render sub-route this.props.children ||
this.props.children || // if no sub-route render hikes map
// if no sub-route render hikes map this.renderMap(hikes)
this.renderMap(hikes) }
}
</Row>
</div> </div>
); );
} }

View File

@ -57,7 +57,7 @@
"express-state": "^1.2.0", "express-state": "^1.2.0",
"express-validator": "^2.18.0", "express-validator": "^2.18.0",
"fetchr": "~0.5.12", "fetchr": "~0.5.12",
"frameguard": "~0.2.2", "frameguard": "~1.1.0",
"gulp": "^3.9.0", "gulp": "^3.9.0",
"gulp-babel": "^6.1.1", "gulp-babel": "^6.1.1",
"gulp-concat": "^2.6.0", "gulp-concat": "^2.6.0",

View File

@ -562,4 +562,4 @@
<glyph unicode="&#xf23e;" horiz-adv-x="1792" /> <glyph unicode="&#xf23e;" horiz-adv-x="1792" />
<glyph unicode="&#xf500;" horiz-adv-x="1792" /> <glyph unicode="&#xf500;" horiz-adv-x="1792" />
</font> </font>
</defs></svg> </defs></svg>

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 326 KiB

After

Width:  |  Height:  |  Size: 326 KiB

View File

@ -24,20 +24,20 @@
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs45"> id="defs45">
</defs><sodipodi:namedview </defs><sodipodi:namedview
pagecolor="#ffffff" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,432 +0,0 @@
/**
* Contains the JailedSite object used both by the application
* site, and by each plugin
*/
(function(){
/**
* JailedSite object represents a single site in the
* communication protocol between the application and the plugin
*
* @param {Object} connection a special object allowing to send
* and receive messages from the opposite site (basically it
* should only provide send() and onMessage() methods)
*/
JailedSite = function(connection) {
this._interface = {};
this._remote = null;
this._remoteUpdateHandler = function(){};
this._getInterfaceHandler = function(){};
this._interfaceSetAsRemoteHandler = function(){};
this._disconnectHandler = function(){};
this._store = new ReferenceStore;
var me = this;
this._connection = connection;
this._connection.onMessage(
function(data){ me._processMessage(data); }
);
this._connection.onDisconnect(
function(m){
me._disconnectHandler(m);
}
);
}
/**
* Set a handler to be called when the remote site updates its
* interface
*
* @param {Function} handler
*/
JailedSite.prototype.onRemoteUpdate = function(handler) {
this._remoteUpdateHandler = handler;
}
/**
* Set a handler to be called when received a responce from the
* remote site reporting that the previously provided interface
* has been succesfully set as remote for that site
*
* @param {Function} handler
*/
JailedSite.prototype.onInterfaceSetAsRemote = function(handler) {
this._interfaceSetAsRemoteHandler = handler;
}
/**
* Set a handler to be called when the remote site requests to
* (re)send the interface. Used to detect an initialzation
* completion without sending additional request, since in fact
* 'getInterface' request is only sent by application at the last
* step of the plugin initialization
*
* @param {Function} handler
*/
JailedSite.prototype.onGetInterface = function(handler) {
this._getInterfaceHandler = handler;
}
/**
* @returns {Object} set of remote interface methods
*/
JailedSite.prototype.getRemote = function() {
return this._remote;
}
/**
* Sets the interface of this site making it available to the
* remote site by sending a message with a set of methods names
*
* @param {Object} _interface to set
*/
JailedSite.prototype.setInterface = function(_interface) {
this._interface = _interface;
this._sendInterface();
}
/**
* Sends the actual interface to the remote site upon it was
* updated or by a special request of the remote site
*/
JailedSite.prototype._sendInterface = function() {
var names = [];
for (var name in this._interface) {
if (this._interface.hasOwnProperty(name)) {
names.push(name);
}
}
this._connection.send({type:'setInterface', api: names});
}
/**
* Handles a message from the remote site
*/
JailedSite.prototype._processMessage = function(data) {
switch(data.type) {
case 'method':
var method = this._interface[data.name];
var args = this._unwrap(data.args);
method.apply(null, args);
break;
case 'callback':
var method = this._store.fetch(data.id)[data.num];
var args = this._unwrap(data.args);
method.apply(null, args);
break;
case 'setInterface':
this._setRemote(data.api);
break;
case 'getInterface':
this._sendInterface();
this._getInterfaceHandler();
break;
case 'interfaceSetAsRemote':
this._interfaceSetAsRemoteHandler();
break;
case 'disconnect':
this._disconnectHandler();
this._connection.disconnect();
break;
}
}
/**
* Sends a requests to the remote site asking it to provide its
* current interface
*/
JailedSite.prototype.requestRemote = function() {
this._connection.send({type:'getInterface'});
}
/**
* Sets the new remote interface provided by the other site
*
* @param {Array} names list of function names
*/
JailedSite.prototype._setRemote = function(names) {
this._remote = {};
var i, name;
for (i = 0; i < names.length; i++) {
name = names[i];
this._remote[name] = this._genRemoteMethod(name);
}
this._remoteUpdateHandler();
this._reportRemoteSet();
}
/**
* Generates the wrapped function corresponding to a single remote
* method. When the generated function is called, it will send the
* corresponding message to the remote site asking it to execute
* the particular method of its interface
*
* @param {String} name of the remote method
*
* @returns {Function} wrapped remote method
*/
JailedSite.prototype._genRemoteMethod = function(name) {
var me = this;
var remoteMethod = function() {
me._connection.send({
type: 'method',
name: name,
args: me._wrap(arguments)
});
};
return remoteMethod;
}
/**
* Sends a responce reporting that interface just provided by the
* remote site was sucessfully set by this site as remote
*/
JailedSite.prototype._reportRemoteSet = function() {
this._connection.send({type:'interfaceSetAsRemote'});
}
/**
* Prepares the provided set of remote method arguments for
* sending to the remote site, replaces all the callbacks with
* identifiers
*
* @param {Array} args to wrap
*
* @returns {Array} wrapped arguments
*/
JailedSite.prototype._wrap = function(args) {
var wrapped = [];
var callbacks = {};
var callbacksPresent = false;
for (var i = 0; i < args.length; i++) {
if (typeof args[i] == 'function') {
callbacks[i] = args[i];
wrapped[i] = {type: 'callback', num : i};
callbacksPresent = true;
} else {
wrapped[i] = {type: 'argument', value : args[i]};
}
}
var result = {args: wrapped};
if (callbacksPresent) {
result.callbackId = this._store.put(callbacks);
}
return result;
}
/**
* Unwraps the set of arguments delivered from the remote site,
* replaces all callback identifiers with a function which will
* initiate sending that callback identifier back to other site
*
* @param {Object} args to unwrap
*
* @returns {Array} unwrapped args
*/
JailedSite.prototype._unwrap = function(args) {
var called = false;
// wraps each callback so that the only one could be called
var once = function(cb) {
return function() {
if (!called) {
called = true;
cb.apply(this, arguments);
} else {
var msg =
'A callback from this set has already been executed';
throw new Error(msg);
}
};
}
var result = [];
var i, arg, cb, me = this;
for (i = 0; i < args.args.length; i++) {
arg = args.args[i];
if (arg.type == 'argument') {
result.push(arg.value);
} else {
cb = once(
this._genRemoteCallback(args.callbackId, i)
);
result.push(cb);
}
}
return result;
}
/**
* Generates the wrapped function corresponding to a single remote
* callback. When the generated function is called, it will send
* the corresponding message to the remote site asking it to
* execute the particular callback previously saved during a call
* by the remote site a method from the interface of this site
*
* @param {Number} id of the remote callback to execute
* @param {Number} argNum argument index of the callback
*
* @returns {Function} wrapped remote callback
*/
JailedSite.prototype._genRemoteCallback = function(id, argNum) {
var me = this;
var remoteCallback = function() {
me._connection.send({
type : 'callback',
id : id,
num : argNum,
args : me._wrap(arguments)
});
};
return remoteCallback;
}
/**
* Sends the notification message and breaks the connection
*/
JailedSite.prototype.disconnect = function() {
this._connection.send({type: 'disconnect'});
this._connection.disconnect();
}
/**
* Set a handler to be called when received a disconnect message
* from the remote site
*
* @param {Function} handler
*/
JailedSite.prototype.onDisconnect = function(handler) {
this._disconnectHandler = handler;
}
/**
* ReferenceStore is a special object which stores other objects
* and provides the references (number) instead. This reference
* may then be sent over a json-based communication channel (IPC
* to another Node.js process or a message to the Worker). Other
* site may then provide the reference in the responce message
* implying the given object should be activated.
*
* Primary usage for the ReferenceStore is a storage for the
* callbacks, which therefore makes it possible to initiate a
* callback execution by the opposite site (which normally cannot
* directly execute functions over the communication channel).
*
* Each stored object can only be fetched once and is not
* available for the second time. Each stored object must be
* fetched, since otherwise it will remain stored forever and
* consume memory.
*
* Stored object indeces are simply the numbers, which are however
* released along with the objects, and are later reused again (in
* order to postpone the overflow, which should not likely happen,
* but anyway).
*/
var ReferenceStore = function() {
this._store = {}; // stored object
this._indices = [0]; // smallest available indices
}
/**
* @function _genId() generates the new reference id
*
* @returns {Number} smallest available id and reserves it
*/
ReferenceStore.prototype._genId = function() {
var id;
if (this._indices.length == 1) {
id = this._indices[0]++;
} else {
id = this._indices.shift();
}
return id;
}
/**
* Releases the given reference id so that it will be available by
* another object stored
*
* @param {Number} id to release
*/
ReferenceStore.prototype._releaseId = function(id) {
for (var i = 0; i < this._indices.length; i++) {
if (id < this._indices[i]) {
this._indices.splice(i, 0, id);
break;
}
}
// cleaning-up the sequence tail
for (i = this._indices.length-1; i >= 0; i--) {
if (this._indices[i]-1 == this._indices[i-1]) {
this._indices.pop();
} else {
break;
}
}
}
/**
* Stores the given object and returns the refernce id instead
*
* @param {Object} obj to store
*
* @returns {Number} reference id of the stored object
*/
ReferenceStore.prototype.put = function(obj) {
var id = this._genId();
this._store[id] = obj;
return id;
}
/**
* Retrieves previously stored object and releases its reference
*
* @param {Number} id of an object to retrieve
*/
ReferenceStore.prototype.fetch = function(id) {
var obj = this._store[id];
this._store[id] = null;
delete this._store[id];
this._releaseId(id);
return obj;
}
})();

View File

@ -1 +0,0 @@
<script sandbox="allow-same-origin allow-scripts" src="_frame.js"></script>

View File

@ -1,56 +0,0 @@
/**
* Contains the code executed in the sandboxed frame under web-browser
*
* Creates a Web-Worker inside the frame, sets up the communication
* between the worker and the parent window
*/
var scripts = document.getElementsByTagName('script');
var __jailed__path__ = scripts[scripts.length-1].src
.split('?')[0]
.split('/')
.slice(0, -1)
.join('/') + '/';
// creating worker as a blob enables import of local files
var blobCode = [
' self.addEventListener("message", function(m){ ',
' if (m.data.type == "initImport") { ',
' importScripts(m.data.url); ',
' self.postMessage({type: "initialized"}); ',
' } ',
' }); '
].join('\n');
var blobUrl;
try {
blobUrl = new Blob([blobCode], {type: 'application/javascript'});
} catch (e) {
window.BlobBuilder = window.BlobBuilder
|| window.WebKitBlobBuilder
|| window.MozBlobBuilder;
blobUrl = new BlobBuilder();
blobUrl.append(blobCode);
blobUrl = blobUrl.getBlob();
}
var worker = new Worker(URL.createObjectURL(blobUrl));
// telling worker to load _pluginWeb.js (see blob code above)
worker.postMessage({
type: 'initImport',
url: __jailed__path__ + '_pluginWeb.js'
});
// forwarding messages between the worker and parent window
worker.addEventListener('message', function(m) {
parent.postMessage(m.data, '*');
});
window.addEventListener('message', function(m) {
worker.postMessage(m.data);
});

View File

@ -1,95 +0,0 @@
/**
* Core plugin script loaded into the plugin process/thread.
*
* Initializes the plugin-site API global methods.
*/
(function(){
// localize
var site = new JailedSite(connection);
delete JailedSite;
delete connection;
site.onGetInterface(function(){
launchConnected();
});
site.onRemoteUpdate(function(){
application.remote = site.getRemote();
});
/**
* Simplified clone of Whenable instance (the object can not be
* placed into a shared script, because the main library needs it
* before the additional scripts may load)
*/
var connected = false;
var connectedHandlers = [];
var launchConnected = function() {
if (!connected) {
connected = true;
var handler;
while(handler = connectedHandlers.pop()) {
handler();
}
}
}
var checkHandler = function(handler){
var type = typeof handler;
if (type != 'function') {
var msg =
'A function may only be subsribed to the event, '
+ type
+ ' was provided instead'
throw new Error(msg);
}
return handler;
}
/**
* Sets a function executed after the connection to the
* application is estaplished, and the initial interface-exchange
* messaging is completed
*
* @param {Function} handler to be called upon initialization
*/
application.whenConnected = function(handler) {
handler = checkHandler(handler);
if (connected) {
handler();
} else {
connectedHandlers.push(handler);
}
}
/**
* Sets the plugin interface available to the application
*
* @param {Object} _interface to set
*/
application.setInterface = function(_interface) {
site.setInterface(_interface);
}
/**
* Disconnects the plugin from the application (sending
* notification message) and destroys itself
*/
application.disconnect = function(_interface) {
site.disconnect();
}
})();

View File

@ -1,267 +0,0 @@
/**
* Contains the routines loaded by the plugin process under Node.js
*
* Initializes the Node.js environment version of the
* platform-dependent connection object for the plugin site
*/
application = {};
connection = {};
/**
* Prints error message and its stack
*
* @param {Object} msg stack provided by error.stack or a message
*/
var printError = function(msg) {
console.error();
console.error(msg);
}
/**
* Event lisener for the plugin message
*/
process.on('message', function(m) {
switch(m.type){
case 'import':
importScript(m.url);
break;
case 'importJailed':
importScriptJailed(m.url);
break;
case 'execute':
execute(m.code);
break;
case 'message':
// unhandled exception would break the IPC channel
try {
conn._messageHandler(m.data);
} catch(e) {
printError(e.stack);
}
break;
}
});
/**
* Checks if the given path is remote
*
* @param {String} path to check
* @returns {Boolean} true if path is remote
*/
var isRemote = function(path) {
return (path.substr(0,7).toLowerCase() == 'http://' ||
path.substr(0,8).toLowerCase() == 'https://');
}
/**
* Loads and executes the JavaScript file with the given url
*
* @param {String} url of the script to load
*/
var importScript = function(url) {
var sCb = function() {
process.send({type: 'importSuccess', url: url});
}
var fCb = function() {
process.send({type: 'importFailure', url: url});
}
var run = function(code) {
executeNormal(code, url, sCb, fCb);
}
if (isRemote(url)) {
loadRemote(url, run, fCb);
} else {
try {
run(loadLocal(url));
} catch(e) {
printError(e.stack);
fCb();
}
}
}
/**
* Loads and executes the JavaScript file with the given url in a
* jailed environment
*
* @param {String} url of the script to load
*/
var importScriptJailed = function(url) {
var sCb = function() {
process.send({type: 'importSuccess', url: url});
}
var fCb = function() {
process.send({type: 'importFailure', url: url});
}
var run = function(code) {
executeJailed(code, url, sCb, fCb);
}
if (isRemote(url)) {
loadRemote(url, run, fCb);
} else {
try {
run(loadLocal(url));
} catch (e) {
printError(e.stack);
fCb();
}
}
}
/**
* Executes the given code in the jailed environment, sends the
* corresponding message to the application site when succeeded/failed
*
* @param {String} code to execute
*/
var execute = function(code) {
var sCb = function() {
process.send({type: 'executeSuccess'});
}
var fCb = function() {
process.send({type: 'executeFailure'});
}
executeJailed(code, 'DYNAMIC PLUGIN', sCb, fCb);
}
/**
* Executes the given code in the current environment / scope, runs
* the corresponding callback when done
*
* @param {String} code to execute
* @param {String} url of the script (for displaying the stack)
* @param {Function} sCb
* @param {Function} fCb
*/
var executeNormal = function(code, url, sCb, fCb) {
var err = null;
try {
require('vm').runInThisContext(code, url);
sCb();
} catch (e) {
printError(e.stack);
fCb();
}
}
/**
* Executes the given code in a jailed environment, runs the
* corresponding callback when done
*
* @param {String} code to execute
* @param {String} url of the script (for displaying the stack)
* @param {Function} sCb
* @param {Function} fCb
*/
var executeJailed = function(code, url, sCb, fCb) {
var vm = require('vm');
var sandbox = {};
var expose = [
'application',
'setTimeout',
'setInterval',
'clearTimeout',
'clearInterval'
];
for (var i = 0; i < expose.length; i++) {
sandbox[expose[i]] = global[expose[i]];
}
code = '"use strict";\n'+code;
try {
vm.runInNewContext(code, vm.createContext(sandbox), url);
sCb();
} catch (e) {
printError(e.stack);
fCb();
}
}
/**
* Loads local file and
*
* @param {String} path of the file to read
*
* @returns {String} file contents
*/
var loadLocal = function(path) {
return require("fs").readFileSync(path).toString();
}
/**
* Downloads the script by remote url and provides its content as a
* string to the callback
*
* @param {String} url of the remote module to load
* @param {Function} sCb success callback
* @param {Function} fCb failure callback
*/
var loadRemote = function(url, sCb, fCb) {
var receive = function(res) {
if (res.statusCode != 200) {
var msg = 'Failed to load ' + url + '\n' +
'HTTP responce status code: ' + res.statusCode;
printError(msg);
fCb();
} else {
var content = '';
res.on('end', function(){ sCb(content); });
res.on(
'readable',
function() {
var chunk = res.read();
content += chunk.toString();
}
);
}
}
try {
require('http').get(url, receive).on('error', fCb);
} catch (e) {
printError(e.stack);
fCb();
}
}
/**
* Connection object provided to the SandboxedSite constructor, plugin
* site implementation for the Node.js environment
*/
var conn = {
disconnect: function(){ process.exit(); },
send: function(data) {
process.send({type: 'message', data: data});
},
onMessage: function(h){ conn._messageHandler = h; },
_messageHandler: function(){},
onDisconnect: function() {}
};
connection = conn;

View File

@ -1,96 +0,0 @@
/**
* Contains the routines loaded by the plugin Worker under web-browser.
*
* Initializes the web environment version of the platform-dependent
* connection object for the plugin site
*/
self.application = {};
self.connection = {};
(function(){
/**
* Event lisener for the plugin message
*/
self.addEventListener('message', function(e){
var m = e.data.data;
switch (m.type) {
case 'import':
case 'importJailed': // already jailed in the Worker
importScript(m.url);
break;
case 'execute':
execute(m.code);
break;
case 'message':
conn._messageHandler(m.data);
break;
}
});
/**
* Loads and executes the JavaScript file with the given url
*
* @param {String} url to load
*/
var importScript = function(url) {
var error = null;
try {
importScripts(url);
} catch (e) {
error = e;
}
if (error) {
self.postMessage({type: 'importFailure', url: url});
throw error;
} else {
self.postMessage({type: 'importSuccess', url: url});
}
}
/**
* Executes the given code in a jailed environment. For web
* implementation, we're already jailed in the worker, so simply
* eval()
*
* @param {String} code code to execute
*/
var execute = function(code) {
try {
eval(code);
} catch (e) {
self.postMessage({type: 'executeFailure'});
throw e;
}
self.postMessage({type: 'executeSuccess'});
}
/**
* Connection object provided to the JailedSite constructor,
* plugin site implementation for the web-based environment.
* Global will be then cleared to prevent exposure into the
* Worker, so we put this local connection object into a closure
*/
var conn = {
disconnect: function(){ self.close(); },
send: function(data) {
self.postMessage({type: 'message', data: data});
},
onMessage: function(h){ conn._messageHandler = h; },
_messageHandler: function(){},
onDisconnect: function() {}
};
connection = conn;
})();

View File

@ -1,780 +0,0 @@
/**
* @fileoverview Jailed - safe yet flexible sandbox
* @version 0.2.0
*
* @license MIT, see http://github.com/asvd/jailed
* Copyright (c) 2014 asvd <heliosframework@gmail.com>
*
* Main library script, the only one to be loaded by a developer into
* the application. Other scrips shipped along will be loaded by the
* library either here (application site), or into the plugin site
* (Worker/child process):
*
* _JailedSite.js loaded into both applicaiton and plugin sites
* _frame.html sandboxed frame (web)
* _frame.js sandboxed frame code (web)
* _pluginWeb.js platform-dependent plugin routines (web)
* _pluginNode.js platform-dependent plugin routines (Node.js)
* _pluginCore.js common plugin site protocol implementation
*/
var __jailed__path__;
if (typeof window == 'undefined') {
// Node.js
__jailed__path__ = __dirname + '/';
} else {
// web
var scripts = document.getElementsByTagName('script');
__jailed__path__ = scripts[scripts.length-1].src
.split('?')[0]
.split('/')
.slice(0, -1)
.join('/')+'/';
}
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory((root.jailed = {}));
}
}(this, function (exports) {
var isNode = typeof window == 'undefined';
/**
* A special kind of event:
* - which can only be emitted once;
* - executes a set of subscribed handlers upon emission;
* - if a handler is subscribed after the event was emitted, it
* will be invoked immideately.
*
* Used for the events which only happen once (or do not happen at
* all) during a single plugin lifecycle - connect, disconnect and
* connection failure
*/
var Whenable = function() {
this._emitted = false;
this._handlers = [];
}
/**
* Emits the Whenable event, calls all the handlers already
* subscribed, switches the object to the 'emitted' state (when
* all future subscibed listeners will be immideately issued
* instead of being stored)
*/
Whenable.prototype.emit = function(){
if (!this._emitted) {
this._emitted = true;
var handler;
while(handler = this._handlers.pop()) {
setTimeout(handler,0);
}
}
}
/**
* Saves the provided function as a handler for the Whenable
* event. This handler will then be called upon the event emission
* (if it has not been emitted yet), or will be scheduled for
* immediate issue (if the event has already been emmitted before)
*
* @param {Function} handler to subscribe for the event
*/
Whenable.prototype.whenEmitted = function(handler){
handler = this._checkHandler(handler);
if (this._emitted) {
setTimeout(handler, 0);
} else {
this._handlers.push(handler);
}
}
/**
* Checks if the provided object is suitable for being subscribed
* to the event (= is a function), throws an exception if not
*
* @param {Object} obj to check for being subscribable
*
* @throws {Exception} if object is not suitable for subscription
*
* @returns {Object} the provided object if yes
*/
Whenable.prototype._checkHandler = function(handler){
var type = typeof handler;
if (type != 'function') {
var msg =
'A function may only be subsribed to the event, '
+ type
+ ' was provided instead'
throw new Error(msg);
}
return handler;
}
/**
* Initializes the library site for Node.js environment (loads
* _JailedSite.js)
*/
var initNode = function() {
require('./_JailedSite.js');
}
/**
* Initializes the library site for web environment (loads
* _JailedSite.js)
*/
var platformInit;
var initWeb = function() {
// loads additional script to the application environment
var load = function(path, cb) {
var script = document.createElement('script');
script.src = path;
var clear = function() {
script.onload = null;
script.onerror = null;
script.onreadystatechange = null;
script.parentNode.removeChild(script);
}
var success = function() {
clear();
cb();
}
script.onerror = clear;
script.onload = success;
script.onreadystatechange = function() {
var state = script.readyState;
if (state==='loaded' || state==='complete') {
success();
}
}
document.body.appendChild(script);
}
platformInit = new Whenable;
var origOnload = window.onload || function(){};
window.onload = function(){
origOnload();
load(
__jailed__path__+'_JailedSite.js',
function(){ platformInit.emit(); }
);
}
}
var BasicConnection;
/**
* Creates the platform-dependent BasicConnection object in the
* Node.js environment
*/
var basicConnectionNode = function() {
var childProcess = require('child_process');
/**
* Platform-dependent implementation of the BasicConnection
* object, initializes the plugin site and provides the basic
* messaging-based connection with it
*
* For Node.js the plugin is created as a forked process
*/
BasicConnection = function() {
this._disconnected = false;
this._messageHandler = function(){};
this._disconnectHandler = function(){};
this._process = childProcess.fork(
__jailed__path__+'_pluginNode.js'
);
var me = this;
this._process.on('message', function(m){
me._messageHandler(m);
});
this._process.on('exit', function(m){
me._disconnected = true;
me._disconnectHandler(m);
});
}
/**
* Sets-up the handler to be called upon the BasicConnection
* initialization is completed.
*
* For Node.js the connection is fully initialized within the
* constructor, so simply calls the provided handler.
*
* @param {Function} handler to be called upon connection init
*/
BasicConnection.prototype.whenInit = function(handler) {
handler();
}
/**
* Sends a message to the plugin site
*
* @param {Object} data to send
*/
BasicConnection.prototype.send = function(data) {
if (!this._disconnected) {
this._process.send(data);
}
}
/**
* Adds a handler for a message received from the plugin site
*
* @param {Function} handler to call upon a message
*/
BasicConnection.prototype.onMessage = function(handler) {
this._messageHandler = function(data) {
// broken stack would break the IPC in Node.js
try {
handler(data);
} catch (e) {
console.error();
console.error(e.stack);
}
}
}
/**
* Adds a handler for the event of plugin disconnection
* (= plugin process exit)
*
* @param {Function} handler to call upon a disconnect
*/
BasicConnection.prototype.onDisconnect = function(handler) {
this._disconnectHandler = handler;
}
/**
* Disconnects the plugin (= kills the forked process)
*/
BasicConnection.prototype.disconnect = function() {
this._process.kill('SIGKILL');
this._disconnected = true;
}
}
/**
* Creates the platform-dependent BasicConnection object in the
* web-browser environment
*/
var basicConnectionWeb = function() {
var perm = ['allow-scripts'];
if (__jailed__path__.substr(0,7).toLowerCase() == 'file://') {
// local instance requires extra permission
perm.push('allow-same-origin');
}
// frame element to be cloned
var sample = document.createElement('iframe');
sample.src = __jailed__path__ + '_frame.html';
sample.sandbox = perm.join(' ');
sample.style.display = 'none';
/**
* Platform-dependent implementation of the BasicConnection
* object, initializes the plugin site and provides the basic
* messaging-based connection with it
*
* For the web-browser environment, the plugin is created as a
* Worker in a sandbaxed frame
*/
BasicConnection = function() {
this._init = new Whenable;
this._disconnected = false;
var me = this;
platformInit.whenEmitted(function() {
if (!me._disconnected) {
me._frame = sample.cloneNode(false);
document.body.appendChild(me._frame);
window.addEventListener('message', function (e) {
if (e.origin === "null" &&
e.source === me._frame.contentWindow) {
if (e.data.type == 'initialized') {
me._init.emit();
} else {
me._messageHandler(e.data);
}
}
});
}
});
}
/**
* Sets-up the handler to be called upon the BasicConnection
* initialization is completed.
*
* For the web-browser environment, the handler is issued when
* the plugin worker successfully imported and executed the
* _pluginWeb.js, and replied to the application site with the
* initImprotSuccess message.
*
* @param {Function} handler to be called upon connection init
*/
BasicConnection.prototype.whenInit = function(handler) {
this._init.whenEmitted(handler);
}
/**
* Sends a message to the plugin site
*
* @param {Object} data to send
*/
BasicConnection.prototype.send = function(data) {
this._frame.contentWindow.postMessage(
{type: 'message', data: data}, '*'
);
}
/**
* Adds a handler for a message received from the plugin site
*
* @param {Function} handler to call upon a message
*/
BasicConnection.prototype.onMessage = function(handler) {
this._messageHandler = handler;
}
/**
* Adds a handler for the event of plugin disconnection
* (not used in case of Worker)
*
* @param {Function} handler to call upon a disconnect
*/
BasicConnection.prototype.onDisconnect = function(){};
/**
* Disconnects the plugin (= kills the frame)
*/
BasicConnection.prototype.disconnect = function() {
if (!this._disconnected) {
this._disconnected = true;
if (typeof this._frame != 'undefined') {
this._frame.parentNode.removeChild(this._frame);
} // otherwise farme is not yet created
}
}
}
if (isNode) {
initNode();
basicConnectionNode();
} else {
initWeb();
basicConnectionWeb();
}
/**
* Application-site Connection object constructon, reuses the
* platform-dependent BasicConnection declared above in order to
* communicate with the plugin environment, implements the
* application-site protocol of the interraction: provides some
* methods for loading scripts and executing the given code in the
* plugin
*/
var Connection = function(){
this._platformConnection = new BasicConnection;
this._importCallbacks = {};
this._executeSCb = function(){};
this._executeFCb = function(){};
this._messageHandler = function(){};
var me = this;
this.whenInit = function(cb){
me._platformConnection.whenInit(cb);
};
this._platformConnection.onMessage(function(m) {
switch(m.type) {
case 'message':
me._messageHandler(m.data);
break;
case 'importSuccess':
me._handleImportSuccess(m.url);
break;
case 'importFailure':
me._handleImportFailure(m.url);
break;
case 'executeSuccess':
me._executeSCb();
break;
case 'executeFailure':
me._executeFCb();
break;
}
});
}
/**
* Tells the plugin to load a script with the given path, and to
* execute it. Callbacks executed upon the corresponding responce
* message from the plugin site
*
* @param {String} path of a script to load
* @param {Function} sCb to call upon success
* @param {Function} fCb to call upon failure
*/
Connection.prototype.importScript = function(path, sCb, fCb) {
var f = function(){};
this._importCallbacks[path] = {sCb: sCb||f, fCb: fCb||f};
this._platformConnection.send({type: 'import', url: path});
}
/**
* Tells the plugin to load a script with the given path, and to
* execute it in the JAILED environment. Callbacks executed upon
* the corresponding responce message from the plugin site
*
* @param {String} path of a script to load
* @param {Function} sCb to call upon success
* @param {Function} fCb to call upon failure
*/
Connection.prototype.importJailedScript = function(path, sCb, fCb) {
var f = function(){};
this._importCallbacks[path] = {sCb: sCb||f, fCb: fCb||f};
this._platformConnection.send({type: 'importJailed', url: path});
}
/**
* Sends the code to the plugin site in order to have it executed
* in the JAILED enviroment. Assuming the execution may only be
* requested once by the Plugin object, which means a single set
* of callbacks is enough (unlike importing additional scripts)
*
* @param {String} code code to execute
* @param {Function} sCb to call upon success
* @param {Function} fCb to call upon failure
*/
Connection.prototype.execute = function(code, sCb, fCb) {
this._executeSCb = sCb||function(){};
this._executeFCb = fCb||function(){};
this._platformConnection.send({type: 'execute', code: code});
}
/**
* Adds a handler for a message received from the plugin site
*
* @param {Function} handler to call upon a message
*/
Connection.prototype.onMessage = function(handler) {
this._messageHandler = handler;
}
/**
* Adds a handler for a disconnect message received from the
* plugin site
*
* @param {Function} handler to call upon disconnect
*/
Connection.prototype.onDisconnect = function(handler) {
this._platformConnection.onDisconnect(handler);
}
/**
* Sends a message to the plugin
*
* @param {Object} data of the message to send
*/
Connection.prototype.send = function(data) {
this._platformConnection.send({
type: 'message',
data: data
});
}
/**
* Handles import succeeded message from the plugin
*
* @param {String} url of a script loaded by the plugin
*/
Connection.prototype._handleImportSuccess = function(url) {
var sCb = this._importCallbacks[url].sCb;
this._importCallbacks[url] = null;
delete this._importCallbacks[url];
sCb();
}
/**
* Handles import failure message from the plugin
*
* @param {String} url of a script loaded by the plugin
*/
Connection.prototype._handleImportFailure = function(url) {
var fCb = this._importCallbacks[url].fCb;
this._importCallbacks[url] = null;
delete this._importCallbacks[url];
fCb();
}
/**
* Disconnects the plugin when it is not needed anymore
*/
Connection.prototype.disconnect = function() {
this._platformConnection.disconnect();
}
/**
* Plugin constructor, represents a plugin initialized by a script
* with the given path
*
* @param {String} url of a plugin source
* @param {Object} _interface to provide for the plugin
*/
var Plugin = function(url, _interface) {
this._path = url;
this._initialInterface = _interface||{};
this._connect();
}
/**
* DynamicPlugin constructor, represents a plugin initialized by a
* string containing the code to be executed
*
* @param {String} code of the plugin
* @param {Object} _interface to provide to the plugin
*/
var DynamicPlugin = function(code, _interface) {
this._code = code;
this._initialInterface = _interface||{};
this._connect();
}
/**
* Creates the connection to the plugin site
*/
DynamicPlugin.prototype._connect =
Plugin.prototype._connect = function() {
this.remote = null;
this._connect = new Whenable;
this._fail = new Whenable;
this._disconnect = new Whenable;
var me = this;
// binded failure callback
this._fCb = function(){
me._fail.emit();
me.disconnect();
}
this._connection = new Connection;
this._connection.whenInit(function(){
me._init();
});
}
/**
* Creates the Site object for the plugin, and then loads the
* common routines (_JailedSite.js)
*/
DynamicPlugin.prototype._init =
Plugin.prototype._init = function() {
this._site = new JailedSite(this._connection);
var me = this;
this._site.onDisconnect(function() {
me._disconnect.emit();
});
var sCb = function() {
me._loadCore();
}
this._connection.importScript(
__jailed__path__+'_JailedSite.js', sCb, this._fCb
);
}
/**
* Loads the core scirpt into the plugin
*/
DynamicPlugin.prototype._loadCore =
Plugin.prototype._loadCore = function() {
var me = this;
var sCb = function() {
me._sendInterface();
}
this._connection.importScript(
__jailed__path__+'_pluginCore.js', sCb, this._fCb
);
}
/**
* Sends to the remote site a signature of the interface provided
* upon the Plugin creation
*/
DynamicPlugin.prototype._sendInterface =
Plugin.prototype._sendInterface = function() {
var me = this;
this._site.onInterfaceSetAsRemote(function() {
if (!me._connected) {
me._loadPlugin();
}
});
this._site.setInterface(this._initialInterface);
}
/**
* Loads the plugin body (loads the plugin url in case of the
* Plugin)
*/
Plugin.prototype._loadPlugin = function() {
var me = this;
var sCb = function() {
me._requestRemote();
}
this._connection.importJailedScript(this._path, sCb, this._fCb);
}
/**
* Loads the plugin body (executes the code in case of the
* DynamicPlugin)
*/
DynamicPlugin.prototype._loadPlugin = function() {
var me = this;
var sCb = function() {
me._requestRemote();
}
this._connection.execute(this._code, sCb, this._fCb);
}
/**
* Requests the remote interface from the plugin (which was
* probably set by the plugin during its initialization), emits
* the connect event when done, then the plugin is fully usable
* (meaning both the plugin and the application can use the
* interfaces provided to each other)
*/
DynamicPlugin.prototype._requestRemote =
Plugin.prototype._requestRemote = function() {
var me = this;
this._site.onRemoteUpdate(function(){
me.remote = me._site.getRemote();
me._connect.emit();
});
this._site.requestRemote();
}
/**
* Disconnects the plugin immideately
*/
DynamicPlugin.prototype.disconnect =
Plugin.prototype.disconnect = function() {
this._connection.disconnect();
this._disconnect.emit();
}
/**
* Saves the provided function as a handler for the connection
* failure Whenable event
*
* @param {Function} handler to be issued upon disconnect
*/
DynamicPlugin.prototype.whenFailed =
Plugin.prototype.whenFailed = function(handler) {
this._fail.whenEmitted(handler);
}
/**
* Saves the provided function as a handler for the connection
* success Whenable event
*
* @param {Function} handler to be issued upon connection
*/
DynamicPlugin.prototype.whenConnected =
Plugin.prototype.whenConnected = function(handler) {
this._connect.whenEmitted(handler);
}
/**
* Saves the provided function as a handler for the connection
* failure Whenable event
*
* @param {Function} handler to be issued upon connection failure
*/
DynamicPlugin.prototype.whenDisconnected =
Plugin.prototype.whenDisconnected = function(handler) {
this._disconnect.whenEmitted(handler);
}
exports.Plugin = Plugin;
exports.DynamicPlugin = DynamicPlugin;
}));

View File

@ -234,6 +234,81 @@
"Si completas todas las 2,080 horas de desafíos y proyectos, obtendrás un Certificado de Desarrollo de Pila Completa. Te ofreceremos gratuitamente una práctica en entrevistas para desarrolladores. Incluso ofrecemos un directorio de trabajos donde los empleadores contratan específicamente campistas que han recibido certificaciones de Free Code Camp.", "Si completas todas las 2,080 horas de desafíos y proyectos, obtendrás un Certificado de Desarrollo de Pila Completa. Te ofreceremos gratuitamente una práctica en entrevistas para desarrolladores. Incluso ofrecemos un directorio de trabajos donde los empleadores contratan específicamente campistas que han recibido certificaciones de Free Code Camp.",
"" ""
] ]
],
"titleDe": "Lerne wie Free Code Camp funktioniert",
"descriptionDe": [
[
"//i.imgur.com/6ibIavQ.jpg",
"Ein Bild von den 4 Vorteilen von Free Code Camp: Vernetz Dich, Lerne Javascript, Bau ein Portfolio auf, Hilf Non-Profit-Organisationen",
"Willkommen bei Free Code Camp. Wir sind eine Open Source Gemeinschaft von motivierten Leuten, die programmieren lernen und Non-Profit-Organisationen helfen",
""
],
[
"//i.imgur.com/Elb3dfj.jpg",
"Ein Screenshot von einigen unserer Camper beim gemeinsamen Programmieren in Toronto.",
"<bold>Programmieren zu lernen ist hart.</bold> Um erfolgreich zu sein brauchst du viel Übung und Unterstützung. Deswegen haben wir ein umfangreiches Curriculum und eine unterstützende Gemeinschaft geschaffen.",
""
],
[
"//i.imgur.com/D7Y5luw.jpg",
"Ein Graph vom Verhältnis der Wachstumsrate von Jobs gegenüber der Abschlüsse von Informatik Studien. Es gibts 1,4 Millionen Jobs aber nur 400.000 Leute um diese zu füllen.",
"Es gibt tausende von unbesetzen Programmierjobs und die Nachfrage wächst jedes Jahr",
""
],
[
"//i.imgur.com/WD3STY6.jpg",
"Foto von drei Campern die einen Job bekommen haben nachdem sie bei Free Code Camp programmieren gelernt haben",
"Free Code Camp ist ein sicherer Weg zu deinem ersten Programmierjob. Tatsächlich hat noch niemand unser komplettes Programm beendet, weil Campers bereits davor Jobs finden.",
""
],
[
"//i.imgur.com/vLNso6h.jpg",
"Eine Illustration die zeigt dass du HTML5, CSS3, JavaScript, Datenbanken, Git, Node.js, React und D3 lernen wirst",
"Wir haben hunderte von optionalen Programmieraufgaben die dir die fundamentalen Webentwicklungstechnologien wie HTML5, Node.js und Datanbanken beibringen werden.",
""
],
[
"//i.imgur.com/UVB9hxp.jpg",
"Ein Foto von einem Camper in einem Cafe der an Free Code Camp Projekten arbeitet.",
"Wir glauben dass Menschen am Besten beim Tun lernen. Deswegen wirst du die meiste Zeit damit beschäftigt sein an tatsächlichen Projekten zu arbeiten. Wir werden dir eine Liste an Anforderungen (agile User Stories) geben und du wirst dich damit auseinander setzen diese zu erfüllen.",
""
],
[
"//i.imgur.com/pbW7K5S.jpg",
"Ein Bild auf dem man unsere Frontend-, Backend- und Daten Visualisierungzertifikate (je 400 Stunden), unsere Non-Profit-Projekte (800 Stunden) und Bewerbungsgesprächsvorbereitung (80 Stunden) sieht mit einer Summe von 2080 Stunden Programmiererfahrung.",
"Unser Curriculum ist in 4 Zertifikate aufgeteilt. Diese Zertifikate sind standardisiert und jederzeit von deinen Kunden oder zukünftigen Arbeitgeber überprüfbar. Wie alles andere auch bei Free Code Camp sind die Zertifikate gratis. Wir empfehlen sie in der vorgesehenen Reihenfolge zu machen, aber es steht dir offen frei zu wählen. Die ersten drei Zertifikate dauern jeweils 400 Stunden. Das letzte Zertifikat dauert 800 Stunden und beinhaltet die Umsetzung eines echten Projektes für eine Non-Profit-Organisation.",
""
],
[
"//i.imgur.com/k8btNUB.jpg",
"Ein Screenshot von unserem Frontendzertifikat",
"Um sich unser geprüftes Frontend-Entwicklungszertifikat zu verdienen, wirst du 10 Projekte mit HTML, CSS, jQuery und Javascript umsetzen.",
""
],
[
"//i.imgur.com/Et3iD74.jpg",
"Ein Screenshot von unserem Datenvisualisierungszertifikat",
"Für unser Datenvisualisierungszertifikat, wirst du 10 Projekte mit React, Sass und D3.js umsetzen.",
""
],
[
"//i.imgur.com/8v3t84p.jpg",
"Ein Screenshot von unserem Backend-Entwicklungszertifikat",
"Um unser Backend-Entwicklungszertifikat zu erhalten, wirst du 10 Projekte mit Node.js, Express und MongoDB umsetzen. Du wirst Git und Heroku verwenden um sie in der Cloud zu veröffentlichen.",
""
],
[
"//i.imgur.com/yXyxbDd.jpg",
"Ein Screenshot von unserem Non-Profit-Verzeichnis",
"Nachdem du alle drei von diesen Zertifikaten abgeschlossen hast, wirst du mit einem anderen Camper zusammen Methoden der agilen Softwareentwicklung verwenden und zwei echte Projekte für Non-Profit-Organisationen umsetzen. Außerdem wirst du zwei bereits existierende Non-Profit-Projekte um neue Funktionalität erweitern. Wenn du fertig bist, wirst du ein Portfolio mit zwei echten Apps besitzen, die täglich von Leuten genutzt werden.",
""
],
[
"//i.imgur.com/PDGQ9ZM.jpg",
"Ein Foto von Campern die zusammen in einem Cafe in Seoul an einem Projekt arbeiten.",
"Wenn du alle 2080 Stunden an Aufgaben und Projekten absolviert hast, hast du dir unser Full Stack Development Zertifikat verdient. Wir bieten dir dann ein gratis Bewerbungstraining an. Außerdem haben wir eine Jobbörse, wo Arbeitsgeber Camper einstellen die Free Code Camp Zertifikate erhalten haben.",
""
]
] ]
}, },
{ {
@ -242,18 +317,18 @@
[ [
"//i.imgur.com/EAR7Lvh.jpg", "//i.imgur.com/EAR7Lvh.jpg",
"Gitterチャットルームの一場面です。", "Gitterチャットルームの一場面です。",
"コーディングを始める前に、Free Code Camp のチャットルームに参加してください。いつでも、雑談や質問ができたりペアプログラミングをするための仲間を見つけ流ことができます。最初に Github アカウントが必要です。", "コーディングを始める前に、Free Code Camp のチャットルームに参加してください。いつでも、雑談や質問ができたりペアプログラミングをするための仲間を見つけ流ことができます。最初に GitHub アカウントが必要です。",
"" ""
], ],
[ [
"//i.imgur.com/n6GeSEm.gif", "//i.imgur.com/n6GeSEm.gif",
"この gif は Github を開始するまでの流れを表しています。必要な欄に情報を入れて登録をしてください。そして Github からあなたのメールアドレス宛にメールが届きますのでアカウントを承認してください。", "この gif は GitHub を開始するまでの流れを表しています。必要な欄に情報を入れて登録をしてください。そして GitHub からあなたのメールアドレス宛にメールが届きますのでアカウントを承認してください。",
"\"Open link in new tab\"をクリックして Github を開いてください。 必要な欄に情報を入力して GitHub アカウントを作ってください。実際に使われている email アドレスかを確認してください( GitHub にはこの情報が保存されます )。メールアドレス宛に GitHub からメールが来たことを確認してください。 メールにある\"verify email address\"をクリックして開いてください。<br><div class=\"small\">注意: もしすでに GitHub アカウントを持っていたら、あなたは \"Open link in new tab\" をクリックすることでこのステップを飛ばすことができます、新しく開かれたタブを閉じて \"go to my next step\" をクリックしてください。私たちはこの大事なステップが飛ばされてしまうのを防ぐために \"このステップを飛ばす\" ボタンは削除してあります。</div>", "\"Open link in new tab\"をクリックして GitHub を開いてください。 必要な欄に情報を入力して GitHub アカウントを作ってください。実際に使われている email アドレスかを確認してください( GitHub にはこの情報が保存されます )。メールアドレス宛に GitHub からメールが来たことを確認してください。 メールにある\"verify email address\"をクリックして開いてください。<br><div class=\"small\">注意: もしすでに GitHub アカウントを持っていたら、あなたは \"Open link in new tab\" をクリックすることでこのステップを飛ばすことができます、新しく開かれたタブを閉じて \"go to my next step\" をクリックしてください。私たちはこの大事なステップが飛ばされてしまうのを防ぐために \"このステップを飛ばす\" ボタンは削除してあります。</div>",
"https://github.com/join" "https://github.com/join"
], ],
[ [
"//i.imgur.com/hFqAEr8.gif", "//i.imgur.com/hFqAEr8.gif",
"この gif は Github の右上にあるプロフィール画像をクリックする方法です。あなたの写真をアップロードするか、自動で生成されるピクセルアートを利用してください。そして、残りの欄に情報を入力し submit ボタンを押してください。", "この gif は GitHub の右上にあるプロフィール画像をクリックする方法です。あなたの写真をアップロードするか、自動で生成されるピクセルアートを利用してください。そして、残りの欄に情報を入力し submit ボタンを押してください。",
"GitHub の右上に表示されているピクセルアートをクリックしてください、そして settings を選んでください。あなたの画像をアップロードしてください。画像はあなたの顔が写っていると良いです。他のキャンパーズの仲間たちがチャットルームであなたを見かけるようになります。住んでいる場所や名前を登録することもできます", "GitHub の右上に表示されているピクセルアートをクリックしてください、そして settings を選んでください。あなたの画像をアップロードしてください。画像はあなたの顔が写っていると良いです。他のキャンパーズの仲間たちがチャットルームであなたを見かけるようになります。住んでいる場所や名前を登録することもできます",
"https://github.com/settings/profile" "https://github.com/settings/profile"
], ],
@ -266,7 +341,7 @@
[ [
"//i.imgur.com/OmRmLB4.gif", "//i.imgur.com/OmRmLB4.gif",
"この git は私たちのチャットルームへのリンクをクリックして、\"sign in with GitHub\" ボタンをクリックしています。そして、テキストを入力してキャンパーズの仲間へメッセージを送る方法を表しています。", "この git は私たちのチャットルームへのリンクをクリックして、\"sign in with GitHub\" ボタンをクリックしています。そして、テキストを入力してキャンパーズの仲間へメッセージを送る方法を表しています。",
"あなたは Github のアカウントを持っているので、私たちのチャットルームへ GitHub を利用してログインできます。\"Hellow world!\" と言って自己紹介をし、あなたがどうやって Free Code Camp を見つけたかや何故プログラミングを学びたいのかを私たちに話してください。", "あなたは GitHub のアカウントを持っているので、私たちのチャットルームへ GitHub を利用してログインできます。\"Hellow world!\" と言って自己紹介をし、あなたがどうやって Free Code Camp を見つけたかや何故プログラミングを学びたいのかを私たちに話してください。",
"https://gitter.im/FreeCodeCamp/FreeCodeCamp" "https://gitter.im/FreeCodeCamp/FreeCodeCamp"
], ],
[ [
@ -470,6 +545,63 @@
] ]
], ],
"titleJa": "Githubアカウントを作成し、チャットに参加しましょう", "titleJa": "Githubアカウントを作成し、チャットに参加しましょう",
"titleDe": "Erstelle einen GitHub Account und tritt unserem Chat bei",
"descriptionDe": [
[
"//i.imgur.com/EAR7Lvh.jpg",
"Ein Screenshot von einem userer Gitter Chats.",
"Bevor wir zu programmieren beginnen, lass uns den Free Code Camp Chats beitreten. Hier kannst du zu jeder Tageszeit kommen, Fragen stellen oder einen anderen Camper suchen um gemeinsam zu programmieren. Doch zuerst benötigst du einen GitHub Account.",
""
],
[
"//i.imgur.com/n6GeSEm.gif",
"Ein GIF das zeigt wie der unten stehenden Link angeklickt wird um auf GitHub zu kommen. Füll die notwendigen Felder aus und bestätige. Dann schau in deine Mails nach einer Nachricht von GitHub um deinen Account zu verifizieren.",
"Klicke unten auf den \"Link in neuem Tab öffnen\" Button um GitHub zu öffnen. Erstelle einen GitHub Account indem du die Felder in dem Formular ausfüllst. Überprüfe ob du deine echte Emailadresse verwendest - GitHub wird sie nicht weitergeben. Dann suche in deinem Posteingang nach einer Nachricht von GitHub. Öffne sie und klicke den darin befindenden \"Emailadresse bestätigen\" Button. <br><div class=\"small\">Hinweis: Wenn du bereits einen GitHub Account besitzt, kannst du diesen Schritt überspringen, indem du \"Link in neuem Tab öffnen\" drückst, den neuen Tab schließt und dann auf \"Gehe zu nächstem Schritt\" klickst. Wir haben den \"Schritt überspringen\" Button entfernt weil viele Leute sich einfach durchgeklickt haben ohne diese wichtigen Schritte zu tun</div>",
"https://github.com/join"
],
[
"//i.imgur.com/hFqAEr8.gif",
"Ein GIF das dir zeigt wie man sein Profilebild im rechten oberen Eck von GitHub anklickt. Lade ein Foto von dir hoch oder verwende weiterhin das automatisch generierte Pixelbild. Dann fülle die übrigen Formularfelder aus und klicke auf Bestätigung.",
"Klicke auf das Pixel-Art Bild in der rechten oberen Ecke von GitHub, dann gehe auf Einstellungen (settings). Lade ein Bild von dir hoch. Ein Foto von deinem Gesicht bietet sich am Besten an. So sehen dich die anderen Camper im Chat, also mach dich schick. Du kannst deine Stadt und deinen Namen hinzufügen, falls du willst.",
"https://github.com/settings/profile"
],
[
"//i.imgur.com/pYk0wOk.gif",
"Ein GIF das dir zeigt wie man einem GitHub Repository einen Stern gibt",
"Öffne Free Code Camp's open-source Repository. Hier arbeitet das ehrenamtliche Team zusammen an Free Code Camp. Du kannst unserem Repositoy einen Stern geben. Das ist das GitHub Äquivalent für etwas \"liken\"",
"https://github.com/freecodecamp/freecodecamp"
],
[
"//i.imgur.com/OmRmLB4.gif",
"Ein GIF das dir zeigt wie der unten stehende Link geklickt, auf den Chat weitergeleitet und mit dem \"Melde dich mit GitHub an\" Button man angemeldet wird. Dann kannst du auf das Textfeld klicken und eine Nachricht an andere Camper schicken",
"Jetzt, da du einen GitHub Account besitzt, kannst du unserem Hauptchat beitreten indem du dich mit GitHub anmeldest. Stell dich vor indem du \"Hello World\" schreibst. Erzähl den anderen Campern wie du Free Code Camp gefunden hast. Außerdem könntest du uns erzählen warum du programmieren lernen willst.",
"https://gitter.im/FreeCodeCamp/FreeCodeCamp"
],
[
"//i.imgur.com/Ecs5XAd.gif",
"Ein Gif das dir zeigt wie man den Einstellungsbutton im oberen rechten Eck anklickt und die Benachrichtigungseinstellungen ändert.",
"Unsere Chats sind sehr aktiv. Du solltest die Einstellungen ändern, damit du nur benachrichtigt wirst falls dich jemand erwähnt",
""
],
[
"//i.imgur.com/T0bGJPe.gif",
"Ein GIF das dir zeigt wie man ein Profilbild von einem anderen User anklickt um eine private Nachricht zu versenden.",
"Sei dir bitte bewusst, dass alle unsere Chats komplett öffentlich sind. Falls du also sensible Informationen, wie zum Beispiel Emailadressen oder Telefonnummern, austauschen willst, verwende Privatnachrichten.",
""
],
[
"//i.imgur.com/vDTMJSh.gif",
"Ein GIF das dir zeigt, dass du mithilfe mehrerer Tabs zwischen Aufgaben und dem Chat hin und her wechseln kannst",
"Halte den Chat offen, während du an den Aufgaben arbeitest. So kannst du jederzeit nach Hilfe fragen falls du nicht weiterkommst. Außerdem kannst du dich mit anderen Campern unterhalten falls du eine Pause brauchst.",
""
],
[
"//i.imgur.com/WvQvNGN.gif",
"Ein GIF das dir zeigt wie du den den untenstehenden Link klickst um die native Chatapp für deinen Computer herunterzuladen.",
"Du kannst dir auch die Chatapp für deinen Computer oder dein Smartphone herunterladen.",
"https://gitter.im/apps"
]
],
"challengeType": 7 "challengeType": 7
}, },
{ {
@ -495,6 +627,24 @@
"Dale un vistazo de tu portafolio de código. Pulsa en tu imagen en la esquina superior derecha. Para activar tu portafolio de código, necesitaras conectar tu cuenta de GitHub con Free Code Camp. Tu portafolio de código muestra tu progreso y cuantos Puntos Cafés tienes. Puedes obtener Puntos Cafés completando desafíos y ayudando a otros campistas en nuestras salas de chat. Si obtienes Puntos Cafés varios días consecutivos, obtendrás una racha.", "Dale un vistazo de tu portafolio de código. Pulsa en tu imagen en la esquina superior derecha. Para activar tu portafolio de código, necesitaras conectar tu cuenta de GitHub con Free Code Camp. Tu portafolio de código muestra tu progreso y cuantos Puntos Cafés tienes. Puedes obtener Puntos Cafés completando desafíos y ayudando a otros campistas en nuestras salas de chat. Si obtienes Puntos Cafés varios días consecutivos, obtendrás una racha.",
"" ""
] ]
],
"titleDe": "Erstelle dein Code Portfolio",
"descriptionDe": [
[
"//i.imgur.com/tP2ccTE.gif",
"Ein GIF das dir zeigt wie man sein Profilbild in der rechten oberen Ecke anklickt um zu deinem Code Portfolio zu gelangen und mit GitHub zu verbinden",
"Schau dir dein Code Portfolio an. Klick auf dein Profilbild in der rechten oberen Ecke. Um dein Portfolio zu aktivieren musst du deinen GitHub Account mit Free Code Camp verbinden. Dein Code Portfolio zeigt deinen Fortschritt und wieviele Brownie Punkte du hast. Du bekommst Brownie Punkte wenn du Aufgaben löst oder anderen Campern im Chat hilfst. Wenn du an mehreren Tagen in Folge Brownie Punkte erhälst bekommst du einen \"streak\"",
""
]
],
"titleFr": "Configurer votre code portefeuille",
"descriptionFr": [
[
"//i.imgur.com/tP2ccTE.gif",
"Un gif montrant comment vous pouvez cliquez sur l'image de votre profil dans votre coin supérieur droit à votre code portefeuille et connectez GitHub.",
"Vérifiez votre code portefeuille. Cliquez sur votre photo dans votre coin supérieur droit. Pour activer votre code portefeuille, vous'll nécessité de lier votre compte avec code sans GitHub Camp. Votre code portefeuille affiche votre progression et combien de bons points vous avez. Vous pouvez obtenir de bons points par remplir les défis et en aidant d'autres campeurs dans nos salles de chat. Si vous obtenez Brownie Points sur plusieurs jours d'affilée, vous'll obtenez une rayure.",
""
]
] ]
}, },
{ {
@ -518,15 +668,6 @@
"tests": [], "tests": [],
"type": "Waypoint", "type": "Waypoint",
"challengeType": 7, "challengeType": 7,
"titleFr": "Configurer votre code portefeuille",
"descriptionFr": [
[
"//i.imgur.com/tP2ccTE.gif",
"Un gif montrant comment vous pouvez cliquez sur l'image de votre profil dans votre coin supérieur droit à votre code portefeuille et connectez GitHub.",
"Vérifiez votre code portefeuille. Cliquez sur votre photo dans votre coin supérieur droit. Pour activer votre code portefeuille, vous'll nécessité de lier votre compte avec code sans GitHub Camp. Votre code portefeuille affiche votre progression et combien de bons points vous avez. Vous pouvez obtenir de bons points par remplir les défis et en aidant d'autres campeurs dans nos salles de chat. Si vous obtenez Brownie Points sur plusieurs jours d'affilée, vous'll obtenez une rayure.",
""
]
],
"titleEs": "Únete a un Campamento en Tu Ciudad", "titleEs": "Únete a un Campamento en Tu Ciudad",
"descriptionEs": [ "descriptionEs": [
[ [
@ -541,6 +682,21 @@
"Encuentra tu ciudad en esta lista y haz clic en esta. Esto te llevara al grupo de Facebook del Campamento de tu ciudad. Da clic en el botón de \"Unirse al grupo\" para unirte a el grupo. Alguien del mismo campamento debería aprobarte en breve. Si tu ciudad no esta en esta lista, ve al final del articulo de la wiki para ver instrucciones de como crear un campamento para tu ciudad.", "Encuentra tu ciudad en esta lista y haz clic en esta. Esto te llevara al grupo de Facebook del Campamento de tu ciudad. Da clic en el botón de \"Unirse al grupo\" para unirte a el grupo. Alguien del mismo campamento debería aprobarte en breve. Si tu ciudad no esta en esta lista, ve al final del articulo de la wiki para ver instrucciones de como crear un campamento para tu ciudad.",
"https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites" "https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites"
] ]
],
"titleDe": "Tritt einem Campsite in deiner Stadt bei",
"descriptionDe": [
[
"//i.imgur.com/XugIMb4.jpg",
"Ein Foto von einigen Campern bei einem Treffen in einem lokalen Cafe.",
"Unsere Campsites sind Facebook Gruppen die dir helfen dich mit anderen Campern aus deiner Stadt zu treffen. Du kannst diese Gruppen verwenden um an \"Coffee-and-Code\" Treffen, wo du andere Camper in einem Cafe triffst um gemeinsam zu programmieren, teilzunehmen oder zu organisieren",
""
],
[
"//i.imgur.com/fTFMjwf.gif",
"Ein GIF das zeigt wie du auf den untenstehenden Link klickst, deine Stadt aus der Liste aller Campsites suchst, auf den Facebook Link klickst und der Facebook Gruppe beitrittst.",
"Finde deine Stadt auf dieser Liste und klick sie an. Du wirst auf die Facebook Gruppe des Campsites deiner Stadt geleitet. Klick den \"Gruppe beitreten\" Button um eine Beitrittsanfrage zu stellen. Jemand aus der Gruppe sollte dich in kürzester Zeit annehmen. Falls deine Stadt nicht auf der Liste ist, scrolle zum Ende des Wiki Artikels für eine Anleitung wie du ein Campsite für deine Stadt erstellst.",
"https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites"
]
] ]
}, },
{ {
@ -701,7 +857,59 @@
"Ahora estas listo para empezar a programar. El botón de \"Mapa\" en tu esquina superior derecha te mostrará nuestro mapa de desafíos. Te recomendaos que completes los desafíos de arriba hacía abajo, a un ritmo sostenible. Nuestra comunidad de código abierto esta constantemente mejorando nuestros desafíos, así que no te sorprendas si cambian o se mueven alrededor. No te preocupes por volver hacia atrás - solo continúa avanzando. Siempre puedes ir a tu desafío más reciente pulsando el botón de \"Aprender\".", "Ahora estas listo para empezar a programar. El botón de \"Mapa\" en tu esquina superior derecha te mostrará nuestro mapa de desafíos. Te recomendaos que completes los desafíos de arriba hacía abajo, a un ritmo sostenible. Nuestra comunidad de código abierto esta constantemente mejorando nuestros desafíos, así que no te sorprendas si cambian o se mueven alrededor. No te preocupes por volver hacia atrás - solo continúa avanzando. Siempre puedes ir a tu desafío más reciente pulsando el botón de \"Aprender\".",
"" ""
] ]
],
"titleDe": "Lerne was du tun kannst falls du nicht weiterkommst",
"descriptionDe": [
[
"//i.imgur.com/lzKvwU2.jpg",
"Der Text \"Coding is hard.\"",
"Programmieren ist hart. Du wirst zeitweise nicht weiterkommen. Sogar erfahrene Programmierer bleiben manchmal hängen. Der Schlüssel zum Erfolg ist zu wissen wie man in so einer Situation weitermacht",
""
],
[
"//i.imgur.com/sfsidp6.jpg",
"Der Text \"It takes time to get good at coding.\"",
"Es dauert seine Zeit bis man gut programmieren kann. Du erwartest auch nicht einen Schachmeister nach 3 Monaten Übung zu schlagen. Erwarte also auch nicht das nächste Facebook nach 3 Monaten zu programmieren",
""
],
[
"//i.imgur.com/EoTfOyC.jpg",
"Ein Foto von einigen Campern die gemeinsam in Montreal programmieren.",
"Übe programmieren jeden Tag und triff dich mit anderen Leuten die programmieren, dann wirst du bereit für einen Programmierjob.",
""
],
[
"//i.imgur.com/EWWZBag.jpg",
"Ein Bild mit dem Text \"1. Read the error 2. Search Google 3. Ask for help.",
"Wann immer du nicht weiterkommst oder nicht weißt was du als nächstes tun sollst: Lesen-Suchen-Fragen",
""
],
[
"//i.imgur.com/99BfAcK.jpg",
"Ein Bild von der jQuery Dokumentation",
"Ließ zuerst die Dokumentation oder Fehlermeldung. Eine Schlüsselfähigkeit von guten Programmierern ist die ist die Fähigkeit zu interpretieren und dann Anweisungen zu folgen",
""
],
[
"//i.imgur.com/GxvrsFb.gif",
"Ein GIF das eine erweiterte Google Suche zeigt. Zuerst wird die Suchanfrage \"jquery doesn't run when my page loads\" eingegeben. Dann wird in den Suchoptionen die Auswahl \"Beliebige Zeit\" zu \"Letztes Jahr\" geändert. Dann wird auf ein Ergebnis geklickt, der Artikel gelesen und die Antwort gefunden",
"Wenn das nicht geholfen hat, durchsuche Google. Gute Google Abfragen brauchen einiges an Übung. Wenn du Google durchsuchst, wirst du normalerweise die Programmiersprache oder das Framework, das du verwendest, inkludieren. Außerdem solltest du die Ergebnisse auf einen aktuellen Zeitraum limitieren.",
""
],
[
"//i.imgur.com/LZYU7p2.gif",
"Ein GIF das zeigt wie der untenstehende Link aufgerufen wird um in den \"Help Chat\" zu kommen um dort zu fragen: \"jquery doesn't run when my page loads\".",
"Falls das nicht geholfen hat, frag deine Freunde. Wenn du Probleme hast kannst du die anderen Camper in unserem Hilfe Chat fragen.",
"https://gitter.im/FreeCodeCamp/Help"
],
[
"//i.imgur.com/ZRgXraT.gif",
"Ein GIF das zeigt wie durch die Challenge Übersicht gescrollt wird",
"Jetzt bist du bereit mit Programmieren zu starten. Der \"Map\" Button in der rechten oberen Ecke zeigt dir deine Challenge Übersicht. Wir empfehlen dir diese von Oben nach Unten in einer angemessenen Geschwindikeit durchzuführen. Unsere Open-Source Gemeinschaft ist permanent am Verbessern der Challenges, wundere dich also nicht falls diese sich ändern oder verschieben. Hab keine Angst davor zurück zu gehen - schau nur dass du vorankommst. Du kommst immer zu deiner aktuellsten Aufgabe indem du den \"Learn\" Button drückst.",
""
]
] ]
} }
] ]
} }

View File

@ -311,10 +311,11 @@
"id": "a2f1d72d9b908d0bd72bb9f6", "id": "a2f1d72d9b908d0bd72bb9f6",
"title": "Make a Person", "title": "Make a Person",
"description": [ "description": [
"Fill in the object constructor with the methods specified in the tests.", "Fill in the object constructor with the following methods below:",
"Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast).", "<blockquote>getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)</blockquote>",
"All functions that take an argument have an arity of 1, and the argument will be a string.", "Run the tests to see the expected output for each method.",
"These methods must be the only available means for interacting with the object.", "The methods that take an argument must accept only one argument and it has to be a string.",
"These methods must be the only available means of interacting with the object.",
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
@ -350,11 +351,12 @@
"challengeType": 5, "challengeType": 5,
"titleEs": "Crea una Persona", "titleEs": "Crea una Persona",
"descriptionEs": [ "descriptionEs": [
"Completa el constructor de objetos con los métodos especificados en las pruebas.", "Completa el constructor de objetos con los métodos especificados a continuación:",
"Los métodos son: getFirstName(), getLastName(), getFullName(), setFirstName(first), setLastName(last), y setFullName(firstAndLast). ", "<blockquote>getFirstName()\ngetLastName()\ngetFullName()\nsetFirstName(first)\nsetLastName(last)\nsetFullName(firstAndLast)</blockquote>",
"Todas las funciones que aceptan un argumento tienen una aridad de 1, y el argumento es una cadena de texto", "Ejecuta las pruebas para ver el resultado esperado de cada método.",
"Estos métodos deben ser el único medio para interactuar con el objeto", "Las funciones que aceptan argumentos deben aceptar sólo uno, y este tiene que ser una cadena.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Estos métodos deben ser el único medio para interactuar con el objeto.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
] ]
}, },
{ {

View File

@ -46,9 +46,9 @@
"id": "bd7123c9c443eddfaeb5bdef", "id": "bd7123c9c443eddfaeb5bdef",
"title": "Declare JavaScript Variables", "title": "Declare JavaScript Variables",
"description": [ "description": [
"In computer science, <code>data</code> is anything that is meaningful to the computer. JavaScript provides seven different <dfn>data types</dfn> which are <code>undefined</code>, <code>null</code>, <code>Boolean</code>, <code>string</code>, <code>symbol</code>, <code>number</code>, and <code>object</code>.", "In computer science, <dfn>data</dfn> is anything that is meaningful to the computer. JavaScript provides seven different <dfn>data types</dfn> which are <code>undefined</code>, <code>null</code>, <code>Boolean</code>, <code>string</code>, <code>symbol</code>, <code>number</code>, and <code>object</code>.",
"For example, computers distinguish between numbers, such as the number <code>12</code>, and <code>strings</code>, such as <code>\"12\"</code>, <code>\"dog\"</code>, or <code>\"123 cats\"</code>, which are collections of characters. Computers can perform mathematical operations on a number, but not on a string.", "For example, computers distinguish between numbers, such as the number <code>12</code>, and <code>strings</code>, such as <code>\"12\"</code>, <code>\"dog\"</code>, or <code>\"123 cats\"</code>, which are collections of characters. Computers can perform mathematical operations on a number, but not on a string.",
"<code>Variables</code> allow computers to store data in a dynamic fashion, rather than updating a formula every time the data changes. Any of the seven different data types may be stored in a variable.", "<dfn>Variables</dfn> allow computers to store and manipulate data in a dynamic fashion. They do this by using a \"label\" to point to the data rather than using the data itself. Any of the seven data types may be stored in a variable.",
"<code>Variables</code> are similar to the x and y variables you use in mathematics, which means they're a simple name to represent the data we want to refer to. Computer <code>variables</code> differ from mathematical variables in that they can store different values at different times.", "<code>Variables</code> are similar to the x and y variables you use in mathematics, which means they're a simple name to represent the data we want to refer to. Computer <code>variables</code> differ from mathematical variables in that they can store different values at different times.",
"We tell JavaScript to create or <dfn>declare</dfn> a variable by putting the keyword <code>var</code> in front of it, like so:", "We tell JavaScript to create or <dfn>declare</dfn> a variable by putting the keyword <code>var</code> in front of it, like so:",
"<blockquote>var ourName;</blockquote>", "<blockquote>var ourName;</blockquote>",
@ -443,6 +443,7 @@
], ],
"tests": [ "tests": [
"assert(myVar === 88, 'message: <code>myVar</code> should equal <code>88</code>');", "assert(myVar === 88, 'message: <code>myVar</code> should equal <code>88</code>');",
"assert(/myVar\\s*\\=.*myVar/.test(code) === false, 'message: <code>myVar = myVar</code> should be changed');",
"assert(/myVar\\s*[+]{2}/.test(code), 'message: Use the <code>++</code> operator');", "assert(/myVar\\s*[+]{2}/.test(code), 'message: Use the <code>++</code> operator');",
"assert(/var myVar = 87;/.test(code), 'message: Do not change code above the line');" "assert(/var myVar = 87;/.test(code), 'message: Do not change code above the line');"
], ],
@ -853,22 +854,19 @@
"id": "56533eb9ac21ba0edf2244b3", "id": "56533eb9ac21ba0edf2244b3",
"title": "Convert Celsius to Fahrenheit", "title": "Convert Celsius to Fahrenheit",
"description": [ "description": [
"To test your learning you will create a solution \"from scratch\". Place your code between the indicated lines and it will be tested against multiple test cases.", "To test your learning, you will create a solution \"from scratch\". Place your code between the indicated lines and it will be tested against multiple test cases.",
"The algorithm to convert from Celsius to Fahrenheit is the temperature in Celsius times 9/5, plus 32.", "The algorithm to convert from Celsius to Fahrenheit is the temperature in Celsius times <code>9/5</code>, plus <code>32</code>.",
"You are given a variable <code>celsius</code> representing a temperature in Celsius. Create a variable <code>fahrenheit</code> and apply the algorithm to assign it the corresponding temperature in Fahrenheit." "You are given a variable <code>celsius</code> representing a temperature in Celsius. Create a variable <code>fahrenheit</code> and apply the algorithm to assign it the corresponding temperature in Fahrenheit.",
"<strong>Note</strong><br>Don't worry too much about the <code>function</code> and <code>return</code> statements as they will be covered in future challenges. For now, only use operators that you have already learned."
], ],
"releasedOn": "January 1, 2016", "releasedOn": "January 1, 2016",
"challengeSeed": [ "challengeSeed": [
"function convert(celsius) {", "function convert(celsius) {",
" // Only change code below this line", " // Only change code below this line",
" ", " ",
"", " ",
" // Only change code above this line", " // Only change code above this line",
" if ( typeof fahrenheit !== 'undefined' ) {", " return fahrenheit;",
" return fahrenheit;",
" } else {",
" return 'fahrenheit not defined';",
" }",
"}", "}",
"", "",
"// Change the inputs below to test your code", "// Change the inputs below to test your code",
@ -2264,23 +2262,24 @@
"<blockquote>function myTest() {<br> var loc = \"foo\";<br> console.log(loc);<br>}<br>myTest(); // \"foo\"<br>console.log(loc); // \"undefined\"</blockquote>", "<blockquote>function myTest() {<br> var loc = \"foo\";<br> console.log(loc);<br>}<br>myTest(); // \"foo\"<br>console.log(loc); // \"undefined\"</blockquote>",
"<code>loc</code> is not defined outside of the function.", "<code>loc</code> is not defined outside of the function.",
"<h4>Instructions</h4>", "<h4>Instructions</h4>",
"Declare a local variable <code>myVar</code> inside <code>myFunction</code>" "Declare a local variable <code>myVar</code> inside <code>myFunction</code>. Run the tests and then follow the instructions commented out in the editor.",
"<strong>Hint</strong><br>Refreshing the page may help if you get stuck."
], ],
"releasedOn": "January 1, 2016", "releasedOn": "January 1, 2016",
"head": [ "head": [
"var logOutput = \"\";", "var logOutput = \"\";",
"var originalConsole = console", "var originalConsole = console",
"function capture() {", "function capture() {",
" var nativeLog = console.log;", " var nativeLog = console.log;",
" console.log = function (message) {", " console.log = function (message) {",
" logOutput = message;", " logOutput = message;",
" if(nativeLog.apply) {", " if(nativeLog.apply) {",
" nativeLog.apply(originalConsole, arguments);", " nativeLog.apply(originalConsole, arguments);",
" } else {", " } else {",
" var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');", " var nativeMsg = Array.prototype.slice.apply(arguments).join(' ');",
" nativeLog(nativeMsg);", " nativeLog(nativeMsg);",
" }", " }",
" };", " };",
"}", "}",
"", "",
"function uncapture() {", "function uncapture() {",
@ -2297,11 +2296,11 @@
"}", "}",
"myFunction();", "myFunction();",
"", "",
"// run and check the console ", "// Run and check the console",
"// myVar is not defined outside of myFunction", "// myVar is not defined outside of myFunction",
"console.log(myVar);", "console.log(myVar);",
"", "",
"// now remove the console log line to pass the test", "// Now remove the console log line to pass the test",
"" ""
], ],
"tail": [ "tail": [
@ -3345,7 +3344,7 @@
"tests": [ "tests": [
"assert(code.match(/else/g).length > 3, 'message: You should have at least four <code>else</code> statements');", "assert(code.match(/else/g).length > 3, 'message: You should have at least four <code>else</code> statements');",
"assert(code.match(/if/g).length > 3, 'message: You should have at least four <code>if</code> statements');", "assert(code.match(/if/g).length > 3, 'message: You should have at least four <code>if</code> statements');",
"assert(code.match(/return/g).length >= 5, 'message: You should have at least five <code>return</code> statements');", "assert(code.match(/return/g).length >= 1, 'message: You should have at least one <code>return</code> statement');",
"assert(myTest(0) === \"Tiny\", 'message: <code>myTest(0)</code> should return \"Tiny\"');", "assert(myTest(0) === \"Tiny\", 'message: <code>myTest(0)</code> should return \"Tiny\"');",
"assert(myTest(4) === \"Tiny\", 'message: <code>myTest(4)</code> should return \"Tiny\"');", "assert(myTest(4) === \"Tiny\", 'message: <code>myTest(4)</code> should return \"Tiny\"');",
"assert(myTest(5) === \"Small\", 'message: <code>myTest(5)</code> should return \"Small\"');", "assert(myTest(5) === \"Small\", 'message: <code>myTest(5)</code> should return \"Small\"');",
@ -3778,6 +3777,7 @@
"assert((function(){ count = 0; cc(10);cc('J');cc('Q');cc('K');var out = cc('A'); if(out === \"-5 Hold\") {return true;} return false; })(), 'message: Cards Sequence 10, J, Q, K, A should return <code>\"-5 Hold\"</code>');", "assert((function(){ count = 0; cc(10);cc('J');cc('Q');cc('K');var out = cc('A'); if(out === \"-5 Hold\") {return true;} return false; })(), 'message: Cards Sequence 10, J, Q, K, A should return <code>\"-5 Hold\"</code>');",
"assert((function(){ count = 0; cc(3);cc(7);cc('Q');cc(8);var out = cc('A'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 7, Q, 8, A should return <code>\"-1 Hold\"</code>');", "assert((function(){ count = 0; cc(3);cc(7);cc('Q');cc(8);var out = cc('A'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 7, Q, 8, A should return <code>\"-1 Hold\"</code>');",
"assert((function(){ count = 0; cc(2);cc('J');cc(9);cc(2);var out = cc(7); if(out === \"1 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, J, 9, 2, 7 should return <code>\"1 Bet\"</code>');", "assert((function(){ count = 0; cc(2);cc('J');cc(9);cc(2);var out = cc(7); if(out === \"1 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, J, 9, 2, 7 should return <code>\"1 Bet\"</code>');",
"assert((function(){ count = 0; cc(2);cc(2);var out = cc(10); if(out === \"1 Bet\") {return true;} return false; })(), 'message: Cards Sequence 2, 2, 10 should return <code>\"1 Bet\"</code>');",
"assert((function(){ count = 0; cc(3);cc(2);cc('A');cc(10);var out = cc('K'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 2, A, 10, K should return <code>\"-1 Hold\"</code>');" "assert((function(){ count = 0; cc(3);cc(2);cc('A');cc(10);var out = cc('K'); if(out === \"-1 Hold\") {return true;} return false; })(), 'message: Cards Sequence 3, 2, A, 10, K should return <code>\"-1 Hold\"</code>');"
], ],
"type": "checkpoint", "type": "checkpoint",

View File

@ -104,102 +104,12 @@
"id": "bad87fee1348bd9acde08812", "id": "bad87fee1348bd9acde08812",
"title": "Make Images Mobile Responsive", "title": "Make Images Mobile Responsive",
"description": [ "description": [
"First, add a new image below the existing one. Set its <code>src</code> attribute to <code>http://bit.ly/fcc-running-cats</code>.", "First, add a new image below the existing one. Set its <code>src</code> attribute to <code>https://bit.ly/fcc-running-cats</code>.",
"It would be great if this image could be exactly the width of our phone's screen.", "It would be great if this image could be exactly the width of our phone's screen.",
"Fortunately, with Bootstrap, all we need to do is add the <code>img-responsive</code> class to your image. Do this, and the image should perfectly fit the width of your page." "Fortunately, with Bootstrap, all we need to do is add the <code>img-responsive</code> class to your image. Do this, and the image should perfectly fit the width of your page."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>",
" .red-text {",
" color: red;",
" }",
"",
" h2 {",
" font-family: Lobster, Monospace;",
" }",
"",
" p {",
" font-size: 16px;",
" font-family: Monospace;",
" }",
"",
" .thick-green-border {",
" border-color: green;",
" border-width: 10px;",
" border-style: solid;",
" border-radius: 50%;",
" }",
"",
" .smaller-image {",
" width: 100px;",
" }",
"</style>",
"",
"<div class=\"container-fluid\">",
" <h2 class=\"red-text\">CatPhotoApp</h2>",
"",
" <p>Click here for <a href=\"#\">cat photos</a>.</p>",
"",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"http://bit.ly/fcc-relaxing-cat\"></a>",
"",
" <p>Things cats love:</p>",
" <ul>",
" <li>cat nip</li>",
" <li>laser pointers</li>",
" <li>lasagna</li>",
" </ul>",
" <p>Top 3 things cats hate:</p>",
" <ol>",
" <li>flea treatment</li>",
" <li>thunder</li>",
" <li>other cats</li>",
" </ol>",
" <form action=\"/submit-cat-photo\">",
" <label><input type=\"radio\" name=\"indoor-outdoor\"> Indoor</label>",
" <label><input type=\"radio\" name=\"indoor-outdoor\"> Outdoor</label>",
" <label><input type=\"checkbox\" name=\"personality\"> Loving</label>",
" <label><input type=\"checkbox\" name=\"personality\"> Lazy</label>",
" <label><input type=\"checkbox\" name=\"personality\"> Crazy</label>",
" <input type=\"text\" placeholder=\"cat photo URL\" required>",
" <button type=\"submit\">Submit</button>",
" </form>",
"</div>"
],
"tests": [
"assert($(\"img\").length === 2, 'message: You should have a total of two images.');",
"assert($(\"img:eq(1)\").hasClass(\"img-responsive\"), 'message: Your new image should be below your old one and have the class <code>img-responsive</code>.');",
"assert(!$(\"img:eq(1)\").hasClass(\"smaller-image\"), 'message: Your new image should not have the class <code>smaller-image</code>.');",
"assert($(\"img:eq(1)\").attr(\"src\") === \"http://bit.ly/fcc-running-cats\", 'message: Your new image should have a <code>src</code> of <code>http&#58;//bit.ly/fcc-running-cats</code>.');",
"assert(code.match(/<img/g) && code.match(/<img[^<]*>/g).length === 2 && code.match(/<img/g).length === 2, 'message: Make sure your new <code>img</code> element has a closing angle bracket.');"
],
"type": "waypoint",
"challengeType": 0,
"titleEs": "Haz que las imágenes sean adaptativas en dispositivos móviles",
"descriptionEs": [
"Primero, agrega una nueva imagen debajo que la que ya existe. Haz que su atributo <code>src</code> sea <code>http://bit.ly/fcc-running-cats</code>.",
"Sería genial si esta imagen fuera exactamente del tamaño de la pantalla de nuestro teléfono.",
"Afortunadamente, con Bootstrap, todo lo que tenemos que hacer es agregar la clase <code>img-responsive</code> a tu imagen. Hazlo, y verás que la imagen se ajustará perfectamente al ancho de tu página."
],
"nameFr": "Rendre des images adaptatives aux appareils mobiles",
"descriptionFr": [
"It would be great if this image could be exactly the width of our phone's screen.",
"Fortunately, with Bootstrap, all we need to do is add the <code>img-responsive</code> class to your image. Do this, and the image should perfectly fit the width of your page.",
"D'abord, ajoutez une nouvelle image en dessous de celle qui eiste dejà. Changez l'attribut <code>src</src> en <code>http://bit.ly/fcc-running-cats</code>.",
"Ce serait absolument super si notre image pouvait être exactement de la largeur de l'écran du téléphone.",
"Heureusement, avec Bootstrap, il faut seulement ajouter la classe <code>img-responsive</code> à notre image. Faites le, et l'image devrait s'ajuster parfaitement à la largeur de la page."
]
},
{
"id": "bad87fee1348bd8acde08812",
"title": "Center Text with Bootstrap",
"description": [
"Now that we're using Bootstrap, we can center our heading element to make it look better. All we need to do is add the class <code>text-center</code> to our <code>h2</code> element.",
"Remember that you can add several classes to the same element by separating each of them with a space, like this:",
"<code>&#60h2 class=\"red-text text-center\"&#62your text&#60/h2&#62</code>"
],
"challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -233,7 +143,97 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <p>Things cats love:</p>",
" <ul>",
" <li>cat nip</li>",
" <li>laser pointers</li>",
" <li>lasagna</li>",
" </ul>",
" <p>Top 3 things cats hate:</p>",
" <ol>",
" <li>flea treatment</li>",
" <li>thunder</li>",
" <li>other cats</li>",
" </ol>",
" <form action=\"/submit-cat-photo\">",
" <label><input type=\"radio\" name=\"indoor-outdoor\"> Indoor</label>",
" <label><input type=\"radio\" name=\"indoor-outdoor\"> Outdoor</label>",
" <label><input type=\"checkbox\" name=\"personality\"> Loving</label>",
" <label><input type=\"checkbox\" name=\"personality\"> Lazy</label>",
" <label><input type=\"checkbox\" name=\"personality\"> Crazy</label>",
" <input type=\"text\" placeholder=\"cat photo URL\" required>",
" <button type=\"submit\">Submit</button>",
" </form>",
"</div>"
],
"tests": [
"assert($(\"img\").length === 2, 'message: You should have a total of two images.');",
"assert($(\"img:eq(1)\").hasClass(\"img-responsive\"), 'message: Your new image should be below your old one and have the class <code>img-responsive</code>.');",
"assert(!$(\"img:eq(1)\").hasClass(\"smaller-image\"), 'message: Your new image should not have the class <code>smaller-image</code>.');",
"assert($(\"img:eq(1)\").attr(\"src\") === \"https://bit.ly/fcc-running-cats\", 'message: Your new image should have a <code>src</code> of <code>https&#58;//bit.ly/fcc-running-cats</code>.');",
"assert(code.match(/<img/g) && code.match(/<img[^<]*>/g).length === 2 && code.match(/<img/g).length === 2, 'message: Make sure your new <code>img</code> element has a closing angle bracket.');"
],
"type": "waypoint",
"challengeType": 0,
"titleEs": "Haz que las imágenes sean adaptativas en dispositivos móviles",
"descriptionEs": [
"Primero, agrega una nueva imagen debajo que la que ya existe. Haz que su atributo <code>src</code> sea <code>https://bit.ly/fcc-running-cats</code>.",
"Sería genial si esta imagen fuera exactamente del tamaño de la pantalla de nuestro teléfono.",
"Afortunadamente, con Bootstrap, todo lo que tenemos que hacer es agregar la clase <code>img-responsive</code> a tu imagen. Hazlo, y verás que la imagen se ajustará perfectamente al ancho de tu página."
],
"nameFr": "Rendre des images adaptatives aux appareils mobiles",
"descriptionFr": [
"It would be great if this image could be exactly the width of our phone's screen.",
"Fortunately, with Bootstrap, all we need to do is add the <code>img-responsive</code> class to your image. Do this, and the image should perfectly fit the width of your page.",
"D'abord, ajoutez une nouvelle image en dessous de celle qui eiste dejà. Changez l'attribut <code>src</src> en <code>https://bit.ly/fcc-running-cats</code>.",
"Ce serait absolument super si notre image pouvait être exactement de la largeur de l'écran du téléphone.",
"Heureusement, avec Bootstrap, il faut seulement ajouter la classe <code>img-responsive</code> à notre image. Faites le, et l'image devrait s'ajuster parfaitement à la largeur de la page."
]
},
{
"id": "bad87fee1348bd8acde08812",
"title": "Center Text with Bootstrap",
"description": [
"Now that we're using Bootstrap, we can center our heading element to make it look better. All we need to do is add the class <code>text-center</code> to our <code>h2</code> element.",
"Remember that you can add several classes to the same element by separating each of them with a space, like this:",
"<code>&#60h2 class=\"red-text text-center\"&#62your text&#60/h2&#62</code>"
],
"challengeSeed": [
"<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>",
" .red-text {",
" color: red;",
" }",
"",
" h2 {",
" font-family: Lobster, Monospace;",
" }",
"",
" p {",
" font-size: 16px;",
" font-family: Monospace;",
" }",
"",
" .thick-green-border {",
" border-color: green;",
" border-width: 10px;",
" border-style: solid;",
" border-radius: 50%;",
" }",
"",
" .smaller-image {",
" width: 100px;",
" }",
"</style>",
"",
"<div class=\"container-fluid\">",
" <h2 class=\"red-text\">CatPhotoApp</h2>",
"",
" <p>Click here for <a href=\"#\">cat photos</a>.</p>",
"",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"",
" <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <p>Things cats love:</p>", " <p>Things cats love:</p>",
" <ul>", " <ul>",
" <li>cat nip</li>", " <li>cat nip</li>",
@ -284,7 +284,7 @@
"Create a new <code>button</code> element below your large kitten photo. Give it the class <code>btn</code> and the text of \"Like\"." "Create a new <code>button</code> element below your large kitten photo. Give it the class <code>btn</code> and the text of \"Like\"."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -318,7 +318,7 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
"", "",
" <p>Things cats love:</p>", " <p>Things cats love:</p>",
" <ul>", " <ul>",
@ -372,7 +372,7 @@
"Add Bootstrap's <code>btn-block</code> class to your Bootstrap button." "Add Bootstrap's <code>btn-block</code> class to your Bootstrap button."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -406,7 +406,7 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <button class=\"btn\">Like</button>", " <button class=\"btn\">Like</button>",
" <p>Things cats love:</p>", " <p>Things cats love:</p>",
" <ul>", " <ul>",
@ -450,7 +450,7 @@
"descriptionFr": [ "descriptionFr": [
"Normalement, vos éléments <code>button</code> sont aussi large que le texte qu'ils contiennent. En les transformants en éléments blocs, vos boutons vont s'ajuster pour remplir l'intégralité de l'espace horizontal de la page et tous les éléments qui le suivront se placeront sur une \"nouvelle ligne\" en dessous du bloc.", "Normalement, vos éléments <code>button</code> sont aussi large que le texte qu'ils contiennent. En les transformants en éléments blocs, vos boutons vont s'ajuster pour remplir l'intégralité de l'espace horizontal de la page et tous les éléments qui le suivront se placeront sur une \"nouvelle ligne\" en dessous du bloc.",
"Cette image illustre la différence entre éléments <code>inline</code> (sans briser la ligne) et éléments <code>block-level</code> (en blocs)", "Cette image illustre la différence entre éléments <code>inline</code> (sans briser la ligne) et éléments <code>block-level</code> (en blocs)",
"<a href=\"http://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/O32cDWE.png\" title=\"Cliquez pour agrandir\" alt=\"Un bouton \"inline\" est aussi petit que le texte qu'il contient. Dans cette image, il est centré. En dessous de celui-ci il y a un bouton \"block-level\" , qui s'étire et remplit l'espace horizontal.'></a>", "<a href=\"https://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"https://i.imgur.com/O32cDWE.png\" title=\"Cliquez pour agrandir\" alt=\"Un bouton \"inline\" est aussi petit que le texte qu'il contient. Dans cette image, il est centré. En dessous de celui-ci il y a un bouton \"block-level\" , qui s'étire et remplit l'espace horizontal.'></a>",
"Notez que ces boutons ont toujours besoin de la classe <code>btn</code>", "Notez que ces boutons ont toujours besoin de la classe <code>btn</code>",
"Ajoutez la classe Bootstrap <code>btn-block</code> à votre bouton Bootstrap." "Ajoutez la classe Bootstrap <code>btn-block</code> à votre bouton Bootstrap."
] ]
@ -464,7 +464,7 @@
"Note that this button will still need the <code>btn</code> and <code>btn-block</code> classes." "Note that this button will still need the <code>btn</code> and <code>btn-block</code> classes."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -498,7 +498,7 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <button class=\"btn btn-block\">Like</button>", " <button class=\"btn btn-block\">Like</button>",
" <p>Things cats love:</p>", " <p>Things cats love:</p>",
" <ul>", " <ul>",
@ -552,7 +552,7 @@
"Note that these buttons still need the <code>btn</code> and <code>btn-block</code> classes." "Note that these buttons still need the <code>btn</code> and <code>btn-block</code> classes."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -586,7 +586,7 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <button class=\"btn btn-block btn-primary\">Like</button>", " <button class=\"btn btn-block btn-primary\">Like</button>",
" <p>Things cats love:</p>", " <p>Things cats love:</p>",
" <ul>", " <ul>",
@ -641,7 +641,7 @@
"Note that these buttons still need the <code>btn</code> and <code>btn-block</code> classes." "Note that these buttons still need the <code>btn</code> and <code>btn-block</code> classes."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -675,7 +675,7 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <button class=\"btn btn-block btn-primary\">Like</button>", " <button class=\"btn btn-block btn-primary\">Like</button>",
" <button class=\"btn btn-block btn-info\">Info</button>", " <button class=\"btn btn-block btn-info\">Info</button>",
" <p>Things cats love:</p>", " <p>Things cats love:</p>",
@ -736,7 +736,7 @@
"The <code>row</code> class is applied to a <code>div</code>, and the buttons themselves can be nested within it." "The <code>row</code> class is applied to a <code>div</code>, and the buttons themselves can be nested within it."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -770,7 +770,7 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <button class=\"btn btn-block btn-primary\">Like</button>", " <button class=\"btn btn-block btn-primary\">Like</button>",
" <button class=\"btn btn-block btn-info\">Info</button>", " <button class=\"btn btn-block btn-info\">Info</button>",
" <button class=\"btn btn-block btn-danger\">Delete</button>", " <button class=\"btn btn-block btn-danger\">Delete</button>",
@ -819,7 +819,7 @@
"descriptionFr": [ "descriptionFr": [
"Bootstrap utilise un système de grille adaptative, qui rend plus simple le placement des éléments en rangées et la spécification de la largeur relative de chaque élément. La plupart des classes de Bootstrap peuvent être associés à un élément <code>div</code>", "Bootstrap utilise un système de grille adaptative, qui rend plus simple le placement des éléments en rangées et la spécification de la largeur relative de chaque élément. La plupart des classes de Bootstrap peuvent être associés à un élément <code>div</code>",
"Voici un diagramme décrivant le fonctionnement du système de grille à 12 colonnes:", "Voici un diagramme décrivant le fonctionnement du système de grille à 12 colonnes:",
"<a href=\"http://i.imgur.com/FaYuui8.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/FaYuui8.png\" title=\"Cliquer pour agrandir\" alt=\"Une image illustrant le système de grille Bootstrap\"></a>", "<a href=\"https://i.imgur.com/FaYuui8.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"https://i.imgur.com/FaYuui8.png\" title=\"Cliquer pour agrandir\" alt=\"Une image illustrant le système de grille Bootstrap\"></a>",
"Notez que dans cet exemple, nous avons utilisé la classe <code>col-md-*</code>. Ici, <code>md</code> signifie medium, et <code>*</code> donne le nombre de colonnes en largeur de l'élément. Dans le cas présenté, on a défini la largeur en colonnes d' un élément sur un écrand de taille medium, comme un ordinateur portable.", "Notez que dans cet exemple, nous avons utilisé la classe <code>col-md-*</code>. Ici, <code>md</code> signifie medium, et <code>*</code> donne le nombre de colonnes en largeur de l'élément. Dans le cas présenté, on a défini la largeur en colonnes d' un élément sur un écrand de taille medium, comme un ordinateur portable.",
"Dans l'application de photos de chats que nous sommes en train de construire, nous utiliserons <code>col-xs-*</code>, où <code>xs</code> signifie extrêmement petit (comme un écran de téléphone mobile), et <code>*</code> est le nombre de colonnes en largeur de l'élément.", "Dans l'application de photos de chats que nous sommes en train de construire, nous utiliserons <code>col-xs-*</code>, où <code>xs</code> signifie extrêmement petit (comme un écran de téléphone mobile), et <code>*</code> est le nombre de colonnes en largeur de l'élément.",
"Mettez les boutons <code>Like</code>, <code>info</code> et <code>Delete</code> côte-à-côte en les enveloppant tous dans un élément <code>&#60;div class=\"row\"&#62;</code>, puis chacun d'entre eux dans un élément <code>&#60;div class=\"col-xs-4\"&#62;</code> element.", "Mettez les boutons <code>Like</code>, <code>info</code> et <code>Delete</code> côte-à-côte en les enveloppant tous dans un élément <code>&#60;div class=\"row\"&#62;</code>, puis chacun d'entre eux dans un élément <code>&#60;div class=\"col-xs-4\"&#62;</code> element.",
@ -837,7 +837,7 @@
"Finally, remove the \"smaller-image\" class from your first <code>img</code> element and replace it with the <code>img-responsive</code> class." "Finally, remove the \"smaller-image\" class from your first <code>img</code> element and replace it with the <code>img-responsive</code> class."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" .red-text {", " .red-text {",
" color: red;", " color: red;",
@ -871,7 +871,7 @@
"", "",
" <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"smaller-image thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\">Like</button>", " <button class=\"btn btn-block btn-primary\">Like</button>",
@ -945,7 +945,7 @@
"<code>&#60;p&#62;Top 3 things cats &#60;span class = \"text-danger\"&#62;hate:&#60;/span&#62;&#60;/p&#62;</code>" "<code>&#60;p&#62;Top 3 things cats &#60;span class = \"text-danger\"&#62;hate:&#60;/span&#62;&#60;/p&#62;</code>"
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
"", "",
" h2 {", " h2 {",
@ -966,7 +966,7 @@
"", "",
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\">Like</button>", " <button class=\"btn btn-block btn-primary\">Like</button>",
@ -1023,7 +1023,7 @@
"descriptionFr": [ "descriptionFr": [
"Vous pouvez utiliser les spans pour créer des éléments inline. Vous rappelez vous quand nous avions utilisé la classe <code>btn-block</code> pour remplir la rangée entière?", "Vous pouvez utiliser les spans pour créer des éléments inline. Vous rappelez vous quand nous avions utilisé la classe <code>btn-block</code> pour remplir la rangée entière?",
"Cette image illustre la différence entre les éléments <code>inline</code> (en ligne) et les éléments <code>block-level</code> (de blocs):", "Cette image illustre la différence entre les éléments <code>inline</code> (en ligne) et les éléments <code>block-level</code> (de blocs):",
"<a href=\"http://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/O32cDWE.png\" title=\"Cliquez pour élargir\" alt=\"Un bouton \"inline\" est aussi petit que le texte qu'il contient. Dans cette image, c'est centré. En dessous il y a un bouton \"block-level\", qui s'étire à tout l'espace horizontal.'></a>", "<a href=\"https://i.imgur.com/O32cDWE.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"https://i.imgur.com/O32cDWE.png\" title=\"Cliquez pour élargir\" alt=\"Un bouton \"inline\" est aussi petit que le texte qu'il contient. Dans cette image, c'est centré. En dessous il y a un bouton \"block-level\", qui s'étire à tout l'espace horizontal.'></a>",
"En utilisant un élément <code>span</code>, vous pouvez mettre ensemble plusieurs éléments, et même donner un style différent à plusieurs parties d'un même élément", "En utilisant un élément <code>span</code>, vous pouvez mettre ensemble plusieurs éléments, et même donner un style différent à plusieurs parties d'un même élément",
"Nichez le mot \"love\" dans votre élément \"Things cats love\" en dessous dans un élément <code>span</code>; Ensuite donnez à ce <code>span</code> la classe <code>text-danger</code> pour rendre le texte rouge.", "Nichez le mot \"love\" dans votre élément \"Things cats love\" en dessous dans un élément <code>span</code>; Ensuite donnez à ce <code>span</code> la classe <code>text-danger</code> pour rendre le texte rouge.",
"Il faudrait que vous fassiez ainsi pour l'élément \"Top 3 things cats hate\":", "Il faudrait que vous fassiez ainsi pour l'élément \"Top 3 things cats hate\":",
@ -1044,7 +1044,7 @@
"Notice how the image is now just the right size to fit along the text?" "Notice how the image is now just the right size to fit along the text?"
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"", "",
"<style>", "<style>",
" h2 {", " h2 {",
@ -1064,7 +1064,7 @@
"", "",
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
"", "",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\">Like</button>", " <button class=\"btn btn-block btn-primary\">Like</button>",
@ -1124,7 +1124,7 @@
"Nous allons réaliser un entête tout simple pour notre appli Cat Photo App en plaçant le titre et l'image de chat relaxante dans la même rangée.", "Nous allons réaliser un entête tout simple pour notre appli Cat Photo App en plaçant le titre et l'image de chat relaxante dans la même rangée.",
"Rappelez-vous, Bootstrap utilise un système de grille adaptative, qui rend facile le placement des éléments en rangées et la définition de la largeur relative de chaque élément. La plupart des classes de Bootstrap peuvent être appliquées à un élément <code>div</code>.", "Rappelez-vous, Bootstrap utilise un système de grille adaptative, qui rend facile le placement des éléments en rangées et la définition de la largeur relative de chaque élément. La plupart des classes de Bootstrap peuvent être appliquées à un élément <code>div</code>.",
"Voici un diagramme du fonctionnement de la grille à 12 colonnes de Bootstrap:", "Voici un diagramme du fonctionnement de la grille à 12 colonnes de Bootstrap:",
"<a href=\"http://i.imgur.com/FaYuui8.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"http://i.imgur.com/FaYuui8.png\" title=\"Cliquer pour élargir\" alt=\"Une image illlustrant le système de grille de Bootstrap\"></a>", "<a href=\"https://i.imgur.com/FaYuui8.png\" data-lightbox=\"img-enlarge\"><img class=\"img-responsive\" src=\"https://i.imgur.com/FaYuui8.png\" title=\"Cliquer pour élargir\" alt=\"Une image illlustrant le système de grille de Bootstrap\"></a>",
"Notez que dans cet exemple, on utilise la classe <code>col-md-*</code>. Ici <code>md</code> signifie medium, et <code>*</code> est un nombre spécifiant le nombre de colonnes en largeur que l'élément devrait avoir.", "Notez que dans cet exemple, on utilise la classe <code>col-md-*</code>. Ici <code>md</code> signifie medium, et <code>*</code> est un nombre spécifiant le nombre de colonnes en largeur que l'élément devrait avoir.",
"Enveloppez votre première image et votre élément <code>h2</code> dans un seul élément <code>&#60;div class=\"row\"&#62;</code>. Mettez l'élément <code>h2</code> dans un <code>&#60;div class=\"col-xs-8\"&#62;</code> et votre image dans un <code>&#60;div class=\"col-xs-4\"&#62;</code> pour qu'ils soient sur la même ligne.", "Enveloppez votre première image et votre élément <code>h2</code> dans un seul élément <code>&#60;div class=\"row\"&#62;</code>. Mettez l'élément <code>h2</code> dans un <code>&#60;div class=\"col-xs-8\"&#62;</code> et votre image dans un <code>&#60;div class=\"col-xs-4\"&#62;</code> pour qu'ils soient sur la même ligne.",
"Voyez vous comme l'image est maintenant exactement ajustée à la bonne taille pour être à côté du texte?" "Voyez vous comme l'image est maintenant exactement ajustée à la bonne taille pour être à côté du texte?"
@ -1143,7 +1143,7 @@
"Use Font Awesome to add a <code>thumbs-up</code> icon to your like button by giving it an <code>i</code> element with the classes <code>fa</code> and <code>fa-thumbs-up</code>." "Use Font Awesome to add a <code>thumbs-up</code> icon to your like button by giving it an <code>i</code> element with the classes <code>fa</code> and <code>fa-thumbs-up</code>."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" h2 {", " h2 {",
" font-family: Lobster, Monospace;", " font-family: Lobster, Monospace;",
@ -1166,7 +1166,7 @@
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
" </div>", " </div>",
" </div>", " </div>",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\">Like</button>", " <button class=\"btn btn-block btn-primary\">Like</button>",
@ -1238,7 +1238,7 @@
"Use Font Awesome to add an <code>info-circle</code> icon to your info button and a <code>trash</code> icon to your delete button." "Use Font Awesome to add an <code>info-circle</code> icon to your info button and a <code>trash</code> icon to your delete button."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" h2 {", " h2 {",
" font-family: Lobster, Monospace;", " font-family: Lobster, Monospace;",
@ -1261,7 +1261,7 @@
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
" </div>", " </div>",
" </div>", " </div>",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>", " <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>",
@ -1322,7 +1322,7 @@
"Nest all of your radio buttons within a <code>&#60;div class=\"row\"&#62;</code> element. Then nest each of them within a <code>&#60;div class=\"col-xs-6\"&#62;</code> element." "Nest all of your radio buttons within a <code>&#60;div class=\"row\"&#62;</code> element. Then nest each of them within a <code>&#60;div class=\"col-xs-6\"&#62;</code> element."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" h2 {", " h2 {",
" font-family: Lobster, Monospace;", " font-family: Lobster, Monospace;",
@ -1345,7 +1345,7 @@
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
" </div>", " </div>",
" </div>", " </div>",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>", " <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>",
@ -1406,7 +1406,7 @@
"Nest all your checkboxes in a <code>&#60;div class=\"row\"&#62;</code> element. Then nest each of them in a <code>&#60;div class=\"col-xs-4\"&#62;</code> element." "Nest all your checkboxes in a <code>&#60;div class=\"row\"&#62;</code> element. Then nest each of them in a <code>&#60;div class=\"col-xs-4\"&#62;</code> element."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" h2 {", " h2 {",
" font-family: Lobster, Monospace;", " font-family: Lobster, Monospace;",
@ -1430,7 +1430,7 @@
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
" </div>", " </div>",
" </div>", " </div>",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>", " <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>",
@ -1498,7 +1498,7 @@
"Give your form's text input field a class of <code>form-control</code>. Give your form's submit button the classes <code>btn btn-primary</code>. Also give this button the Font Awesome icon of <code>fa-paper-plane</code>." "Give your form's text input field a class of <code>form-control</code>. Give your form's submit button the classes <code>btn btn-primary</code>. Also give this button the Font Awesome icon of <code>fa-paper-plane</code>."
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" h2 {", " h2 {",
" font-family: Lobster, Monospace;", " font-family: Lobster, Monospace;",
@ -1522,7 +1522,7 @@
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
" </div>", " </div>",
" </div>", " </div>",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>", " <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>",
@ -1599,7 +1599,7 @@
"This is the last challenge we'll do for our Cat Photo App for now. We hope you've enjoyed learning Font Awesome, Bootstrap, and responsive design!" "This is the last challenge we'll do for our Cat Photo App for now. We hope you've enjoyed learning Font Awesome, Bootstrap, and responsive design!"
], ],
"challengeSeed": [ "challengeSeed": [
"<link href=\"http://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"https://fonts.googleapis.com/css?family=Lobster\" rel=\"stylesheet\" type=\"text/css\">",
"<style>", "<style>",
" h2 {", " h2 {",
" font-family: Lobster, Monospace;", " font-family: Lobster, Monospace;",
@ -1623,7 +1623,7 @@
" <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>", " <a href=\"#\"><img class=\"img-responsive thick-green-border\" src=\"https://bit.ly/fcc-relaxing-cat\"></a>",
" </div>", " </div>",
" </div>", " </div>",
" <img src=\"http://bit.ly/fcc-running-cats\" class=\"img-responsive\">", " <img src=\"https://bit.ly/fcc-running-cats\" class=\"img-responsive\">",
" <div class=\"row\">", " <div class=\"row\">",
" <div class=\"col-xs-4\">", " <div class=\"col-xs-4\">",
" <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>", " <button class=\"btn btn-block btn-primary\"><i class=\"fa fa-thumbs-up\"></i> Like</button>",

View File

@ -1694,10 +1694,10 @@
"<p>Top 3 things cats hate:</p>" "<p>Top 3 things cats hate:</p>"
], ],
"tests": [ "tests": [
"assert($(\"ul\").length > 0, 'message: You should have an <code>ul</code> element on your page.');", "assert.equal($(\"ol\").prev().text(), 'Top 3 things cats hate:', 'message: Your should have an ordered list for \"Top 3 things cats hate\"');",
"assert($(\"ol\").length > 0, 'message: You should have an <code>ol</code> element on your page.');", "assert.equal($(\"ul\").prev().text(), \"Things cats love:\", 'message: You should have an unordered list for \"Things Cats Love\"');",
"assert($(\"ul li\").length > 2, 'message: You should have three <code>li</code> elements within your <code>ul</code> element.');", "assert.equal($(\"ul li\").length, 3, 'message: You should have three <code>li</code> elements within your <code>ul</code> element.');",
"assert($(\"ol li\").length > 2, 'message: You should have three <code>li</code> elements within your <code>ol</code> element.');", "assert.equal($(\"ol li\").length, 3, 'message: You should have three <code>li</code> elements within your <code>ol</code> element.');",
"assert(code.match(/<\\/ul>/g) && code.match(/<\\/ul>/g).length === code.match(/<ul>/g).length, 'message: Make sure your <code>ul</code> element has a closing tag.');", "assert(code.match(/<\\/ul>/g) && code.match(/<\\/ul>/g).length === code.match(/<ul>/g).length, 'message: Make sure your <code>ul</code> element has a closing tag.');",
"assert(code.match(/<\\/ol>/g) && code.match(/<\\/ol>/g).length === code.match(/<ol>/g).length, 'message: Make sure your <code>ol</code> element has a closing tag.');", "assert(code.match(/<\\/ol>/g) && code.match(/<\\/ol>/g).length === code.match(/<ol>/g).length, 'message: Make sure your <code>ol</code> element has a closing tag.');",
"assert(code.match(/<\\/li>/g) && code.match(/<li>/g) && code.match(/<\\/li>/g).length === code.match(/<li>/g).length, 'message: Make sure your <code>li</code> element has a closing tag.');" "assert(code.match(/<\\/li>/g) && code.match(/<li>/g) && code.match(/<\\/li>/g).length === code.match(/<li>/g).length, 'message: Make sure your <code>li</code> element has a closing tag.');"
@ -1875,7 +1875,7 @@
"tests": [ "tests": [
"assert($(\"input[placeholder]\").length > 0, 'message: Add a <code>placeholder</code> attribute text <code>input</code> element.');", "assert($(\"input[placeholder]\").length > 0, 'message: Add a <code>placeholder</code> attribute text <code>input</code> element.');",
"assert($(\"input\") && $(\"input\").attr(\"placeholder\") && $(\"input\").attr(\"placeholder\").match(/cat\\s+photo\\s+URL/gi), 'message: Set the value of your placeholder attribute to \"cat photo URL\".');", "assert($(\"input\") && $(\"input\").attr(\"placeholder\") && $(\"input\").attr(\"placeholder\").match(/cat\\s+photo\\s+URL/gi), 'message: Set the value of your placeholder attribute to \"cat photo URL\".');",
"assert($(\"input[type=text]\").length > 0 && code.match(/URL\\s*[\"\\']\\s*\\/?>/gi), 'message: The finished <code>input</code> element should have valid syntax.');" "assert($(\"input[type=text]\").length > 0 && code.match(/<input.*(text|URL)\\s*[\"\\']\\s*\\/?>/gi), 'message: The finished <code>input</code> element should have valid syntax.');"
], ],
"type": "waypoint", "type": "waypoint",
"titleEs": "Agrega un texto de relleno a un campo de texto", "titleEs": "Agrega un texto de relleno a un campo de texto",
@ -2527,7 +2527,7 @@
"</form>" "</form>"
], ],
"tests": [ "tests": [
"assert($(\"div\").children(\"p\").length > 1, 'message: Nest your <code>p</code> element inside your <code>div</code> element.');", "assert($(\"div\").children(\"p\").length > 1, 'message: Nest your <code>p</code> elements inside your <code>div</code> element.');",
"assert($(\"div\").children(\"ul\").length > 0, 'message: Nest your <code>ul</code> element inside your <code>div</code> element.');", "assert($(\"div\").children(\"ul\").length > 0, 'message: Nest your <code>ul</code> element inside your <code>div</code> element.');",
"assert($(\"div\").children(\"ol\").length > 0, 'message: Nest your <code>ol</code> element inside your <code>div</code> element.');", "assert($(\"div\").children(\"ol\").length > 0, 'message: Nest your <code>ol</code> element inside your <code>div</code> element.');",
"assert(code.match(/<\\/div>/g) && code.match(/<\\/div>/g).length === code.match(/<div>/g).length, 'message: Make sure your <code>div</code> element has a closing tag.');" "assert(code.match(/<\\/div>/g) && code.match(/<\\/div>/g).length === code.match(/<div>/g).length, 'message: Make sure your <code>div</code> element has a closing tag.');"

View File

@ -42,6 +42,12 @@
"Te pasaremos un vector que contiene dos números. Crea una función que devuelva la suma de esos dos números y todos los números entre ellos.", "Te pasaremos un vector que contiene dos números. Crea una función que devuelva la suma de esos dos números y todos los números entre ellos.",
"El número menor no siempre será el primer elemento en el vector.", "El número menor no siempre será el primer elemento en el vector.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Additionner tous les nombres d'une série",
"descriptionFr": [
"Nous te passons un tableau de deux nombres. Crée une fonction qui renvoie la somme de ces 2 nombres ainsi que tous les nombres entre ceux-ci.",
"Le plus petit nombre ne viendra pas forcément en premier.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -52,26 +58,26 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function diff(arr1, arr2) {", "function diffArray(arr1, arr2) {",
" var newArr = [];", " var newArr = [];",
" // Same, same; but different.", " // Same, same; but different.",
" return newArr;", " return newArr;",
"}", "}",
"", "",
"diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);" "diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);"
], ],
"solutions": [ "solutions": [
"function diff(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}" "function diffArray(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}"
], ],
"tests": [ "tests": [
"assert(typeof diff([1, 2, 3, 5], [1, 2, 3, 4, 5]) === \"object\", 'message: <code>diff([1, 2, 3, 5], [1, 2, 3, 4, 5])</code> should return an array.');", "assert(typeof diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]) === \"object\", 'message: <code>diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])</code> should return an array.');",
"assert.sameMembers(diff([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], 'message: <code>[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[\"pink wool\"]</code>.');", "assert.sameMembers(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], 'message: <code>[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[\"pink wool\"]</code>.');",
"assert.sameMembers(diff([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], 'message: <code>[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[\"diorite\", \"pink wool\"]</code>.');", "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], 'message: <code>[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[\"diorite\", \"pink wool\"]</code>.');",
"assert.sameMembers(diff([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], 'message: <code>[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[]</code>.');", "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], 'message: <code>[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]</code> should return <code>[]</code>.');",
"assert.sameMembers(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: <code>[1, 2, 3, 5], [1, 2, 3, 4, 5]</code> should return <code>[4]</code>.');", "assert.sameMembers(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: <code>[1, 2, 3, 5], [1, 2, 3, 4, 5]</code> should return <code>[4]</code>.');",
"assert.sameMembers(diff([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: <code>[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]</code> should return <code>[\"piglet\", 4]</code>.');", "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: <code>[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]</code> should return <code>[\"piglet\", 4]</code>.');",
"assert.sameMembers(diff([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: <code>[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code> should return <code>[\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code>.');", "assert.sameMembers(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: <code>[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code> should return <code>[\"snuffleupagus\", \"cookie monster\", \"elmo\"]</code>.');",
"assert.sameMembers(diff([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], 'message: <code>[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]</code> should return <code>[1, \"calf\", 3, \"piglet\", 7, \"filly\"]</code>.');" "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], 'message: <code>[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]</code> should return <code>[1, \"calf\", 3, \"piglet\", 7, \"filly\"]</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -87,6 +93,11 @@
"descriptionEs": [ "descriptionEs": [
"Crea una función que compare dos vectores y que devuelva un nuevo vector que contenga los elementos que sólo se encuentre en uno de los vectores dados, pero no en ambos En otras palabras, devuelve la diferencia simétrica entre los dos vectores.", "Crea una función que compare dos vectores y que devuelva un nuevo vector que contenga los elementos que sólo se encuentre en uno de los vectores dados, pero no en ambos En otras palabras, devuelve la diferencia simétrica entre los dos vectores.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Comparer 2 arrays",
"descriptionFr": [
"Compare les 2 tableaux donnés et renvoie un nouvel tableau avec les éléments trouvé dans un seul des deux tableaux, pas dans les deux. En d'autres termes, renvoie la différence symétrique des deux tableaux.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -98,41 +109,41 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function convert(num) {", "function convertToRoman(num) {",
" return num;", " return num;",
"}", "}",
"", "",
"convert(36);" "convertToRoman(36);"
], ],
"solutions": [ "solutions": [
"function convert(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}" "function convertToRoman(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(convert(2), \"II\", 'message: <code>convert(2)</code> should return \"II\".');", "assert.deepEqual(convertToRoman(2), \"II\", 'message: <code>convertToRoman(2)</code> should return \"II\".');",
"assert.deepEqual(convert(3), \"III\", 'message: <code>convert(3)</code> should return \"III\".');", "assert.deepEqual(convertToRoman(3), \"III\", 'message: <code>convertToRoman(3)</code> should return \"III\".');",
"assert.deepEqual(convert(4), \"IV\", 'message: <code>convert(4)</code> should return \"IV\".');", "assert.deepEqual(convertToRoman(4), \"IV\", 'message: <code>convertToRoman(4)</code> should return \"IV\".');",
"assert.deepEqual(convert(5), \"V\", 'message: <code>convert(5)</code> should return \"V\".');", "assert.deepEqual(convertToRoman(5), \"V\", 'message: <code>convertToRoman(5)</code> should return \"V\".');",
"assert.deepEqual(convert(9), \"IX\", 'message: <code>convert(9)</code> should return \"IX\".');", "assert.deepEqual(convertToRoman(9), \"IX\", 'message: <code>convertToRoman(9)</code> should return \"IX\".');",
"assert.deepEqual(convert(12), \"XII\", 'message: <code>convert(12)</code> should return \"XII\".');", "assert.deepEqual(convertToRoman(12), \"XII\", 'message: <code>convertToRoman(12)</code> should return \"XII\".');",
"assert.deepEqual(convert(16), \"XVI\", 'message: <code>convert(16)</code> should return \"XVI\".');", "assert.deepEqual(convertToRoman(16), \"XVI\", 'message: <code>convertToRoman(16)</code> should return \"XVI\".');",
"assert.deepEqual(convert(29), \"XXIX\", 'message: <code>convert(29)</code> should return \"XXIX\".');", "assert.deepEqual(convertToRoman(29), \"XXIX\", 'message: <code>convertToRoman(29)</code> should return \"XXIX\".');",
"assert.deepEqual(convert(44), \"XLIV\", 'message: <code>convert(44)</code> should return \"XLIV\".');", "assert.deepEqual(convertToRoman(44), \"XLIV\", 'message: <code>convertToRoman(44)</code> should return \"XLIV\".');",
"assert.deepEqual(convert(45), \"XLV\", 'message: <code>convert(45)</code> should return \"XLV\"');", "assert.deepEqual(convertToRoman(45), \"XLV\", 'message: <code>convertToRoman(45)</code> should return \"XLV\"');",
"assert.deepEqual(convert(68), \"LXVIII\", 'message: <code>convert(68)</code> should return \"LXVIII\"');", "assert.deepEqual(convertToRoman(68), \"LXVIII\", 'message: <code>convertToRoman(68)</code> should return \"LXVIII\"');",
"assert.deepEqual(convert(83), \"LXXXIII\", 'message: <code>convert(83)</code> should return \"LXXXIII\"');", "assert.deepEqual(convertToRoman(83), \"LXXXIII\", 'message: <code>convertToRoman(83)</code> should return \"LXXXIII\"');",
"assert.deepEqual(convert(97), \"XCVII\", 'message: <code>convert(97)</code> should return \"XCVII\"');", "assert.deepEqual(convertToRoman(97), \"XCVII\", 'message: <code>convertToRoman(97)</code> should return \"XCVII\"');",
"assert.deepEqual(convert(99), \"XCIX\", 'message: <code>convert(99)</code> should return \"XCIX\"');", "assert.deepEqual(convertToRoman(99), \"XCIX\", 'message: <code>convertToRoman(99)</code> should return \"XCIX\"');",
"assert.deepEqual(convert(500), \"D\", 'message: <code>convert(500)</code> should return \"D\"');", "assert.deepEqual(convertToRoman(500), \"D\", 'message: <code>convertToRoman(500)</code> should return \"D\"');",
"assert.deepEqual(convert(501), \"DI\", 'message: <code>convert(501)</code> should return \"DI\"');", "assert.deepEqual(convertToRoman(501), \"DI\", 'message: <code>convertToRoman(501)</code> should return \"DI\"');",
"assert.deepEqual(convert(649), \"DCXLIX\", 'message: <code>convert(649)</code> should return \"DCXLIX\"');", "assert.deepEqual(convertToRoman(649), \"DCXLIX\", 'message: <code>convertToRoman(649)</code> should return \"DCXLIX\"');",
"assert.deepEqual(convert(798), \"DCCXCVIII\", 'message: <code>convert(798)</code> should return \"DCCXCVIII\"');", "assert.deepEqual(convertToRoman(798), \"DCCXCVIII\", 'message: <code>convertToRoman(798)</code> should return \"DCCXCVIII\"');",
"assert.deepEqual(convert(891), \"DCCCXCI\", 'message: <code>convert(891)</code> should return \"DCCCXCI\"');", "assert.deepEqual(convertToRoman(891), \"DCCCXCI\", 'message: <code>convertToRoman(891)</code> should return \"DCCCXCI\"');",
"assert.deepEqual(convert(1000), \"M\", 'message: <code>convert(1000)</code> should return \"M\"');", "assert.deepEqual(convertToRoman(1000), \"M\", 'message: <code>convertToRoman(1000)</code> should return \"M\"');",
"assert.deepEqual(convert(1004), \"MIV\", 'message: <code>convert(1004)</code> should return \"MIV\"');", "assert.deepEqual(convertToRoman(1004), \"MIV\", 'message: <code>convertToRoman(1004)</code> should return \"MIV\"');",
"assert.deepEqual(convert(1006), \"MVI\", 'message: <code>convert(1006)</code> should return \"MVI\"');", "assert.deepEqual(convertToRoman(1006), \"MVI\", 'message: <code>convertToRoman(1006)</code> should return \"MVI\"');",
"assert.deepEqual(convert(1023), \"MXXIII\", 'message: <code>convert(1023)</code> should return \"MXXIII\"');", "assert.deepEqual(convertToRoman(1023), \"MXXIII\", 'message: <code>convertToRoman(1023)</code> should return \"MXXIII\"');",
"assert.deepEqual(convert(2014), \"MMXIV\", 'message: <code>convert(2014)</code> should return \"MMXIV\"');", "assert.deepEqual(convertToRoman(2014), \"MMXIV\", 'message: <code>convertToRoman(2014)</code> should return \"MMXIV\"');",
"assert.deepEqual(convert(3999), \"MMMCMXCIX\", 'message: <code>convert(3999)</code> should return \"MMMCMXCIX\"');" "assert.deepEqual(convertToRoman(3999), \"MMMCMXCIX\", 'message: <code>convertToRoman(3999)</code> should return \"MMMCMXCIX\"');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -148,6 +159,12 @@
"Convierte el número dado en numeral romano.", "Convierte el número dado en numeral romano.",
"Todos los <a href=\"http://www.mathsisfun.com/roman-numerals.html\" target=\"_blank\">numerales romanos</a> en las respuestas deben estar en mayúsculas.", "Todos los <a href=\"http://www.mathsisfun.com/roman-numerals.html\" target=\"_blank\">numerales romanos</a> en las respuestas deben estar en mayúsculas.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Convertir en chiffres romains",
"descriptionFr": [
"Convertis le nombre donné en chiffres romains.",
"Tous les <a href=\"http://www.mathsisfun.com/roman-numerals.html\" target=\"_blank\">chiffres romains</a> doivent être en lettres capitales.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -159,22 +176,22 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function where(collection, source) {", "function whereAreYou(collection, source) {",
" var arr = [];", " var arr = [];",
" // What's in a name?", " // What's in a name?",
" return arr;", " return arr;",
"}", "}",
"", "",
"where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });" "whereAreYou([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });"
], ],
"solutions": [ "solutions": [
"function where(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}" "function whereAreYou(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: <code>where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })</code> should return <code>[{ first: \"Tybalt\", last: \"Capulet\" }]</code>.');", "assert.deepEqual(whereAreYou([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: <code>whereAreYou([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })</code> should return <code>[{ first: \"Tybalt\", last: \"Capulet\" }]</code>.');",
"assert.deepEqual(where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 }), [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], 'message: <code>where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 })</code> should return <code>[{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }]</code>.');", "assert.deepEqual(whereAreYou([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 }), [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], 'message: <code>whereAreYou([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 })</code> should return <code>[{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }]</code>.');",
"assert.deepEqual(where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 }), [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: <code>where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 })</code> should return <code>[{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }]</code>.');", "assert.deepEqual(whereAreYou([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 }), [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: <code>whereAreYou([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 })</code> should return <code>[{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }]</code>.');",
"assert.deepEqual(where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"c\": 2 }), [{ \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: <code>where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"c\": 2 })</code> should return <code>[{ \"a\": 1, \"b\": 2, \"c\": 2 }]</code>.');" "assert.deepEqual(whereAreYou([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"c\": 2 }), [{ \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: <code>whereAreYou([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"c\": 2 })</code> should return <code>[{ \"a\": 1, \"b\": 2, \"c\": 2 }]</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -189,6 +206,12 @@
"Crea una función que busque en un vector de objetos (primer argumento) y devuelva un vector con todos los objetos que compartan el valor indicado para una propiedad dada (segundo argumento). Cada pareja de propiedad y valor debe estar presente en el objeto de la colección para ser incluido en el vector devuelto por la función", "Crea una función que busque en un vector de objetos (primer argumento) y devuelva un vector con todos los objetos que compartan el valor indicado para una propiedad dada (segundo argumento). Cada pareja de propiedad y valor debe estar presente en el objeto de la colección para ser incluido en el vector devuelto por la función",
"Por ejemplo, si el primer argumento es <code>[{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]</code>, y el segundo argumento es <code>{ last: \"Capulet\" }</code>, entonces tu función debe devolver el tercer objeto del vector en el primer argumento, ya que contiene la propiedad y el valor indicados en el segundo argumento.", "Por ejemplo, si el primer argumento es <code>[{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]</code>, y el segundo argumento es <code>{ last: \"Capulet\" }</code>, entonces tu función debe devolver el tercer objeto del vector en el primer argumento, ya que contiene la propiedad y el valor indicados en el segundo argumento.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "O Roméo! Roméo!",
"descriptionFr": [
"Écris une fonction qui parcourt un array d'objets (premier argument) et renvoie un array de tous les objects ayant les paires de nom/valeur correspondantes à l'objet donné (second argument). Chaque paire de nom et de valeur de l'objet source doit être présente dans les objects renvoyés.",
"Par exemple, si le premier argument est <code>[{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]</code>, et le second argument est <code>{ last: \"Capulet\" }</code>, tu dois renvoyer le troisième objet de l'array (premier argument), parce qu'il contient le nom et sa valeur, donnés en deuxième argument.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -235,6 +258,15 @@
"El tercer argumento es lo que reemplazará a la palabra indicada en el segundo argumento", "El tercer argumento es lo que reemplazará a la palabra indicada en el segundo argumento",
"NOTA: Debes respetar mayúsculas y minúsculas de la palabra original cuando ejecutes el reemplazo. Por ejemplo, si quisieras reemplazar la palabra \"Libro\" con la palabra \"perro\", deberías insertar en vez la palabra \"Perro\"", "NOTA: Debes respetar mayúsculas y minúsculas de la palabra original cuando ejecutes el reemplazo. Por ejemplo, si quisieras reemplazar la palabra \"Libro\" con la palabra \"perro\", deberías insertar en vez la palabra \"Perro\"",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Cherche et remplace",
"descriptionFr": [
"Crée une fonction qui cherche et remplace une partie de la phrase en utilisant les arguments et renvoie la nouvelle phrase.",
"Le premier argument est la phrase à modifier.",
"Le deuxième argument est le mot à remplacer (avant).",
"Le troisième argument est le mot qui doit remplacer le deuxième argument (après).",
"NB: Tu dois respecter les majuscules ou miniscules du mot originel que tu remplaces. Par exemple, si tu veux remplacer le mot \"Livre\" par \"chien\", tu devras le remplacer par \"Chien\"",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -247,21 +279,21 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function translate(str) {", "function translatePigLatin(str) {",
" return str;", " return str;",
"}", "}",
"", "",
"translate(\"consonant\");" "translatePigLatin(\"consonant\");"
], ],
"solutions": [ "solutions": [
"function translate(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}" "function translatePigLatin(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'message: <code>translate(\"california\")</code> should return \"aliforniacay\".');", "assert.deepEqual(translatePigLatin(\"california\"), \"aliforniacay\", 'message: <code>translatePigLatin(\"california\")</code> should return \"aliforniacay\".');",
"assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'message: <code>translate(\"paragraphs\")</code> should return \"aragraphspay\".');", "assert.deepEqual(translatePigLatin(\"paragraphs\"), \"aragraphspay\", 'message: <code>translatePigLatin(\"paragraphs\")</code> should return \"aragraphspay\".');",
"assert.deepEqual(translate(\"glove\"), \"oveglay\", 'message: <code>translate(\"glove\")</code> should return \"oveglay\".');", "assert.deepEqual(translatePigLatin(\"glove\"), \"oveglay\", 'message: <code>translatePigLatin(\"glove\")</code> should return \"oveglay\".');",
"assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'message: <code>translate(\"algorithm\")</code> should return \"algorithmway\".');", "assert.deepEqual(translatePigLatin(\"algorithm\"), \"algorithmway\", 'message: <code>translatePigLatin(\"algorithm\")</code> should return \"algorithmway\".');",
"assert.deepEqual(translate(\"eight\"), \"eightway\", 'message: <code>translate(\"eight\")</code> should return \"eightway\".');" "assert.deepEqual(translatePigLatin(\"eight\"), \"eightway\", 'message: <code>translatePigLatin(\"eight\")</code> should return \"eightway\".');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -279,6 +311,13 @@
"<a href=\"http://en.wikipedia.org/wiki/Pig_Latin\" target=\"_blank\">Pig Latin</a> toma la primera consonante (o grupo de consonantes) de una palabra en inglés, la mueve al final de la palabra y agrega un \"ay\".", "<a href=\"http://en.wikipedia.org/wiki/Pig_Latin\" target=\"_blank\">Pig Latin</a> toma la primera consonante (o grupo de consonantes) de una palabra en inglés, la mueve al final de la palabra y agrega un \"ay\".",
"Si la palabra comienza con una vocal, simplemente añade \"way\" al final.", "Si la palabra comienza con una vocal, simplemente añade \"way\" al final.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Pig latin",
"descriptionFr": [
"Traduis la phrase donnée en pig latin (verlan anglais)",
"Le <a href=\"http://fr.wikipedia.org/wiki/Pig_Latin\" target=\"_blank\">Pig Latin</a> prend la ou les première(s) consonne(s) d'un mot en anglais et les mets à la fin du mot accompagné par le suffixe \"ay\".",
"Si un mot commence par une voyelle ajoute \"way\" à la fin du mot.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -293,19 +332,19 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function pair(str) {", "function pairElement(str) {",
" return str;", " return str;",
"}", "}",
"", "",
"pair(\"GCG\");" "pairElement(\"GCG\");"
], ],
"solutions": [ "solutions": [
"var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pair(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}" "var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pairElement(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(pair(\"ATCGA\"),[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]], 'message: <code>pair(\"ATCGA\")</code> should return <code>[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]]</code>.');", "assert.deepEqual(pairElement(\"ATCGA\"),[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]], 'message: <code>pairElement(\"ATCGA\")</code> should return <code>[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]]</code>.');",
"assert.deepEqual(pair(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'message: <code>pair(\"TTGAG\")</code> should return <code>[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]]</code>.');", "assert.deepEqual(pairElement(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'message: <code>pairElement(\"TTGAG\")</code> should return <code>[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]]</code>.');",
"assert.deepEqual(pair(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'message: <code>pair(\"CTCTA\")</code> should return <code>[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]]</code>.');" "assert.deepEqual(pairElement(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'message: <code>pairElement(\"CTCTA\")</code> should return <code>[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]]</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -322,6 +361,15 @@
"Por ejemplo, si te pasáramos la cadena GCG, tu función debería devolver el vector: [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]", "Por ejemplo, si te pasáramos la cadena GCG, tu función debería devolver el vector: [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]",
"Cada letra que se te provee y su pareja deben estar contenidos en un vector, y cada uno de estos vectores debe estar contenidos en un vector.", "Cada letra que se te provee y su pareja deben estar contenidos en un vector, y cada uno de estos vectores debe estar contenidos en un vector.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Coupler les bases d'ADN",
"descriptionFr": [
"Une base d'ADN a perdu sa paire. Assemble chaque paire de caractères et renvoie les résultats dans un second tableau.",
"Les <a href=\"https://fr.wikipedia.org/wiki/Paire_de_bases\" target=\"_blank\">paires de bases</a> sont des paires d'AT et CG. Associe l'élement manquant au caractère donné.",
"Renvoie le caractère donné comme premier élément de chaque tableau.",
"Par exemple, pour GCG, il faut renvoyer [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]",
"Chaque caractère et sa paire sont couplées dans un tableau, et tous les tableaux sont groupés dans un tableau.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -360,6 +408,12 @@
"Crea una función que devuelva la letra que falta en el rango de letras que se le pasa", "Crea una función que devuelva la letra que falta en el rango de letras que se le pasa",
"Si todas las letras en el rango están presentes, la función debe devolver undefined.", "Si todas las letras en el rango están presentes, la función debe devolver undefined.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Lettres perdues",
"descriptionFr": [
"Crée une fonction qui renvoie la lettre manquante dans la série.",
"Si aucune lettre n'est manquante, renvoie undefined.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -371,27 +425,27 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function boo(bool) {", "function booWho(bool) {",
" // What is the new fad diet for ghost developers? The Boolean.", " // What is the new fad diet for ghost developers? The Boolean.",
" return bool;", " return bool;",
"}", "}",
"", "",
"boo(null);" "booWho(null);"
], ],
"solutions": [ "solutions": [
"function boo(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\n return typeof bool === \"boolean\";\n}\n\nboo(null);" "function booWho(bool) {\n // What is the new fad diet for ghost developers? The Boolean.\n return typeof bool === \"boolean\";\n}\n\nbooWho(null);"
], ],
"tests": [ "tests": [
"assert.strictEqual(boo(true), true, 'message: <code>boo(true)</code> should return true.');", "assert.strictEqual(booWho(true), true, 'message: <code>booWho(true)</code> should return true.');",
"assert.strictEqual(boo(false), true, 'message: <code>boo(false)</code> should return true.');", "assert.strictEqual(booWho(false), true, 'message: <code>booWho(false)</code> should return true.');",
"assert.strictEqual(boo([1, 2, 3]), false, 'message: <code>boo([1, 2, 3])</code> should return false.');", "assert.strictEqual(booWho([1, 2, 3]), false, 'message: <code>booWho([1, 2, 3])</code> should return false.');",
"assert.strictEqual(boo([].slice), false, 'message: <code>boo([].slice)</code> should return false.');", "assert.strictEqual(booWho([].slice), false, 'message: <code>booWho([].slice)</code> should return false.');",
"assert.strictEqual(boo({ \"a\": 1 }), false, 'message: <code>boo({ \"a\": 1 })</code> should return false.');", "assert.strictEqual(booWho({ \"a\": 1 }), false, 'message: <code>booWho({ \"a\": 1 })</code> should return false.');",
"assert.strictEqual(boo(1), false, 'message: <code>boo(1)</code> should return false.');", "assert.strictEqual(booWho(1), false, 'message: <code>booWho(1)</code> should return false.');",
"assert.strictEqual(boo(NaN), false, 'message: <code>boo(NaN)</code> should return false.');", "assert.strictEqual(booWho(NaN), false, 'message: <code>booWho(NaN)</code> should return false.');",
"assert.strictEqual(boo(\"a\"), false, 'message: <code>boo(\"a\")</code> should return false.');", "assert.strictEqual(booWho(\"a\"), false, 'message: <code>booWho(\"a\")</code> should return false.');",
"assert.strictEqual(boo(\"true\"), false, 'message: <code>boo(\"true\")</code> should return false.');", "assert.strictEqual(booWho(\"true\"), false, 'message: <code>booWho(\"true\")</code> should return false.');",
"assert.strictEqual(boo(\"false\"), false, 'message: <code>boo(\"false\")</code> should return false.');" "assert.strictEqual(booWho(\"false\"), false, 'message: <code>booWho(\"false\")</code> should return false.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -404,6 +458,12 @@
"Crea una función que verifique si el valor que se le pasa es de tipo booleano. Haz que la función devuelva true o false según corresponda.", "Crea una función que verifique si el valor que se le pasa es de tipo booleano. Haz que la función devuelva true o false según corresponda.",
"Los primitivos booleanos primitivos son: true y false", "Los primitivos booleanos primitivos son: true y false",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Boo !",
"descriptionFr": [
"Crée une fonction qui vérifie qu'une valeur est de type booléen. Renvoie true ou false.",
"Les primitives booléennes sont true ou false.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -417,20 +477,20 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function unite(arr1, arr2, arr3) {", "function uniteUnique(arr1, arr2, arr3) {",
" return arr1;", " return arr1;",
"}", "}",
"", "",
"unite([1, 3, 2], [5, 2, 1, 4], [2, 1]);" "uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);"
], ],
"solutions": [ "solutions": [
"function unite(arr1, arr2, arr3) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}" "function uniteUnique(arr1, arr2, arr3) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(unite([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'message: <code>unite([1, 3, 2], [5, 2, 1, 4], [2, 1])</code> should return <code>[1, 3, 2, 5, 4]</code>.');", "assert.deepEqual(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'message: <code>uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1])</code> should return <code>[1, 3, 2, 5, 4]</code>.');",
"assert.deepEqual(unite([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'message: <code>unite([1, 3, 2], [1, [5]], [2, [4]])</code> should return <code>[1, 3, 2, [5], [4]]</code>.');", "assert.deepEqual(uniteUnique([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'message: <code>uniteUnique([1, 3, 2], [1, [5]], [2, [4]])</code> should return <code>[1, 3, 2, [5], [4]]</code>.');",
"assert.deepEqual(unite([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'message: <code>unite([1, 2, 3], [5, 2, 1])</code> should return <code>[1, 2, 3, 5]</code>.');", "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'message: <code>uniteUnique([1, 2, 3], [5, 2, 1])</code> should return <code>[1, 2, 3, 5]</code>.');",
"assert.deepEqual(unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [1, 2, 3, 5, 4, 6, 7, 8], 'message: <code>unite([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])</code> should return <code>[1, 2, 3, 5, 4, 6, 7, 8]</code>.');" "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [1, 2, 3, 5, 4, 6, 7, 8], 'message: <code>uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])</code> should return <code>[1, 2, 3, 5, 4, 6, 7, 8]</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -446,6 +506,14 @@
"Los valores únicos deben aparecer en el orden original, pero el vector final no necesariamente debe mostrar los elementos en orden numérico.", "Los valores únicos deben aparecer en el orden original, pero el vector final no necesariamente debe mostrar los elementos en orden numérico.",
"Puedes usar de referencia las pruebas de verificación si necesitas ejemplos.", "Puedes usar de referencia las pruebas de verificación si necesitas ejemplos.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Union arrangée",
"descriptionFr": [
"Crée une fonction qui accepte deux tableaux ou plus et renvoie un nouvel array de valeurs uniques dans l'ordre des tableaux donnés.",
"En d'autres termes, toutes les valeurs des tableaux doivent être incluses dans l'ordre originel, sans doublon dans le tableau final.",
"Les valeurs uniques doivent être classées dans l'ordre originel, mais le tableau final ne doit pas être classé par ordre croissant.",
"Réfère toi aux test pour plus d'examples.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -456,24 +524,24 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function convert(str) {", "function convertHTML(str) {",
" // &colon;&rpar;", " // &colon;&rpar;",
" return str;", " return str;",
"}", "}",
"", "",
"convert(\"Dolce & Gabbana\");" "convertHTML(\"Dolce & Gabbana\");"
], ],
"solutions": [ "solutions": [
"var MAP = { '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&apos;'};\n\nfunction convert(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}" "var MAP = { '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&apos;'};\n\nfunction convertHTML(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}"
], ],
"tests": [ "tests": [
"assert.match(convert(\"Dolce & Gabbana\"), /Dolce &amp; Gabbana/, 'message: <code>convert(\"Dolce & Gabbana\")</code> should return <code>Dolce &&#8203;amp; Gabbana</code>.');", "assert.match(convertHTML(\"Dolce & Gabbana\"), /Dolce &amp; Gabbana/, 'message: <code>convertHTML(\"Dolce & Gabbana\")</code> should return <code>Dolce &&#8203;amp; Gabbana</code>.');",
"assert.match(convert(\"Hamburgers < Pizza < Tacos\"), /Hamburgers &lt; Pizza &lt; Tacos/, 'message: <code>convert(\"Hamburgers < Pizza < Tacos\")</code> should return <code>Hamburgers &&#8203;lt; Pizza &&#8203;lt; Tacos</code>.');", "assert.match(convertHTML(\"Hamburgers < Pizza < Tacos\"), /Hamburgers &lt; Pizza &lt; Tacos/, 'message: <code>convertHTML(\"Hamburgers < Pizza < Tacos\")</code> should return <code>Hamburgers &&#8203;lt; Pizza &&#8203;lt; Tacos</code>.');",
"assert.match(convert(\"Sixty > twelve\"), /Sixty &gt; twelve/, 'message: <code>convert(\"Sixty > twelve\")</code> should return <code>Sixty &&#8203;gt; twelve</code>.');", "assert.match(convertHTML(\"Sixty > twelve\"), /Sixty &gt; twelve/, 'message: <code>convertHTML(\"Sixty > twelve\")</code> should return <code>Sixty &&#8203;gt; twelve</code>.');",
"assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in &quot;quotation marks&quot;/, 'message: <code>convert(&apos;Stuff in \"quotation marks\"&apos;)</code> should return <code>Stuff in &&#8203;quot;quotation marks&&#8203;quot;</code>.');", "assert.match(convertHTML('Stuff in \"quotation marks\"'), /Stuff in &quot;quotation marks&quot;/, 'message: <code>convertHTML(&apos;Stuff in \"quotation marks\"&apos;)</code> should return <code>Stuff in &&#8203;quot;quotation marks&&#8203;quot;</code>.');",
"assert.match(convert(\"Shindler's List\"), /Shindler&apos;s List/, 'message: <code>convert(\"Shindler&apos;s List\")</code> should return <code>Shindler&&#8203;apos;s List</code>.');", "assert.match(convertHTML(\"Shindler's List\"), /Shindler&apos;s List/, 'message: <code>convertHTML(\"Shindler&apos;s List\")</code> should return <code>Shindler&&#8203;apos;s List</code>.');",
"assert.match(convert('<>'), /&lt;&gt;/, 'message: <code>convert(\"<>\")</code> should return <code>&&#8203;lt;&&#8203;gt;</code>.');", "assert.match(convertHTML('<>'), /&lt;&gt;/, 'message: <code>convertHTML(\"<>\")</code> should return <code>&&#8203;lt;&&#8203;gt;</code>.');",
"assert.strictEqual(convert('abc'), 'abc', 'message: <code>convert(\"abc\")</code> should return <code>abc</code>.');" "assert.strictEqual(convertHTML('abc'), 'abc', 'message: <code>convertHTML(\"abc\")</code> should return <code>abc</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -486,6 +554,11 @@
"descriptionEs": [ "descriptionEs": [
"Convierte los caracteres <code>&</code>, <code>&lt;<code>, <code>&gt;<code>, <code>\"<code>' (comilla), y <code>'<code> (apóstrofe), contenidos en la cadena de texto que se te pasa, en sus entidades HTML correspondientes", "Convierte los caracteres <code>&</code>, <code>&lt;<code>, <code>&gt;<code>, <code>\"<code>' (comilla), y <code>'<code> (apóstrofe), contenidos en la cadena de texto que se te pasa, en sus entidades HTML correspondientes",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Convertir les entités HTML",
"descriptionFr": [
"Convertis les caractères <code>&</code>, <code>&lt;<code>, <code>&gt;<code>, <code>\"<code>' (guillemet), y <code>'<code> (apostrophe), contenus dans la chaîne de caractères en entités HTML.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -511,7 +584,8 @@
"assert.deepEqual(spinalCase(\"This Is Spinal Tap\"), \"this-is-spinal-tap\", 'message: <code>spinalCase(\"This Is Spinal Tap\")</code> should return <code>\"this-is-spinal-tap\"</code>.');", "assert.deepEqual(spinalCase(\"This Is Spinal Tap\"), \"this-is-spinal-tap\", 'message: <code>spinalCase(\"This Is Spinal Tap\")</code> should return <code>\"this-is-spinal-tap\"</code>.');",
"assert.strictEqual(spinalCase('thisIsSpinalTap'), \"this-is-spinal-tap\", 'message: <code>spinalCase(\"thisIsSpinalTap\")</code> should return <code>\"this-is-spinal-tap\"</code>.');", "assert.strictEqual(spinalCase('thisIsSpinalTap'), \"this-is-spinal-tap\", 'message: <code>spinalCase(\"thisIsSpinalTap\")</code> should return <code>\"this-is-spinal-tap\"</code>.');",
"assert.strictEqual(spinalCase(\"The_Andy_Griffith_Show\"), \"the-andy-griffith-show\", 'message: <code>spinalCase(\"The_Andy_Griffith_Show\")</code> should return <code>\"the-andy-griffith-show\"</code>.');", "assert.strictEqual(spinalCase(\"The_Andy_Griffith_Show\"), \"the-andy-griffith-show\", 'message: <code>spinalCase(\"The_Andy_Griffith_Show\")</code> should return <code>\"the-andy-griffith-show\"</code>.');",
"assert.strictEqual(spinalCase(\"Teletubbies say Eh-oh\"), \"teletubbies-say-eh-oh\", 'message: <code>spinalCase(\"Teletubbies say Eh-oh\")</code> should return <code>\"teletubbies-say-eh-oh\"</code>.');" "assert.strictEqual(spinalCase(\"Teletubbies say Eh-oh\"), \"teletubbies-say-eh-oh\", 'message: <code>spinalCase(\"Teletubbies say Eh-oh\")</code> should return <code>\"teletubbies-say-eh-oh\"</code>.');",
"assert.strictEqual(spinalCase(\"AllThe-small Things\"), \"all-the-small-things\", 'message: <code>spinalCase(\"AllThe-small Things\")</code> should return <code>\"all-the-small-things\"</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -524,6 +598,11 @@
"descriptionEs": [ "descriptionEs": [
"Convierte la cadena de texto que se te pasa al formato spinal case. Spinal case es cuando escribes todas las palabras en-minúsculas-unidas-por-guiones.", "Convierte la cadena de texto que se te pasa al formato spinal case. Spinal case es cuando escribes todas las palabras en-minúsculas-unidas-por-guiones.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Trait d'union",
"descriptionFr": [
"Convertis la chaîne de caractères en spinal case. Spinal case correspond au bas-de-casse-séparé-par-des-tirets.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -565,6 +644,13 @@
"Los primeros números de la secuencia son 1, 1, 2, 3, 5 y 8, y cada número siguiente es la suma de los dos números anteriores.", "Los primeros números de la secuencia son 1, 1, 2, 3, 5 y 8, y cada número siguiente es la suma de los dos números anteriores.",
"Por ejemplo, si se te pasa el número 4, la función deberá devolver 5, ya que los números impares menores que 4 son 1, 1 y 3.", "Por ejemplo, si se te pasa el número 4, la función deberá devolver 5, ya que los números impares menores que 4 son 1, 1 y 3.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Additionner tous les nombre de Fibonacci impairs",
"descriptionFr": [
"Crée une fonction qui additionne tous les nombre de Fibonacci jusqu'au nombre donné (inclus si c'est un nombre de Fibonacci).",
"Les premiers chiffres de la séquence sont 1, 1, 2, 3, 5 y 8, et chaque nombre correspond à la somme des deux nombres précédents.",
"Par example, pour le chiffre 4, la fonction doit retourner 5, puisque les chiffres précédent 4 sont 1, 1 et 3.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -604,6 +690,13 @@
"Números primos son todos aquellos que sólo son divisibles entre 1 y entre sí mismos. Por ejemplo, el número 2 es primo porque solo es divisible por 1 y por 2. Por el contrario, el número 1 no es primo, ya que sólo puede dividirse por sí mismo", "Números primos son todos aquellos que sólo son divisibles entre 1 y entre sí mismos. Por ejemplo, el número 2 es primo porque solo es divisible por 1 y por 2. Por el contrario, el número 1 no es primo, ya que sólo puede dividirse por sí mismo",
"El número que se le provee a la función no puede ser primo", "El número que se le provee a la función no puede ser primo",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Additionner tous les nombres primaires",
"descriptionFr": [
"Additionne tous les nombres primaires jusqu'au nombre donné (inclus).",
"Un nombre primaire est un nombre divisible que par 1 ou par lui-même (plus grand que 1). Par exemple, 2 est un nombre primaire puisqu'il n'est divisible que par 1 et 2. 1 n'est pas primaire puiqu'il n'est divisible que par lui-même.",
"Le nombre donné en argument n'est pas forcément un nombre primaire.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -644,6 +737,13 @@
"Tu función debe aceptar como argumento un vector con dos números, los cuales no necesariamente estarán en orden.", "Tu función debe aceptar como argumento un vector con dos números, los cuales no necesariamente estarán en orden.",
"Por ejemplo, si se te pasan los números 1 y 3, deberás encontrar el mínimo común múltiplo de 1 y 3 que es divisible por todos los números <em>entre</em> 1 y 3.", "Por ejemplo, si se te pasan los números 1 y 3, deberás encontrar el mínimo común múltiplo de 1 y 3 que es divisible por todos los números <em>entre</em> 1 y 3.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Plus petit commun multiple",
"descriptionFr": [
"Cherche le plus petit commun multiple qui soit divisible par les deux nombres donnés et par les nombres de la série entre ces deux nombres.",
"La série est un tableau de deux nombres qui ne seront pas nécessairement dans l'ordre croissant.",
"Par exemple, pour 1 et 3, il faut trouver le plus petit commun multiple de 1 et 3 mais aussi des nombres <em>entre</em> 1 et 3/",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -654,19 +754,19 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function find(arr, func) {", "function findElement(arr, func) {",
" var num = 0;", " var num = 0;",
" return num;", " return num;",
"}", "}",
"", "",
"find([1, 2, 3, 4], function(num){ return num % 2 === 0; });" "findElement([1, 2, 3, 4], function(num){ return num % 2 === 0; });"
], ],
"solutions": [ "solutions": [
"function find(arr, func) {\n var num;\n arr.some(function(e) {\n if (func(e)) {\n num = e;\n return true;\n }\n });\n return num;\n}" "function findElement(arr, func) {\n var num;\n arr.some(function(e) {\n if (func(e)) {\n num = e;\n return true;\n }\n });\n return num;\n}"
], ],
"tests": [ "tests": [
"assert.strictEqual(find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'message: <code>find([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; })</code> should return 8.');", "assert.strictEqual(findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; }), 8, 'message: <code>findElement([1, 3, 5, 8, 9, 10], function(num) { return num % 2 === 0; })</code> should return 8.');",
"assert.strictEqual(find([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'message: <code>find([1, 3, 5, 9], function(num) { return num % 2 === 0; })</code> should return undefined.');" "assert.strictEqual(findElement([1, 3, 5, 9], function(num) { return num % 2 === 0; }), undefined, 'message: <code>findElement([1, 3, 5, 9], function(num) { return num % 2 === 0; })</code> should return undefined.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -678,6 +778,11 @@
"descriptionEs": [ "descriptionEs": [
"Crea una función que busque dentro de un vector (primer argumento) y que devuelva el primer elemento que pase una prueba de verdad (segundo argumento).", "Crea una función que busque dentro de un vector (primer argumento) y que devuelva el primer elemento que pase una prueba de verdad (segundo argumento).",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Détecteur de mensonges",
"descriptionFr": [
"Crée une fonction qui parcourt un tableau (premier argument) et renvoie le premier élément du tableau qui passe le test (second argument).",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -690,23 +795,23 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function drop(arr, func) {", "function dropElements(arr, func) {",
" // Drop them elements.", " // Drop them elements.",
" return arr;", " return arr;",
"}", "}",
"", "",
"drop([1, 2, 3], function(n) {return n < 3; });" "dropElements([1, 2, 3], function(n) {return n < 3; });"
], ],
"solutions": [ "solutions": [
"function drop(arr, func) {\n // Drop them elements.\n while (arr.length && !func(arr[0])) {\n arr.shift();\n }\n return arr;\n}" "function dropElements(arr, func) {\n // Drop them elements.\n while (arr.length && !func(arr[0])) {\n arr.shift();\n }\n return arr;\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n >= 3;}), [3, 4], 'message: <code>drop([1, 2, 3, 4], function(n) {return n >= 3;})</code> should return <code>[3, 4]</code>.');", "assert.deepEqual(dropElements([1, 2, 3, 4], function(n) {return n >= 3;}), [3, 4], 'message: <code>dropElements([1, 2, 3, 4], function(n) {return n >= 3;})</code> should return <code>[3, 4]</code>.');",
"assert.deepEqual(drop([0, 1, 0, 1], function(n) {return n === 1;}), [1, 0, 1], 'message: <code>drop([0, 1, 0, 1], function(n) {return n === 1;})</code> should return <code>[1, 0, 1]</code>.');", "assert.deepEqual(dropElements([0, 1, 0, 1], function(n) {return n === 1;}), [1, 0, 1], 'message: <code>dropElements([0, 1, 0, 1], function(n) {return n === 1;})</code> should return <code>[1, 0, 1]</code>.');",
"assert.deepEqual(drop([1, 2, 3], function(n) {return n > 0;}), [1, 2, 3], 'message: <code>drop([1, 2, 3], function(n) {return n > 0;})</code> should return <code>[1, 2, 3]</code>.');", "assert.deepEqual(dropElements([1, 2, 3], function(n) {return n > 0;}), [1, 2, 3], 'message: <code>dropElements([1, 2, 3], function(n) {return n > 0;})</code> should return <code>[1, 2, 3]</code>.');",
"assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: <code>drop([1, 2, 3, 4], function(n) {return n > 5;})</code> should return <code>[]</code>.');", "assert.deepEqual(dropElements([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: <code>dropElements([1, 2, 3, 4], function(n) {return n > 5;})</code> should return <code>[]</code>.');",
"assert.deepEqual(drop([1, 2, 3, 7, 4], function(n) {return n > 3;}), [7, 4], 'message: <code>drop([1, 2, 3, 7, 4], function(n) {return n > 3;})</code> should return <code>[7, 4]</code>.');", "assert.deepEqual(dropElements([1, 2, 3, 7, 4], function(n) {return n > 3;}), [7, 4], 'message: <code>dropElements([1, 2, 3, 7, 4], function(n) {return n > 3;})</code> should return <code>[7, 4]</code>.');",
"assert.deepEqual(drop([1, 2, 3, 9, 2], function(n) {return n > 2;}), [3, 9, 2], 'message: <code>drop([1, 2, 3, 9, 2], function(n) {return n > 2;})</code> should return <code>[3, 9, 2]</code>.');" "assert.deepEqual(dropElements([1, 2, 3, 9, 2], function(n) {return n > 2;}), [3, 9, 2], 'message: <code>dropElements([1, 2, 3, 9, 2], function(n) {return n > 2;})</code> should return <code>[3, 9, 2]</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -721,6 +826,12 @@
"Toma los elementos contenidos en el vector que se te provee en el primer argumento de la función y elimínalos uno por uno, hasta que la función provista en el segundo argumento devuelva true.", "Toma los elementos contenidos en el vector que se te provee en el primer argumento de la función y elimínalos uno por uno, hasta que la función provista en el segundo argumento devuelva true.",
"Retorna el resto del vector, de lo contrario retorna un vector vacío.", "Retorna el resto del vector, de lo contrario retorna un vector vacío.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Laisse tomber",
"descriptionFr": [
"Écarte les éléments du tableau (premier argument), en commençant par la gauche, jusqu'à ce la fonction (second argument) renvoie true.",
"Renvoie le reste du tableau, ou dans le cas contraire un tableau vide",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -731,21 +842,21 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function steamroller(arr) {", "function steamrollArray(arr) {",
" // I'm a steamroller, baby", " // I'm a steamroller, baby",
" return arr;", " return arr;",
"}", "}",
"", "",
"steamroller([1, [2], [3, [[4]]]]);" "steamrollArray([1, [2], [3, [[4]]]]);"
], ],
"solutions": [ "solutions": [
"function steamroller(arr) {\n if (!Array.isArray(arr)) {\n return [arr];\n }\n var out = [];\n arr.forEach(function(e) {\n steamroller(e).forEach(function(v) {\n out.push(v);\n });\n });\n return out;\n}" "function steamrollArray(arr) {\n if (!Array.isArray(arr)) {\n return [arr];\n }\n var out = [];\n arr.forEach(function(e) {\n steamrollArray(e).forEach(function(v) {\n out.push(v);\n });\n });\n return out;\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(steamroller([[[\"a\"]], [[\"b\"]]]), [\"a\", \"b\"], 'message: <code>steamroller([[[\"a\"]], [[\"b\"]]])</code> should return <code>[\"a\", \"b\"]</code>.');", "assert.deepEqual(steamrollArray([[[\"a\"]], [[\"b\"]]]), [\"a\", \"b\"], 'message: <code>steamrollArray([[[\"a\"]], [[\"b\"]]])</code> should return <code>[\"a\", \"b\"]</code>.');",
"assert.deepEqual(steamroller([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'message: <code>steamroller([1, [2], [3, [[4]]]])</code> should return <code>[1, 2, 3, 4]</code>.');", "assert.deepEqual(steamrollArray([1, [2], [3, [[4]]]]), [1, 2, 3, 4], 'message: <code>steamrollArray([1, [2], [3, [[4]]]])</code> should return <code>[1, 2, 3, 4]</code>.');",
"assert.deepEqual(steamroller([1, [], [3, [[4]]]]), [1, 3, 4], 'message: <code>steamroller([1, [], [3, [[4]]]])</code> should return <code>[1, 3, 4]</code>.');", "assert.deepEqual(steamrollArray([1, [], [3, [[4]]]]), [1, 3, 4], 'message: <code>steamrollArray([1, [], [3, [[4]]]])</code> should return <code>[1, 3, 4]</code>.');",
"assert.deepEqual(steamroller([1, {}, [3, [[4]]]]), [1, {}, 3, 4], 'message: <code>steamroller([1, {}, [3, [[4]]]])</code> should return <code>[1, {}, 3, 4]</code>.');" "assert.deepEqual(steamrollArray([1, {}, [3, [[4]]]]), [1, {}, 3, 4], 'message: <code>steamrollArray([1, {}, [3, [[4]]]])</code> should return <code>[1, {}, 3, 4]</code>.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -757,6 +868,11 @@
"descriptionEs": [ "descriptionEs": [
"Aplana el vector anidado que se te provee. Tu función debe poder aplanar vectores de cualquier forma.", "Aplana el vector anidado que se te provee. Tu función debe poder aplanar vectores de cualquier forma.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Rouleau compresseur",
"descriptionFr": [
"Aplatis le tableau donné. Ta fonction doit pour gérer différentes formes de tableaux.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -793,6 +909,12 @@
"Haz que la función devuelva el mensaje en inglés escondido en el código binario de la cadena de texto que se le pasa.", "Haz que la función devuelva el mensaje en inglés escondido en el código binario de la cadena de texto que se le pasa.",
"La cadena de texto binaria estará separada por espacios.", "La cadena de texto binaria estará separada por espacios.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Agent binaire",
"descriptionFr": [
"Traduis la chaîne binaire donnée en anglais.",
"La chaîne binaire comporte des espaces.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -804,26 +926,26 @@
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function every(collection, pre) {", "function truthCheck(collection, pre) {",
" // Is everyone being true?", " // Is everyone being true?",
" return pre;", " return pre;",
"}", "}",
"", "",
"every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\");" "truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\");"
], ],
"solutions": [ "solutions": [
"function every(collection, pre) {\n // Does everyone have one of these?\n return collection.every(function(e) { return e[pre]; });\n}" "function truthCheck(collection, pre) {\n // Does everyone have one of these?\n return collection.every(function(e) { return e[pre]; });\n}"
], ],
"tests": [ "tests": [
"assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), true, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")</code> should return true.');", "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), true, 'message: <code>truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\", \"sex\": \"male\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")</code> should return true.');",
"assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), false, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")</code> should return false.');", "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\"), false, 'message: <code>truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\"}, {\"user\": \"Dipsy\"}, {\"user\": \"Laa-Laa\", \"sex\": \"female\"}, {\"user\": \"Po\", \"sex\": \"female\"}], \"sex\")</code> should return false.');",
"assert.strictEqual(every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 2}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\"), false, 'message: <code>every([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 3}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\")</code> should return false.');", "assert.strictEqual(truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 2}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\"), false, 'message: <code>truthCheck([{\"user\": \"Tinky-Winky\", \"sex\": \"male\", \"age\": 0}, {\"user\": \"Dipsy\", \"sex\": \"male\", \"age\": 3}, {\"user\": \"Laa-Laa\", \"sex\": \"female\", \"age\": 5}, {\"user\": \"Po\", \"sex\": \"female\", \"age\": 4}], \"age\")</code> should return false.');",
"assert.strictEqual(every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\"), false, 'message: <code>every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\")</code> should return false');", "assert.strictEqual(truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\"), false, 'message: <code>truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true}, {\"name\": \"FastFoward\", \"onBoat\": null}], \"onBoat\")</code> should return false');",
"assert.strictEqual(every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\"), true, 'message: <code>every([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\")</code> should return true');", "assert.strictEqual(truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\"), true, 'message: <code>truthCheck([{\"name\": \"Pete\", \"onBoat\": true}, {\"name\": \"Repeat\", \"onBoat\": true, \"alias\": \"Repete\"}, {\"name\": \"FastFoward\", \"onBoat\": true}], \"onBoat\")</code> should return true');",
"assert.strictEqual(every([{\"single\": \"yes\"}], \"single\"), true, 'message: <code>every([{\"single\": \"yes\"}], \"single\")</code> should return true');", "assert.strictEqual(truthCheck([{\"single\": \"yes\"}], \"single\"), true, 'message: <code>truthCheck([{\"single\": \"yes\"}], \"single\")</code> should return true');",
"assert.strictEqual(every([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\"), false, 'message: <code>every([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\")</code> should return false');", "assert.strictEqual(truthCheck([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\"), false, 'message: <code>truthCheck([{\"single\": \"\"}, {\"single\": \"double\"}], \"single\")</code> should return false');",
"assert.strictEqual(every([{\"single\": \"double\"}, {\"single\": undefined}], \"single\"), false, 'message: <code>every([{\"single\": \"double\"}, {\"single\": undefined}], \"single\")</code> should return false');", "assert.strictEqual(truthCheck([{\"single\": \"double\"}, {\"single\": undefined}], \"single\"), false, 'message: <code>truthCheck([{\"single\": \"double\"}, {\"single\": undefined}], \"single\")</code> should return false');",
"assert.strictEqual(every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\"), false, 'message: <code>every([{\"single\": \"double\"}, {\"single\": NaN}], \"single\")</code> should return false');" "assert.strictEqual(truthCheck([{\"single\": \"double\"}, {\"single\": NaN}], \"single\"), false, 'message: <code>truthCheck([{\"single\": \"double\"}, {\"single\": NaN}], \"single\")</code> should return false');"
], ],
"isRequired": true, "isRequired": true,
"type": "bonfire", "type": "bonfire",
@ -833,6 +955,12 @@
"Verifica si la función en el segundo argumento devuelve true para todos los elementos de la colección en el primer argumento.", "Verifica si la función en el segundo argumento devuelve true para todos los elementos de la colección en el primer argumento.",
"Recuerda que puedes accesar a las propiedades de un objeto, ya sea a través de la notación por punto o de la notación por corchete usando [].", "Recuerda que puedes accesar a las propiedades de un objeto, ya sea a través de la notación por punto o de la notación por corchete usando [].",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Tout doit être vrai",
"descriptionFr": [
"Vérifie que la fonction donnée (second argument) est vraie sur tous les éléments de la collection (premier argument).",
"Tu peux utiliser un point ou des [] pour accéder aux propritétés de l'objet.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
}, },
{ {
@ -840,29 +968,29 @@
"title": "Arguments Optional", "title": "Arguments Optional",
"description": [ "description": [
"Create a function that sums two arguments together. If only one argument is provided, then return a function that expects one argument and returns the sum.", "Create a function that sums two arguments together. If only one argument is provided, then return a function that expects one argument and returns the sum.",
"For example, <code>add(2, 3)</code> should return <code>5</code>, and <code>add(2)</code> should return a function.", "For example, <code>addTogether(2, 3)</code> should return <code>5</code>, and <code>addTogether(2)</code> should return a function.",
"Calling this returned function with a single argument will then return the sum:", "Calling this returned function with a single argument will then return the sum:",
"<code>var sumTwoAnd = add(2);</code>", "<code>var sumTwoAnd = addTogether(2);</code>",
"<code>sumTwoAnd(3)</code> returns <code>5</code>.", "<code>sumTwoAnd(3)</code> returns <code>5</code>.",
"If either argument isn't a valid number, return undefined.", "If either argument isn't a valid number, return undefined.",
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code." "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck. Try to pair program. Write your own code."
], ],
"challengeSeed": [ "challengeSeed": [
"function add() {", "function addTogether() {",
" return false;", " return false;",
"}", "}",
"", "",
"add(2,3);" "addTogether(2,3);"
], ],
"solutions": [ "solutions": [
"function add() {\n var a = arguments[0];\n if (toString.call(a) !== '[object Number]') return; \n if (arguments.length === 1) {\n return function(b) {\n if (toString.call(b) !== '[object Number]') return;\n return a + b;\n };\n }\n var b = arguments[1];\n if (toString.call(b) !== '[object Number]') return; \n return a + arguments[1];\n}" "function addTogether() {\n var a = arguments[0];\n if (toString.call(a) !== '[object Number]') return; \n if (arguments.length === 1) {\n return function(b) {\n if (toString.call(b) !== '[object Number]') return;\n return a + b;\n };\n }\n var b = arguments[1];\n if (toString.call(b) !== '[object Number]') return; \n return a + arguments[1];\n}"
], ],
"tests": [ "tests": [
"assert.deepEqual(add(2, 3), 5, 'message: <code>add(2, 3)</code> should return 5.');", "assert.deepEqual(addTogether(2, 3), 5, 'message: <code>addTogether(2, 3)</code> should return 5.');",
"assert.deepEqual(add(2)(3), 5, 'message: <code>add(2)(3)</code> should return 5.');", "assert.deepEqual(addTogether(2)(3), 5, 'message: <code>addTogether(2)(3)</code> should return 5.');",
"assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'message: <code>add(\"http://bit.ly/IqT6zt\")</code> should return undefined.');", "assert.isUndefined(addTogether(\"http://bit.ly/IqT6zt\"), 'message: <code>addTogether(\"http://bit.ly/IqT6zt\")</code> should return undefined.');",
"assert.isUndefined(add(2, \"3\"), 'message: <code>add(2, \"3\")</code> should return undefined.');", "assert.isUndefined(addTogether(2, \"3\"), 'message: <code>addTogether(2, \"3\")</code> should return undefined.');",
"assert.isUndefined(add(2)([3]), 'message: <code>add(2)([3])</code> should return undefined.');" "assert.isUndefined(addTogether(2)([3]), 'message: <code>addTogether(2)([3])</code> should return undefined.');"
], ],
"type": "bonfire", "type": "bonfire",
"MDNlinks": [ "MDNlinks": [
@ -880,6 +1008,16 @@
"<code>sumTwoAnd(3)</code> devuelve <code>5</code>.", "<code>sumTwoAnd(3)</code> devuelve <code>5</code>.",
"Si alguno de los argumentos no es un número válido, haz que devuelva undefined.", "Si alguno de los argumentos no es un número válido, haz que devuelva undefined.",
"Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código." "Recuerda utilizar <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Leer-Buscar-Preguntar</a> si te sientes atascado. Intenta programar en pareja. Escribe tu propio código."
],
"titleFr": "Arguments optionnels",
"descriptionFr": [
"Crée une fonction qui additionne deux arguments. Si un seul argument est donné, renvoie une fonction qui attend un argument et renvoie la somme.",
"Par exemple, <code>add(2, 3)</code>, doit renvoyer <code>5</code>, et <code>add(2)</code> doit renvoyer une fonction.",
"Appeler cette fonction avec un seul argument renvoie la somme:",
"<code>var sumTwoAnd = add(2);</code>",
"<code>sumTwoAnd(3)</code> renvoie <code>5</code>.",
"Si aucun argument n'est un nombre, renvoie undefined.",
"N'oublie pas d'utiliser <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Lire-Chercher-Demander</a> si tu es bloqué. Essaye de trouver un partenaire. Écris ton propre code."
] ]
} }
] ]

View File

@ -547,8 +547,8 @@
"Using jQuery, you can change the text between the start and end tags of an element. You can even change HTML markup.", "Using jQuery, you can change the text between the start and end tags of an element. You can even change HTML markup.",
"jQuery has a function called <code>.html()</code> that lets you add HTML tags and text within an element. Any content previously within the element will be completely replaced with the content you provide using this function.", "jQuery has a function called <code>.html()</code> that lets you add HTML tags and text within an element. Any content previously within the element will be completely replaced with the content you provide using this function.",
"Here's how you would rewrite and italicize the text of our heading:", "Here's how you would rewrite and italicize the text of our heading:",
"<code>$(\"h3\").html(\"&#60;i&#62;jQuery Playground&#60;/i&#62;\");</code>", "<code>$(\"h3\").html(\"&#60;em&#62;jQuery Playground&#60;/em&#62;\");</code>",
"jQuery also has a similar function called <code>.text()</code> that only alters text without adding tags.", "jQuery also has a similar function called <code>.text()</code> that only alters text without adding tags. In other words, this function will not evaluate any HTML tags passed to it, but will instead treat it as text you want to replace with.",
"Change the button with id <code>target4</code> by italicizing its text." "Change the button with id <code>target4</code> by italicizing its text."
], ],
"releasedOn": "November 18, 2015", "releasedOn": "November 18, 2015",
@ -556,7 +556,7 @@
"fccss", "fccss",
" $(document).ready(function() {", " $(document).ready(function() {",
" $(\"#target1\").css(\"color\", \"red\");", " $(\"#target1\").css(\"color\", \"red\");",
"", " ",
" });", " });",
"fcces", "fcces",
"", "",
@ -585,9 +585,10 @@
"</div>" "</div>"
], ],
"tests": [ "tests": [
"assert.isTrue((/<i>#target4<\\/i>/gi).test($(\"#target4\").html()), 'message: Italicize the text in your <code>target4</code> button by adding HTML tags.');", "assert.isTrue((/<em>#target4<\\/em>/gi).test($(\"#target4\").html()), 'message: Italicize the text in your <code>target4</code> button by adding HTML tags.');",
"assert($(\"#target4\") && $(\"#target4\").text() === '#target4', 'message: Make sure the text is otherwise unchanged.');", "assert($(\"#target4\") && $(\"#target4\").text() === '#target4', 'message: Make sure the text is otherwise unchanged.');",
"assert.isFalse((/<i>/gi).test($(\"h3\").html()), 'message: Do not alter any other text.');" "assert.isFalse((/<em>/gi).test($(\"h3\").html()), 'message: Do not alter any other text.');",
"assert(code.match(/\\.html\\(/g), 'message: Make sure you are using <code>.html()</code> and not <code>.text()</code>.');"
], ],
"type": "waypoint", "type": "waypoint",
"challengeType": 0, "challengeType": 0,

View File

@ -67,7 +67,7 @@
"<strong>Rule #3:</strong> You must use both Sass and React to build this project.", "<strong>Rule #3:</strong> You must use both Sass and React to build this project.",
"<strong>User Story:</strong> I can see a table of the Free Code Camp campers who've earned the most brownie points in the past 30 days.", "<strong>User Story:</strong> I can see a table of the Free Code Camp campers who've earned the most brownie points in the past 30 days.",
"<strong>User Story:</strong> I can see how many brownie points they've earned in the past 30 days, and how many they've earned total.", "<strong>User Story:</strong> I can see how many brownie points they've earned in the past 30 days, and how many they've earned total.",
"<strong>User Story:</strong> I can toggle between sorting the list by how many bronwie points they've earned in the past 30 days and by how many brownie points they've earned total.", "<strong>User Story:</strong> I can toggle between sorting the list by how many brownie points they've earned in the past 30 days and by how many brownie points they've earned total.",
"<strong>Hint:</strong> To get the top 100 campers for the last 30 days: <a href='http://fcctop100.herokuapp.com/api/fccusers/top/recent' target='_blank'>http://fcctop100.herokuapp.com/api/fccusers/top/recent</a>.", "<strong>Hint:</strong> To get the top 100 campers for the last 30 days: <a href='http://fcctop100.herokuapp.com/api/fccusers/top/recent' target='_blank'>http://fcctop100.herokuapp.com/api/fccusers/top/recent</a>.",
"<strong>Hint:</strong> To get the top 100 campers of all time: <a href='http://fcctop100.herokuapp.com/api/fccusers/top/alltime' target='_blank'>http://fcctop100.herokuapp.com/api/fccusers/top/alltime</a>.", "<strong>Hint:</strong> To get the top 100 campers of all time: <a href='http://fcctop100.herokuapp.com/api/fccusers/top/alltime' target='_blank'>http://fcctop100.herokuapp.com/api/fccusers/top/alltime</a>.",
"Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.", "Remember to use <a href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-get-help-when-you-get-stuck' target='_blank'>Read-Search-Ask</a> if you get stuck.",

View File

@ -109,7 +109,7 @@
[ [
"//i.imgur.com/F7i5Hhi.gif", "//i.imgur.com/F7i5Hhi.gif",
"Una imagen gif que te muestra cómo llenar el formulario para crear un área de trabajo nueva", "Una imagen gif que te muestra cómo llenar el formulario para crear un área de trabajo nueva",
"En vez de iniciar desde cero, recomendamos utilizar Clementine.js, un modelo (<em>bolierplate</em>) de JavaScript pila completa (full stack) que viene con código básico ya escrito para ti. Clementine.js tiene un tutorial detallado que puedes seguir para construirlo por ti mismo, pero por ahora simplemente vamos a clonarlo. En c9.io, dale un nombre a tu área de trabajo, luego deja \"Plantilla\" (\"Template\") como personalizado y crea tu espacio de trabajo usando el siguiente url de Github: <code>https://github.com/johnstonbl01/clementinejs-fcc.git</code>", "En vez de iniciar desde cero, recomendamos utilizar Clementine.js, un modelo (<em>bolierplate</em>) de JavaScript pila completa (full stack) que viene con código básico ya escrito para ti. Clementine.js tiene un tutorial detallado que puedes seguir para construirlo por ti mismo, pero por ahora simplemente vamos a clonarlo. En c9.io, dale un nombre a tu área de trabajo, luego deja \"Plantilla\" (\"Template\") como personalizado y crea tu espacio de trabajo usando el siguiente url de GitHub: <code>https://github.com/johnstonbl01/clementinejs-fcc.git</code>",
"" ""
], ],
[ [

View File

@ -52,7 +52,7 @@
"assert(code.match(/console\\.log\\(typeof[\\( ][\"'].*[\"']\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> a string.');", "assert(code.match(/console\\.log\\(typeof[\\( ][\"'].*[\"']\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> a string.');",
"assert(code.match(/console\\.log\\(typeof[\\( ]\\d+\\.?\\d*\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> a number.');", "assert(code.match(/console\\.log\\(typeof[\\( ]\\d+\\.?\\d*\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> a number.');",
"assert(code.match(/console\\.log\\(typeof[\\( ]\\[\\]\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> an array.');", "assert(code.match(/console\\.log\\(typeof[\\( ]\\[\\]\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> an array.');",
"assert(code.match(/console\\.log\\(typeof[\\( ]\\{\\}\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> a object.');" "assert(code.match(/console\\.log\\(typeof[\\( ]\\{\\}\\)?\\);/), 'message: You should <code>console.log</code> the <code>typeof</code> an object.');"
], ],
"type": "waypoint", "type": "waypoint",
"challengeType": 1, "challengeType": 1,

View File

@ -118,7 +118,34 @@
"" ""
] ]
], ],
"titleEs": "Reclama tu certificado de desarrollo del lado del servidor" "titleEs": "Reclama tu certificado de desarrollo del lado del servidor",
"titleFr": "Demandez votre certificat de développement Back End",
"descriptionFr": [
[
"//i.imgur.com/8v3t84p.jpg",
"Une image de notre certificat de développement Back End",
"Ce défi vous donnera votre certificat de développement Back End authentifié. Avant que nous ne vous le donnions, nous devons vérifier que vous avez complété tous les projets de développement Back End. Vous devez aussi accepter notre serment de droiture académique. Cliquez le bouton ci-dessous pour commencer cette procédure.",
""
],
[
"//i.imgur.com/HArFfMN.jpg",
"La définition du plagiat: Plagiat (nom) - copier le travail de quelqu'un d'autre et le presenter comme le votre sans lui en donner crédit.",
"En cliquant ci dessous, vous faites le serment que tout le code que vous avez mis en ligne A) est un code que vous ou un pair avez personellement écrit, ou B) qu'il provient de librairies open-source comme jQuery, ou C) qu'il a été cmairement attribué à ses auteurs originaux. Vous nous donnez la permission de consulter vos solutions aux défis et de révoquer votre certificat si nous y trouvons une preuve de plagiat.",
"#"
],
[
"//i.imgur.com/2qn7tHp.jpg",
"Une image du texte \"Back End Development Certificate requirements\"",
"Confirmons que vous avez complété nos projets de développement Back End. Cliquez sur le bouton ci dessous pour vérifier.",
"#"
],
[
"//i.imgur.com/16SIhHO.jpg",
"Une image du mot \"Congratulations\"",
"Félicitations! Nous avons ajouté votre certificat de développement Back End à votre page portfolio. A moins que vous ne choisissiez de cacher vos solutions, ce certificat restera publiquement visible et vérifiable.",
""
]
]
} }
] ]
} }

View File

@ -225,7 +225,7 @@
], ],
"tests": [ "tests": [
[ [
"1 === on and 0 ===off", "1 == on and 0 == off",
true true
], ],
[ [
@ -313,7 +313,7 @@
"Data speed and data size are measured differently.", "Data speed and data size are measured differently.",
"In this video, we cover how data speed is measured.", "In this video, we cover how data speed is measured.",
"Let's talk about data speed.", "Let's talk about data speed.",
"Data speed, unlike data size, is usually measured in bits per second, whereas size is usually measured in bits.", "Data speed, unlike data size, is usually measured in bits per second, whereas data size is usually measured in bytes.",
"Once we start talking exponentially, that makes a really big difference.", "Once we start talking exponentially, that makes a really big difference.",
"How we talk about speed really depends on what we're talking about.", "How we talk about speed really depends on what we're talking about.",
"In audio download, we talk about kilobits per second.", "In audio download, we talk about kilobits per second.",

View File

@ -526,7 +526,7 @@ module.exports = function(app) {
} }
function completedChallenge(req, res, next) { function completedChallenge(req, res, next) {
req.checkBody('id', 'id must be a ObjectId').isMongoId(); req.checkBody('id', 'id must be an ObjectId').isMongoId();
req.checkBody('name', 'name must be at least 3 characters') req.checkBody('name', 'name must be at least 3 characters')
.isString() .isString()
.isLength({ min: 3 }); .isLength({ min: 3 });

View File

@ -337,7 +337,7 @@ module.exports = function(app) {
function newStory(req, res, next) { function newStory(req, res, next) {
if (!req.user.isGithubCool) { if (!req.user.isGithubCool) {
req.flash('errors', { req.flash('errors', {
msg: 'You must authenticate with Github to post to Camper News' msg: 'You must authenticate with GitHub to post to Camper News'
}); });
return res.redirect('/news'); return res.redirect('/news');
} }

View File

@ -35,7 +35,7 @@ const certViews = {
}; };
const certText = { const certText = {
[certTypes.fronEnd]: 'Front End certified', [certTypes.frontEnd]: 'Front End certified',
[certTypes.dataVis]: 'Data Vis Certified', [certTypes.dataVis]: 'Data Vis Certified',
[certTypes.backEnd]: 'Back End Certified', [certTypes.backEnd]: 'Back End Certified',
[certTypes.fullStack]: 'Full Stack Certified' [certTypes.fullStack]: 'Full Stack Certified'

View File

@ -6,6 +6,8 @@ const MongoStore = MongoStoreFactory(session);
export default function sessionsMiddleware() { export default function sessionsMiddleware() {
return session({ return session({
// 900 day session cookie
cookie: { maxAge: 900 * 24 * 60 * 60 * 1000 },
resave: true, resave: true,
saveUninitialized: true, saveUninitialized: true,
secret: secrets.sessionSecret, secret: secrets.sessionSecret,

View File

@ -59,7 +59,7 @@ var passportOptions = {
null; null;
// create random username // create random username
// username will be assigned when camper signups for Github // username will be assigned when camper signups for GitHub
var username = 'fcc' + uuid.v4().slice(0, 8); var username = 'fcc' + uuid.v4().slice(0, 8);
var password = generateKey('password'); var password = generateKey('password');
var userObj = { var userObj = {

View File

@ -36,12 +36,12 @@ block content
a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='/commit') a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='/commit')
| Edit my pledge | Edit my pledge
.spacer .spacer
h2.text-center Privacy Settings h2.text-center Privacy Settings
.row .row
.col-xs-12.col-sm-8.col-sm-offset-2.col-md-6.col-md-offset-3 .col-xs-12.col-sm-8.col-sm-offset-2.col-md-6.col-md-offset-3
.row .row
.col-xs-9 .col-xs-9
p.large-p Make all of my solutions private p.large-p Make all of my solutions private
br br
| (this disables your certificates) | (this disables your certificates)
if (user.isLocked) if (user.isLocked)

View File

@ -124,7 +124,7 @@ block content
td.col-xs-2.hidden-xs= challenge.completedDate ? challenge.completedDate : 'Not Available' td.col-xs-2.hidden-xs= challenge.completedDate ? challenge.completedDate : 'Not Available'
td.col-xs-2.hidden-xs= challenge.lastUpdated ? challenge.lastUpdated : '' td.col-xs-2.hidden-xs= challenge.lastUpdated ? challenge.lastUpdated : ''
td.col-xs-2.hidden-xs td.col-xs-2.hidden-xs
a(href=challenge.solution, target='_blank') View my project a(href=challenge.solution, target='_blank') View project
td.col-xs-12.visible-xs td.col-xs-12.visible-xs
a(href=challenge.solution, target='_blank')= removeOldTerms(challenge.name) a(href=challenge.solution, target='_blank')= removeOldTerms(challenge.name)
if (algorithms.length > 0) if (algorithms.length > 0)

View File

@ -4,12 +4,12 @@ block content
h2 Sign in with one of these options: h2 Sign in with one of these options:
a.btn.btn-lg.btn-block.btn-social.btn-github(href='/auth/github') a.btn.btn-lg.btn-block.btn-social.btn-github(href='/auth/github')
i.fa.fa-github i.fa.fa-github
| Sign in with Github | Sign in with GitHub
a.btn.btn-lg.btn-block.btn-social.btn-facebook(href='/auth/facebook') a.btn.btn-lg.btn-block.btn-social.btn-facebook(href='/auth/facebook')
i.fa.fa-facebook i.fa.fa-facebook
| Sign in with Facebook | Sign in with Facebook
a.btn.btn-lg.btn-block.btn-social.btn-google-plus(href='/auth/google') a.btn.btn-lg.btn-block.btn-social.btn-google(href='/auth/google')
i.fa.fa-google-plus i.fa.fa-google
| Sign in with Google | Sign in with Google
a.btn.btn-lg.btn-block.btn-social.btn-linkedin(href='/auth/linkedin') a.btn.btn-lg.btn-block.btn-social.btn-linkedin(href='/auth/linkedin')
i.fa.fa-linkedin i.fa.fa-linkedin

View File

@ -5,7 +5,7 @@ block content
h4.text-center.challenge-instructions-title= name h4.text-center.challenge-instructions-title= name
if (isCompleted) if (isCompleted)
| &nbsp; | &nbsp;
i.ion-checkmark-circled.text-primary(title="Completed") i.ion-checkmark-circled.text-primary(title="Completed")
hr hr
ol ol
for step, index in description for step, index in description

View File

@ -1,6 +1,6 @@
doctype xml doctype xml
rss(version="2.0", xmlns:atom="http://www.w3.org/2005/Atom") rss(version="2.0", xmlns:atom="http://www.w3.org/2005/Atom")
channel channel
title= title title= title
link= url link= url
description= description description= description

View File

@ -1,4 +1,3 @@
script(type='text/javascript', src='/js/lib/jailed/jailed.js')
script(src=rev('/js', 'vendor-challenges.js')) script(src=rev('/js', 'vendor-challenges.js'))
script(src=rev('/js', 'commonFramework.js')) script(src=rev('/js', 'commonFramework.js'))
script. script.

View File

@ -1,15 +1,15 @@
extends ../layout extends ../layout
block content block content
.row .row
.col-xs-12.col-sm-10.col-sm-offset-1.col-md-6.col-md-offset-3 .col-xs-12.col-sm-10.col-sm-offset-1.col-md-6.col-md-offset-3
h2.text-center Statistics h2.text-center Statistics
hr hr
ul.population-table ul.population-table
li li
span.tag Established:&#9; span.tag Established:&#9;
span.text-primary #{daysRunning} span.text-primary #{daysRunning}
| days ago | days ago
li li
span.tag Population:&#9; span.tag Population:&#9;
span.text-primary #{camperCount} span.text-primary #{camperCount}
| campers | campers
@ -74,7 +74,7 @@ block content
a(href="/code-of-conduct") Our code of conduct a(href="/code-of-conduct") Our code of conduct
tr tr
td.text-center td.text-center
i.fa.fa-university i.fa.fa-university
td td
a(href="/academic-honesty") Our academic honesty policy a(href="/academic-honesty") Our academic honesty policy
tr tr

View File

@ -1,9 +1,9 @@
.row .row
.col-xs-12 .col-xs-12
h2 We are retiring Camper News in favor of our h2 We are retiring Camper News in favor of our
a(href='http://reddit.com/r/freecodecamp') Subreddit a(href='http://reddit.com/r/freecodecamp') Subreddit
| . | .
h3 Thank you to all of the campers who have contributed links over the past year. We will keep Camper News accessible until May. Our h3 Thank you to all of the campers who have contributed links over the past year. We will keep Camper News accessible until May. Our
a(href='http://reddit.com/r/freecodecamp') Subreddit a(href='http://reddit.com/r/freecodecamp') Subreddit
| &thinsp; is now the best place to share coding-related links. | &thinsp; is now the best place to share coding-related links.
.spacer .spacer

View File

@ -1,7 +1,7 @@
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import sinon from 'sinon'; import sinon from 'sinon';
import { import {
prepUniqueDays, prepUniqueDays,
calcCurrentStreak, calcCurrentStreak,
calcLongestStreak calcLongestStreak