Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

workshopper-adventure

Package Overview
Dependencies
Maintainers
1
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

workshopper-adventure - npm Package Compare versions

Comparing version 3.4.2 to 3.4.3

lib/appDirFilter.js

314

adventure.js

@@ -7,2 +7,3 @@ const minimist = require('minimist')

, chalk = require('chalk')
, commandico = require('commandico')
, inherits = require('util').inherits

@@ -12,6 +13,8 @@ , EventEmitter = require('events').EventEmitter

/* jshint -W079 */
const createMenu = require('simple-terminal-menu')
, print = require('./print-text')
, util = require('./util')
, i18n = require('./i18n')
const createMenu = require('simple-terminal-menu')
, print = require('./lib/print')
, util = require('./util')
, i18n = require('./i18n')
, storage = require('./lib/storage')
, error = print.error
/* jshint +W079 */

@@ -21,2 +24,10 @@

function legacyCommands(item) {
if (!item.aliases)
item.aliases = []
if (item && item.name)
item.aliases.unshift(item.name)
return item
}
function Adventure (options) {

@@ -32,6 +43,6 @@ if (!(this instanceof Adventure))

if (typeof options !== 'object')
throw new TypeError('need to provide an options object')
return error('You need to provide an options object')
if (typeof options.name !== 'string')
throw new TypeError('need to provide a `name` String option')
return error('You need to provide a `name` String option')

@@ -46,4 +57,7 @@ this.name = options.name

this.globalDataDir = util.userDir('.config', 'workshopper')
this.dataDir = util.userDir('.config', this.appName)
this.global = storage(storage.userDir, '.config', 'workshopper')
this.local = storage(storage.userDir, '.config', this.appName)
this.globalDataDir = this.global.dir
this.dataDir = this.local.dir

@@ -94,39 +108,5 @@ // Backwards compatibility with adventure

this.commands = Array.isArray(options.commands) ? options.commands : []
this.options = options
}
inherits(Adventure, EventEmitter)
Adventure.prototype.execute = function (args) {
var mode = args[0]
, handled = false
, argv = minimist(args, {
alias: {
h: 'help',
l: 'lang',
v: 'version',
select: 'print',
selected: 'current'
}
})
try {
this.lang = i18n.chooseLang(
this.globalDataDir
, this.dataDir
, argv.lang
, this.defaultLang
, this.options.languages
)
} catch (e) {
if (e instanceof TypeError) // In case the language couldn't be selected
console.log(e.message)
else
console.error(e.stack)
process.exit(1)
}
this.i18n = i18n.init(this.options, this.exercises, this.lang, this.globalDataDir)
this.i18n = i18n.init(this.options, this.exercises, this.global, this.local, this.defaultLang)
this.__ = this.i18n.__

@@ -139,2 +119,3 @@ this.__n = this.i18n.__n

this.__defineGetter__('subtitle', this.__.bind(this, 'subtitle'))
this.__defineGetter__('lang', this.i18n.lang.bind(this.i18n, 'lang'))
this.__defineGetter__('width', function () {

@@ -144,89 +125,16 @@ return this.menuOptions.width

this.current = this.getData('current')
this.current = this.local.get('current')
if (this.commands)
this.commands.forEach(function (item) {
if (mode == item.name
|| argv[item.name]
|| (item.short && argv[item.short])) {
handled = true
return item.handler(this)
}
}.bind(this))
this.app = commandico(this, 'menu')
.loadCommands(path.join(__dirname, 'lib/commands'))
.loadModifiers(path.join(__dirname, 'lib/modifiers'))
.addCommands((options.commands || []).map(legacyCommands))
.addModifiers((options.modifiers || []).map(legacyCommands))
}
inherits(Adventure, EventEmitter)
if (argv.version || mode == 'version')
return console.log(
this.appName
+ '@'
+ require(path.join(this.appDir, 'package.json')).version
)
if (handled)
return
if (argv.help || mode == 'help')
return this._printHelp()
if (mode == 'list') {
return this.exercises.forEach(function (name) {
console.log(this.__('exercise.' + name))
}.bind(this))
}
if (mode == 'current')
return console.log(this.__('exercise.' + this.current))
if (mode == 'print') {
var selected = argv._.length > 1 ? argv._.slice(1).join(' ') : this.current
if (/[0-9]+/.test(selected)) {
selected = this.exercises[parseInt(selected-1, 10)] || selected
} else {
selected = this.exercises.filter(function (exercise) {
return selected === this.__('exercise.' + exercise)
}.bind(this))[0] || selected;
}
onselect.call(this, selected)
return
}
if (mode == 'verify' || mode == 'run') {
if (!this.current)
return error(this.__('error.exercise.none_active'))
exercise = this.loadExercise(this.current)
if (!exercise)
return error(this.__('error.exercise.missing', {name: name}))
if (exercise.requireSubmission !== false && argv._.length == 1)
return error(this.__('ui.usage', {appName: this.appName, mode: mode}))
return this.runExercise(exercise, mode, argv._.slice(1))
}
if (mode == 'next') {
var remainingAfterCurrent = this.exercises.slice(this.exercises.indexOf(this.current))
var completed = this.getData('completed')
if (!completed)
return error(this.__('error.exercise.none_active') + '\n')
var incompleteAfterCurrent = remainingAfterCurrent.filter(function (elem) {
return completed.indexOf(elem) < 0
})
if (incompleteAfterCurrent.length === 0)
return console.log(this.__('error.no_uncomplete_left') + '\n')
return onselect.call(this, incompleteAfterCurrent[0])
}
if (mode == 'reset') {
this.reset()
return console.log(this.__('progress.reset', {title: this.__('title')}))
}
this.printMenu()
Adventure.prototype.execute = function (args) {
return this.app.execute(args)
}

@@ -243,3 +151,3 @@

? fn_or_object
: { name: name_or_object }
: {}

@@ -256,3 +164,3 @@ if (typeof name_or_object === 'string')

if (!meta.dir)
meta.dir = this.dirFromName(meta.name)
meta.dir = util.dirFromName(this.exerciseDir, meta.name)

@@ -305,3 +213,2 @@ if (meta.dir && !meta.exerciseFile)

// overall exercise fail

@@ -323,14 +230,10 @@ Adventure.prototype.exerciseFail = function (mode, exercise) {

var done = function done () {
var completed = this.getData('completed') || []
var completed = this.local.get('completed') || []
, remaining
this.updateData('completed', function (xs) {
if (!xs)
xs = []
if (completed.indexOf(exercise.meta.name) === -1)
completed.push(exercise.meta.name)
return xs.indexOf(exercise.meta.name) >= 0 ? xs : xs.concat(exercise.meta.name)
})
this.local.save('completed', completed)
completed = this.getData('completed') || []
remaining = this.exercises.length - completed.length

@@ -344,4 +247,4 @@

}
if (exercise.solution)
if (typeof exercise.getSolutionFiles !== 'function' && exercise.solution)
print.text(this.appName, this.appDir, exercise.solutionType || 'txt', exercise.solution)

@@ -363,2 +266,3 @@

if (!exercise.hideSolutions && typeof exercise.getSolutionFiles === 'function') {

@@ -412,3 +316,2 @@ exercise.getSolutionFiles(function (err, files) {

// single 'pass' event for a validation

@@ -425,3 +328,2 @@ function onpass (msg) {

Adventure.prototype.runExercise = function (exercise, mode, args) {

@@ -476,40 +378,6 @@ // individual validation events

Adventure.prototype.selectLanguage = function (lang) {
this.i18n.change(this.globalDataDir, this.dataDir, lang, this.defaultLang, this.i18n.languages)
this.lang = lang
this.printMenu()
}
Adventure.prototype.printLanguageMenu = function () {
var __ = this.i18n.__
, menu = createMenu(this.menuOptions)
, completed = this.getData('completed') || []
menu.writeLine(chalk.bold(__('title')))
if (this.i18n.has('subtitle'))
menu.writeLine(chalk.italic(__('subtitle')))
menu.writeSeparator()
this.i18n.languages.forEach(function (language) {
var label = chalk.bold('»') + ' ' + __('language.' + language)
, marker = (this.lang === language) ? '[' + __('language._current') + ']' : ''
menu.add(label, marker, this.selectLanguage.bind(this, language))
}.bind(this))
menu.writeSeparator()
menu.add(chalk.bold(__('menu.cancel')), this.printMenu.bind(this))
menu.add(chalk.bold(__('menu.exit')), this._exit.bind(this))
}
Adventure.prototype._exit = function () {
process.exit(0)
}
Adventure.prototype.printMenu = function () {
var __ = this.i18n.__
, menu = createMenu(this.menuOptions)
, completed = this.getData('completed') || []
, completed = this.local.get('completed') || []

@@ -526,3 +394,3 @@ menu.writeLine(chalk.bold(__('title')))

, marker = (completed.indexOf(exercise) >= 0) ? '[' + __('menu.completed') + ']' : ''
menu.add(label, marker, onselect.bind(this, exercise))
menu.add(label, marker, this.printExercise.bind(this, exercise))
}.bind(this))

@@ -532,76 +400,13 @@

menu.add(chalk.bold(__('menu.help')), this._printHelp.bind(this))
if (this.i18n.languages && this.i18n.languages.length > 1)
menu.add(chalk.bold(__('menu.language')), this.printLanguageMenu.bind(this))
this.commands.filter(function (extra) {
this.app.commands.reverse().filter(function (extra) {
return extra.menu !== false
}).forEach(function (extra) {
}.bind(this)).forEach(function (extra) {
menu.add(chalk.bold(__('menu.' + extra.name)), extra.handler.bind(extra, this))
}.bind(this))
menu.add(chalk.bold(__('menu.exit')), this._exit.bind(this))
menu.add(chalk.bold(__('menu.exit')), process.exit.bind(process, 0))
}
Adventure.prototype.getData = function (name) {
var file = path.resolve(this.dataDir, name + '.json')
try {
return JSON.parse(fs.readFileSync(file, 'utf8'))
} catch (e) {}
return null
}
Adventure.prototype.updateData = function (id, fn) {
var json = {}
, file
try {
json = this.getData(id)
} catch (e) {}
file = path.resolve(this.dataDir, id + '.json')
fs.writeFileSync(file, JSON.stringify(fn(json)))
}
Adventure.prototype.reset = function () {
fs.unlink(path.resolve(this.dataDir, 'completed.json'), function () {})
fs.unlink(path.resolve(this.dataDir, 'current.json'), function () {})
}
Adventure.prototype.dirFromName = function (name) {
return util.dirFromName(this.exerciseDir, name)
}
Adventure.prototype._printHelp = function () {
var part
, stream = require("combined-stream").create()
if (this.helpFile)
part = print.localisedFileStream(this.appName, this.appDir, this.helpFile, this.lang)
if (part)
stream.append(part)
part = print.localisedFirstFileStream(this.appName, this.appDir, [
path.join(__dirname, './i18n/usage/{lang}.txt'),
path.join(__dirname, './i18n/usage/en.txt')
], this.lang)
if (part)
stream.append(part)
stream.pipe(process.stdout)
}
Adventure.prototype.getExerciseMeta = function (name) {
return this._meta[util.idFromName(name)]
}
Adventure.prototype.loadExercise = function (name) {
var meta = this.getExerciseMeta(name)
var meta = this._meta[util.idFromName(name)]

@@ -621,9 +426,3 @@ if (!meta)

function error () {
var pr = chalk.bold.red
console.log(pr.apply(pr, arguments))
process.exit(-1)
}
function onselect (name) {
Adventure.prototype.printExercise = function printExercise (name) {
var exercise = this.loadExercise(name)

@@ -646,5 +445,3 @@ , afterPrepare

this.updateData('current', function () {
return exercise.meta.name
})
this.local.save('current', exercise.meta.name)

@@ -661,3 +458,3 @@ afterPreparation = function (err) {

else {
part = print.localisedFileStream(this.appName, this.appDir, path.resolve(__dirname, 'i18n/missing_problem/{lang}.md'), this.lang)
part = print.localisedFileStream(this.appName, this.appDir, path.resolve(__dirname, 'i18n/missing_problem/{lang}.md'), this.lang)
if (part)

@@ -699,7 +496,2 @@ stream.append(part)

Adventure.prototype.error = error
Adventure.prototype.print = print
module.exports = Adventure
module.exports = Adventure

@@ -5,2 +5,3 @@ const i18n = require('i18n-core')

, path = require('path')
, error = require('./lib/print').error
, fs = require('fs')

@@ -59,24 +60,5 @@

function chooseLang (globalDataDir, appDataDir, lang, defaultLang, availableLangs) {
var globalPath = path.resolve(globalDataDir, 'lang.json')
, appPath = path.resolve(appDataDir, 'lang.json')
, data
try {
// Lets see if we find some stored language in the app's config
data = require(appPath)
} catch (e) {
// Without a file an error will occur here, but thats okay
}
if (!data) {
// Lets see if some other workshopper stored language settings
try {
data = require(globalPath)
} catch (e) {
data = {}
// Without a file an error will occur here, but thats okay
}
}
function chooseLang (globalData, appData, defaultLang, availableLangs, lang) {
if (!!lang && typeof lang != 'string')
throw new TypeError('Please supply a language. Available languages are: ' + availableLangs.join(', '))
return error('Please supply a language. Available languages are: ' + availableLangs.join(', '))

@@ -87,7 +69,9 @@ if (lang)

if (availableLangs.indexOf(defaultLang) === -1)
throw new TypeError('The default language "' + defaultLang + ' is not one of the available languages?! Available languages are: ' + availableLangs.join(', '))
return error('The default language "' + defaultLang + ' is not one of the available languages?! Available languages are: ' + availableLangs.join(', '))
if (lang && availableLangs.indexOf(lang) === -1)
throw new TypeError('The language "' + lang + '" is not available.\nAvailable languages are ' + availableLangs.join(', ') + '.\n\nNote: the language is not case-sensitive ("en", "EN", "eN", "En" will become "en") and you can use "_" instead of "-" for seperators.')
return error('The language "' + lang + '" is not available.\nAvailable languages are ' + availableLangs.join(', ') + '.\n\nNote: the language is not case-sensitive ("en", "EN", "eN", "En" will become "en") and you can use "_" instead of "-" for seperators.')
var data = (appData.get('lang') || globalData.get('lang') || {})
if (availableLangs.indexOf(data.selected) === -1)

@@ -99,8 +83,5 @@ // The stored data is not available so lets use one of the other languages

try {
fs.writeFileSync(globalPath, JSON.stringify(data))
fs.writeFileSync(appPath, JSON.stringify(data))
} catch(e) {
// It is not good if an error occurs but it shouldn't really matter
}
globalData.save('lang', data)
appData.save('lang', data)
return data.selected

@@ -110,4 +91,3 @@ }

module.exports = {
chooseLang: chooseLang,
init: function(options, exercises, lang) {
init: function(options, exercises, globalData, appData, defaultLang) {
var generalTranslator = i18nChain(

@@ -122,2 +102,5 @@ i18nFs(path.resolve(__dirname, './i18n'))

)
, languages = options.languages || ['en']
, choose = chooseLang.bind(null, globalData, appData, defaultLang, languages)
, lang = choose(null)
, result = translator.lang(lang, true)

@@ -130,9 +113,12 @@ translator.fallback = function (key) {

}
result.languages = options.languages || ['en']
result.change = function (globalDataDir, appDataDir, lang, defaultLang, availableLangs) {
result.languages = languages
result.change = function (lang) {
lang = choose(lang)
result.changeLang(lang)
chooseLang(globalDataDir, appDataDir, lang, defaultLang, availableLangs)
}
result.lang = function () {
return lang
}
return result
}
}
{
"name": "workshopper-adventure",
"version": "3.4.2",
"version": "3.4.3",
"description": "A terminal workshop runner framework (adventure compatible)",
"main": "./index.js",
"author": "Rod Vagg <rod@vagg.org> (https://github.com/rvagg)",
"author": "Martin Heidegger <martin.heidegger@gmail.com> (https://github.com/martinheidegger)",
"repository": {

@@ -16,2 +16,3 @@ "type": "git",

"combined-stream": "0.0.7",
"commandico": "^1.0.0",
"i18n-core": "^1.3.2",

@@ -29,5 +30,5 @@ "map-async": "~0.1.1",

"bugs": {
"url": "https://github.com/rvagg/workshopper/issues"
"url": "https://github.com/workshopper/workshopper-adventure/issues"
},
"homepage": "https://github.com/rvagg/workshopper",
"homepage": "https://github.com/workshopper/workshopper-adventure",
"directories": {

@@ -34,0 +35,0 @@ "example": "examples"

@@ -1,22 +0,23 @@

# Workshopper
# Workshopper-Adventure
**A terminal workshop runner framework**
**A flexible terminal workshop runner framework**
[![NPM](https://nodei.co/npm/workshopper.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/workshopper/) [![NPM](https://nodei.co/npm-dl/workshopper.png?months=3&height=3)](https://nodei.co/npm/workshopper/)
[![NPM](https://nodei.co/npm/workshopper-adventure.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/workshopper-adventure/) [![NPM](https://nodei.co/npm-dl/workshopper-adventure.png?months=3&height=3)](https://nodei.co/npm/workshopper-adventure/)
![Learn You The Node.js For Much Win!](https://raw.github.com/rvagg/learnyounode/master/learnyounode.png)
**Workshopper** is used by **[learnyounode](https://github.com/rvagg/learnyounode)**, and other Node.js command-line workshop applications.
**Workshopper** was used by **[learnyounode](https://github.com/rvagg/learnyounode)**, and other Node.js command-line workshop applications.
*Documentation is being written for the v1 rewrite right now! Ping @rvagg if you need anything. **learnyounode** is now using this new version, for now you can use it to see how this works.
**Adventure** was used by **[javascripting](hhttps://github.com/sethvincent/javascripting), and other Node.js command-line workshop applications.
For now, [@linclark](https://github.com/linclark) has written a good introduction on creating your own workshop, available [here](http://lin-clark.com/blog/2014/07/01/authoring-nodejs-workshopper-lessons/).
**Workshopper-Adventure** allows you to create a workshop written
like either of those frameworks!
[@linclark](https://github.com/linclark) has written a good introduction on creating your own workshop, available [here](http://lin-clark.com/blog/2014/07/01/authoring-nodejs-workshopper-lessons/).
## High-level overview
Workshopper is essentially a *test-runner* with a fancy terminal UI. The Workshopper package itself is largely concerned with the menu system and some of the basic command-line parsing. Much of the work for executing the exercise validation is handled by [workshopper-exercise](http://github.com/rvagg/workshopper-exercise).
Workshopper-Adventure is essentially a *test-runner* with a fancy terminal UI. The Workshopper package itself is largely concerned with the menu system and some of the basic command-line parsing. Much of the work for executing the exercise validation is handled by [workshopper-exercise](http://github.com/rvagg/workshopper-exercise).
### Contributors

@@ -45,2 +46,3 @@

* [@martinheidegger](https://github.com/martinheidegger)
* [@rvagg](https://github.com/rvagg)

@@ -57,4 +59,8 @@ * [@substack](https://github.com/substack)

**Workshopper-Adventure** is Copyright (c) 2015 Martin Heidegger [@martinheidegger](https://github.com/martinheidegger) and licenced under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
it is originally a fork of **Workshopper**
**Workshopper** is Copyright (c) 2013-2015 Rod Vagg [@rvagg](https://twitter.com/rvagg) and licenced under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
**Workshopper** builds on the excellent work by [@substack](https://github.com/substack) and [@maxogden](https://github.com/maxogden) who created **[stream-adventure](https://github.com/substack/stream-adventure)** which serves as the original foundation for **Workshopper** and **learnyounode**. Portions of **Workshopper** may also be Copyright (c) 2013 [@substack](https://github.com/substack) and [@maxogden](https://github.com/maxogden) given that it builds on their original code.
**Workshopper-Adventure** builds on the excellent work by [@substack](https://github.com/substack) and [@maxogden](https://github.com/maxogden) who created **[stream-adventure](https://github.com/substack/stream-adventure)** which serves as the original foundation for **Workshopper** and **learnyounode**. Portions of **Workshopper** may also be Copyright (c) 2013 [@substack](https://github.com/substack) and [@maxogden](https://github.com/maxogden) given that it builds on their original code.
const path = require('path')
, fs = require('fs')
, mkdirp = require('mkdirp')
, vw = require('visualwidth')

@@ -26,9 +25,2 @@

function userDir () {
var folders = [process.env.HOME || process.env.USERPROFILE].concat(Array.prototype.slice.apply(arguments))
var dir = path.join.apply(path, folders)
mkdirp.sync(dir)
return dir
}
function getFsObject(type, file, base) {

@@ -57,3 +49,2 @@ var stat

, getFile: getFsObject.bind(null, 'file')
, userDir: userDir
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc