diff --git a/package-lock.json b/package-lock.json index 024fce8..b586ddd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@coderoad/cli", - "version": "0.1.1", + "version": "0.1.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b49f273..8162fa1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@coderoad/cli", - "version": "0.1.1", + "version": "0.1.2", "description": "A CLI to build the configuration file for Coderoad Tutorials", "keywords": [ "coderoad", diff --git a/src/build.ts b/src/build.ts index 016b64f..fc341d2 100644 --- a/src/build.ts +++ b/src/build.ts @@ -25,31 +25,28 @@ type BuildArgs = { output: string; }; -const parseArgs = (args: string[]): BuildArgs => { - // default . - const dir = args[0] || "."; - - // -m --markdown - default TUTORIAL.md - const markdown = - getArg(args, { name: "markdown", alias: "m" }) || "TUTORIAL.md"; - // -y --yaml - default coderoad-config.yml - const yaml = getArg(args, { name: "yaml", alias: "y" }) || "coderoad.yaml"; - // -o --output - default coderoad.json - const output = - getArg(args, { name: "output", alias: "o" }) || "tutorial.json"; - - return { - dir, - output, - markdown, - yaml, - }; -}; - async function build(args: string[]) { let options: BuildArgs; try { - options = parseArgs(args); + // default . + const dir = args[0].match(/^-/) ? "." : args[0]; + // -m --markdown - default TUTORIAL.md + const markdown = + getArg(args, { name: "markdown", alias: "m" }) || "TUTORIAL.md"; + // -y --yaml - default coderoad-config.yml + const yaml = getArg(args, { name: "yaml", alias: "y" }) || "coderoad.yaml"; + // -o --output - default coderoad.json + const output = + getArg(args, { name: "output", alias: "o" }) || "tutorial.json"; + + console.log(`Building CodeRoad ${output}...`); + + options = { + dir, + output, + markdown, + yaml, + }; } catch (e) { console.error("Error parsing build logs"); console.error(e.message); diff --git a/src/cli.ts b/src/cli.ts index 3371d0c..d71a956 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -19,7 +19,7 @@ export async function cli(rawArgs: string[]): Promise { break; case "create": - create(process.cwd()); + create(args); break; case "--help": diff --git a/src/create.ts b/src/create.ts index 27a082a..5840b10 100644 --- a/src/create.ts +++ b/src/create.ts @@ -1,24 +1,75 @@ import ncp from "ncp"; import * as path from "path"; import { promisify } from "util"; +import { getArg } from "./utils/args"; const copy = promisify(ncp); -const copyFiles = async (filePath: string): Promise => { +type CreateArgs = { + dir: string; + lang: string; + testRunner: string; +}; + +async function create(args: string[]): Promise { + let options: CreateArgs; + + // default . + const dir = !args.length || args[0].match(/^-/) ? "." : args[0]; + const lang = getArg(args, { name: "lang", alias: "l" }) || "js"; + const testRunner = + getArg(args, { name: "testRunner", alias: "t" }) || "mocha"; + + // validate lang + if (!["js"].includes(lang)) { + throw new Error(`Language ${lang} not supported yet in create`); + } + + // validate test runner + if (!["mocha"].includes(testRunner)) { + throw new Error(`Test Runner ${testRunner} not supported yet in create`); + } + + console.info(`Creating CodeRoad project for ${lang} ${testRunner}`); + + options = { + dir, + lang, + testRunner, + }; + + const localPath = path.join(process.cwd(), options.dir); + + // TODO: git init ? + + // copy tutorial file + const pathToSrc = path.join(__dirname, "..", "src"); + const templateDirectory = path.resolve(pathToSrc, "templates"); + + const markdownPath = path.join(templateDirectory, "TUTORIAL.md"); + const targetMarkdownPath = path.join(localPath, "TUTORIAL.md"); try { - const pathToSrc = path.join(__dirname, "..", "src"); - const templateDirectory = path.resolve(pathToSrc, "templates"); - const targetDirectory = process.cwd(); + await copy(markdownPath, targetMarkdownPath, { + clobber: false, + }); + } catch (e) { + console.error("Error on creating markdown file"); + console.error(e.message); + } - await copy(templateDirectory, targetDirectory, { + // TODO: copy master yaml + const pathToYaml = path.join(templateDirectory, `${lang}-${testRunner}`); + const targetYamlPath = path.join(localPath, "coderoad.yaml"); + try { + await copy(pathToYaml, targetYamlPath, { clobber: false, }); } catch (e) { - console.log("Error on creating the files:"); - console.log(JSON.stringify(e, null, 1)); + console.error("Error on creating yaml file"); + console.error(e.message); } -}; -const create = copyFiles; + // TODO: copy code files with commits +} export default create; diff --git a/src/utils/schema/index.ts b/src/schema/index.ts similarity index 100% rename from src/utils/schema/index.ts rename to src/schema/index.ts diff --git a/src/utils/schema/meta.ts b/src/schema/meta.ts similarity index 100% rename from src/utils/schema/meta.ts rename to src/schema/meta.ts diff --git a/src/templates/TUTORIAL.md b/src/templates/TUTORIAL.md index 23452a2..f9b3d04 100644 --- a/src/templates/TUTORIAL.md +++ b/src/templates/TUTORIAL.md @@ -2,39 +2,37 @@ Short description to be shown as a tutorial's subtitle - ## L1 Put Level's title here > Level's summary: a short description of the level's content in one line. -The level is identified and distributed following the regex: +The level is identified and distributed following the regex: ```js -/^(##\s(?L\d+)\s(?.*)\n*(>\s*(?.*))?\n+(?[^]*))/ +/^(##\s(?L\d+)\s(?.*)\n*(>\s*(?.*))?\n+(?[^]*))/; ``` The Level can be split into steps or have no steps. Levels without steps are meant to be used as only informative content, for example: use a Level without steps at the end of the tutorial to congratulate the student and provide some additional related resources. -Tutorial's content. It can span through multiple paragraphs and use headers `####` and `#####`. +Tutorial's content. It can span through multiple paragraphs and use headers `####` and `#####`. Steps are identified and their content described using the following regex: ```js -/^(###\s(?(?L\d+)S\d+)\s(?.*)\n+(?[^]*))/ +/^(###\s(?(?L\d+)S\d+)\s(?.*)\n+(?[^]*))/; ``` The numbers identifying the levels and steps are irrelevant but keep in mind that they will be executed in order. A level with id `10` will be executed before another one with id `20` and so on. These `ids` should have a match in the configuration file (`coderoad.yaml`). - ### L1S1 A step title (not being shown on the extension at this moment) Short description of the step's purpose. Should be short and fit in one line **Important** + 1. Both level and step ids must have an entry with the same id on the configuration file; 2. Step Ids are based on its level id. Any step from level `L234` must start with `L234S`, followed by the sequential digits. - ### L1S2 Another step -Step's short description. \ No newline at end of file +Step's short description. diff --git a/src/templates/coderoad.yaml b/src/templates/js-mocha/coderoad.yaml similarity index 97% rename from src/templates/coderoad.yaml rename to src/templates/js-mocha/coderoad.yaml index 01c32f6..dbe78b1 100644 --- a/src/templates/coderoad.yaml +++ b/src/templates/js-mocha/coderoad.yaml @@ -21,8 +21,6 @@ config: ## Commits to load to setup the test runner. Optional. ## setup: - ## A list of commits to load to setup the tutorial - commits: [] # - commit1 # - commit2 ## A list of commands to run to configure the tutorial diff --git a/src/utils/validate.ts b/src/utils/validate.ts index 6ae0d09..a7ec4fc 100644 --- a/src/utils/validate.ts +++ b/src/utils/validate.ts @@ -1,4 +1,4 @@ -import schema from "./schema"; +import schema from "../schema"; // https://www.npmjs.com/package/ajv // @ts-ignore ajv typings not working