npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

workshopper-exercise

v3.0.3

Published

An exercise runner component for the Workshopper framework

Downloads

804

Readme

NPM

How to fail an exercise

In /exercises/${EXERCISE_NAME}/exercise.js:

const exercise = require('workshopper-exercise')();

function sureToFail(errback) {
    exercise.emit('fail', 'told you it was going to fail');
    errback(null, false);
}

exercise.addVerifyProcessor(sureToFail);

module.exports = exercise;

This exercise will always fail, with the output:

 ✗ 

 told you it was going to fail

 # FAIL Your solution to ${EXERCISE_NAME} didn't pass. Try again!

─────────────────────────────────────────────────────────────────────────────

  » To print these instructions again, run: ${WORKSHOP_NAME} print
  » To execute your program in a test environment, run: ${WORKSHOP_NAME} run
    program.js
  » To verify your program, run: ${WORKSHOP_NAME} verify program.js
  » For help run: ${WORKSHOP_NAME} help 

How use i18n-ed messages in an exercise

The term "i18n" is short for "internationalisation". A workshopper exercise can surface messages in multiple languages through its built-in i18n functionality:

  1. Use exercise.__(...) in place of hard-coded strings, and
  2. add the values to the relevant i18n file, as per workshopper's folder structure conventions.

In /exercises/${EXERCISE_NAME}/exercise.js:

const exercise = require('workshopper-exercise')();

function pureLuck(errback) {
    const chance = Math.random();
    const pass = chance < 0.5;
    if (pass) {
        exercise.emit('pass', exercise.__('pass.lucky', { chance }));
    } else {
        exercise.emit('fail', exercise.__('fail.unlucky', { chance }));
    }
    errback(null, pass);
}

exercise.addVerifyProcessor(pureLuck);

module.exports = exercise;

exercise.__(...):

  • The 1st parameter is a . delimited key used for lookups in i18n files.
  • The 2nd (optional) parameter is a hash of substitutions, and should be used for messages whose content is dynamic.

In /i18n/${LANGUAGE_CODE}.json:

{
  ...
  "exercises": {
    "${EXERCISE_NAME}": {
      "pass": {
        "lucky": "You were lucky :) {{chance}}"
    },
      "fail": {
        "unlucky": "You were unlucky :( {{chance}}"
      }
    }
  }
}

Workshopper's i18n looks in several different places for the string values, as i18n is used in many other parts of workshopper. For exercises, the logical place to put them is in exercises -> ${EXERCISE_NAME} -> .... The pass and fail sub-objects are merely convention, and you do not have to use them - any nesting below this is completely free-form. The {{...}} are markers for templating, using key-value pairs from the 2nd parameter to exercise.__(...).

In order for your exercise to display multiple languages, you will need to create one of these files per language, where the keys are identical and the values are translated into each language. For example, the line for pass.lucky for the தமிழ் language would be: "lucky": "நீ அதிர்ஷ்டசாலி :) {{chance}}", and would be in the /i18n/ta.json file.

When this exercise fails, it will output:

 ✗ 

 You were unlucky :( 0.5738622391092318

 # FAIL Your solution to ${EXERCISE_NAME} didn't pass. Try again!

─────────────────────────────────────────────────────────────────────────────

  » To print these instructions again, run: ${WORKSHOP_NAME} print
  » To execute your program in a test environment, run: ${WORKSHOP_NAME} run                                                                          
    program.js                                                                
  » To verify your program, run: ${WORKSHOP_NAME} verify program.js            
  » For help run: ${WORKSHOP_NAME} help

... and when it passes, it will output:

 ✓ 

 You were lucky :) 0.2753477873643899

 # PASS Your solution to ${EXERCISE_NAME} passed!

 You have ${REMAINING_EXERCISE_COUNT} challenges left.

 Type '${WORKSHOP_NAME}' to show the menu.

─────────────────────────────────────────────────────────────────────────────

  » To print these instructions again, run: ${WORKSHOP_NAME} print             
  » To execute your program in a test environment, run: ${WORKSHOP_NAME} run
    program.js
  » To verify your program, run: ${WORKSHOP_NAME} verify program.js
  » For help run: ${WORKSHOP_NAME} help

How to get command line arguments

The command line arguments passed into the verify subcommand can be accessed within an exercise via the args property.

In /exercises/${EXERCISE_NAME}/exercise.js:

const exercise = require('workshopper-exercise')();

function firstArgMustBeFoo(errback) {
    const pass = exercise.args[0] === 'foo';
    if (pass) {
      exercise.emit('pass', 'first CLI argument was foo');
    } else {
      exercise.emit('fail', 'first CLI argument wasn\'t foo');
    }
    errback(null, pass);
}

exercise.addVerifyProcessor(firstArgMustBeFoo);

module.exports = exercise;

Command line arguments have a variety of use cases, and in workshopper exercises, one would typically use it to specify the submission file name.

When you run ${WORKSHOP_NAME} verify bar, it will output:

 ✗ 

 first CLI argument wasn't foo

 # FAIL Your solution to ${EXERCISE_NAME} didn't pass. Try again!

─────────────────────────────────────────────────────────────────────────────

  » To print these instructions again, run: ${WORKSHOP_NAME} print
  » To execute your program in a test environment, run: ${WORKSHOP_NAME} run
    program.js
  » To verify your program, run: ${WORKSHOP_NAME} verify program.js
  » For help run: ${WORKSHOP_NAME} help

... and when you run ${WORKSHOP_NAME} verify foo, it will output:

 ✓ 

 first CLI argument was foo

 # PASS Your solution to ${EXERCISE_NAME} passed!

 You have ${REMAINING_EXERCISE_COUNT} challenges left.

 Type '${WORKSHOP_NAME}' to show the menu.

─────────────────────────────────────────────────────────────────────────────

  » To print these instructions again, run: ${WORKSHOP_NAME} print
  » To execute your program in a test environment, run: ${WORKSHOP_NAME} run
    program.js
  » To verify your program, run: ${WORKSHOP_NAME} verify program.js
  » For help run: ${WORKSHOP_NAME} help