Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Feature/tests#4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ShMcK merged 2 commits intomasterfromfeature/tests
May 30, 2020
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletionpackage.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,13 @@
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node"
"verbose": true,
"testPathIgnorePatterns": [
"build"
],
"moduleFileExtensions": [
"js",
"ts"
]
}
}
100 changes: 4 additions & 96 deletionssrc/build.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,84 +3,14 @@ import * as path from "path";
import * as _ from "lodash";
import * as fs from "fs";
import * as T from "../typings/tutorial";
import { parse } from "./utils/parse";
// import validate from './validator';

// import not working
const simpleGit = require("simple-git/promise");

const workingDir = "tmp";

type TutorialContent = {};

function parseContent(md: string): TutorialContent {
let start: number = -1;
const parts: any[] = [];

const lines = md.split("\n");

// Split the multiple parts - This way enables the creator to use 4/5 level headers inside the content.
lines.forEach((line, index) => {
if (line.match(/#{1,3}\s/) || index === lines.length - 1) {
if (start !== -1) {
parts.push(lines.slice(start, index).join("\n"));
start = index;
} else {
start = index;
}
}
});

const sections = {};

// Identify and remove the header
const summaryMatch = parts
.shift()
.match(/^#\s(?<tutorialTitle>.*)[\n\r]+(?<tutorialDescription>[^]*)/);

sections["summary"] = {
title: summaryMatch.groups.tutorialTitle.trim(),
description: summaryMatch.groups.tutorialDescription.trim(),
};

// Identify each part of the content
parts.forEach((section) => {
const levelRegex = /^(##\s(?<levelId>L\d+)\s(?<levelTitle>.*)[\n\r]*(>\s*(?<levelSummary>.*))?[\n\r]+(?<levelContent>[^]*))/;
const stepRegex = /^(###\s(?<stepId>(?<levelId>L\d+)S\d+)\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/;

const levelMatch = section.match(levelRegex);
const stepMatch = section.match(stepRegex);

if (levelMatch) {
const level = {
[levelMatch.groups.levelId]: {
id: levelMatch.groups.levelId,
title: levelMatch.groups.levelTitle,
summary: levelMatch.groups.levelSummary.trim(),
content: levelMatch.groups.levelContent.trim(),
},
};

_.merge(sections, level);
} else if (stepMatch) {
const step = {
[stepMatch.groups.levelId]: {
steps: {
[stepMatch.groups.stepId]: {
id: stepMatch.groups.stepId,
// title: stepMatch.groups.stepTitle, //Not using at this momemnt
content: stepMatch.groups.stepContent.trim(),
},
},
},
};

_.merge(sections, step);
}
});

return sections;
}

function rmDir(dir: string, rmSelf = false) {
try {
let files;
Expand DownExpand Up@@ -164,32 +94,10 @@ async function build({ repo, codeBranch, setupBranch, isLocal }: BuildOptions) {
await git.checkout(setupBranch);

// Load files
const _mdContent = fs.readFileSync(
path.join(localPath, "TUTORIAL.md"),
"utf8"
);
let _tutorial = fs.readFileSync(
path.join(localPath, "coderoad.yaml"),
"utf8"
);

// Add one more line to the content as per Shawn's request
const mdContent: any = parseContent(_mdContent);

// Parse tutorial to JSON
const tutorial: T.Tutorial = yamlParser.load(_tutorial);

// Add the summary to the tutorial file
tutorial.summary = mdContent.summary;

// merge content and tutorial
tutorial.levels.forEach((level: T.Level) => {
const { steps, ...content } = mdContent[level.id];

level.steps.forEach((step: T.Step) => _.merge(step, steps[step.id]));
const _content = fs.readFileSync(path.join(localPath, "TUTORIAL.md"), "utf8");
let _config = fs.readFileSync(path.join(localPath, "coderoad.yaml"), "utf8");

_.merge(level, content);
});
const tutorial = parse(_content, _config);

// Checkout the code branches
await git.checkout(codeBranch);
Expand Down
40 changes: 17 additions & 23 deletionssrc/templates/coderoad.yaml
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,7 @@
# This is a YAML-formatted file.
## Your personal version of the tutorial
##
version: '0.1.0'
## Data used to populate the tutorial summary page
##
summary:
## The title of your tutorial. Required.
##
title: ''
## A description of your tutorial. Required.
##
description: ''
version: "0.1.0"
## Data used to configure and setup the tutorial
##
config:
Expand All@@ -32,28 +23,31 @@ config:
setup:
## A list of commits to load to setup the tutorial
commits: []
# - commit1
# - commit2
# - commit1
# - commit2
## A list of commands to run to configure the tutorial
commands: []
commands:
[]
# - npm install
## App versions helps to ensure compatability with the Extension
appVersions: {}
appVersions:
{}
## Ensure compatability with a minimal VSCode CodeRoad version
# vscode: '>=0.7.0'
## Repo information to load code from
##
repo:
## The uri path to the repo containing the code commits. Required.
##
uri:''
uri:""
## The branch on the repo uri that contains the code commits. Required.
branch:''
branch:""

## A list of tutorial dependencies to ensure the environment is setup for the tutorial. Optional.
## The dependencies will be checked by running `dependency.name` --version and comparing it to the version provided.
##
dependencies: []
dependencies:
[]
## The name of the dependency
# - name: node
# ## The version requirement. See https://github.com/npm/node-semver for options.
Expand All@@ -69,16 +63,17 @@ levels:
setup:
## Files to open in a text editor when the task loads. Optional.
files: []
# - package.json
# - package.json
## Commits to load when the task loads. These should include failing tests. Required.
## The list will be filled by the parser
commits: []
commits:
[]
# - a commit hash
## Solution for the first task. Required.
solution:
## Files to open when the solution loads. Optional.
files: []
# - package.json
# - package.json
## Commits that complete the task. All tests should pass when the commits load. These commits will not be loaded by the tutorial user in normal tutorial activity.
## The list will be filled by the parser
commits: []
Expand DownExpand Up@@ -117,10 +112,9 @@ levels:
- commit8
commands:
## A filter is a regex that limits the test results
- filter:'^Example 2'
- filter:"^Example 2"
## A feature that shows subtasks: all filtered active test names and the status of the tests (pass/fail).
- subtasks: true
solution:
commits:
- commit9

114 changes: 114 additions & 0 deletionssrc/utils/parse.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
import * as yamlParser from "js-yaml";
import * as _ from "lodash";
import * as T from "../../typings/tutorial";

type TutorialFrame = {
summary: T.TutorialSummary;
};

export function parseMdContent(md: string): TutorialFrame | never {
let start: number = -1;
const parts: any[] = [];

const lines = md.split("\n");

// Split the multiple parts - This way enables the creator to use 4/5 level headers inside the content.
lines.forEach((line, index) => {
if (line.match(/#{1,3}\s/) || index === lines.length - 1) {
if (start !== -1) {
parts.push(lines.slice(start, index).join("\n"));
start = index;
} else {
start = index;
}
}
});

const sections = {};

// Identify and remove the header
const summaryMatch = parts
.shift()
.match(/^#\s(?<tutorialTitle>.*)[\n\r]+(?<tutorialDescription>[^]*)/);

if (!summaryMatch.groups.tutorialTitle) {
throw new Error("Missing tutorial title");
}

if (!summaryMatch.groups.tutorialDescription) {
throw new Error("Missing tutorial summary description");
}

sections["summary"] = {
title: summaryMatch.groups.tutorialTitle.trim(),
description: summaryMatch.groups.tutorialDescription.trim(),
};

// Identify each part of the content
parts.forEach((section) => {
const levelRegex = /^(##\s(?<levelId>L\d+)\s(?<levelTitle>.*)[\n\r]*(>\s*(?<levelSummary>.*))?[\n\r]+(?<levelContent>[^]*))/;
const stepRegex = /^(###\s(?<stepId>(?<levelId>L\d+)S\d+)\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/;

const levelMatch = section.match(levelRegex);
const stepMatch = section.match(stepRegex);

if (levelMatch) {
const level = {
[levelMatch.groups.levelId]: {
id: levelMatch.groups.levelId,
title: levelMatch.groups.levelTitle,
summary: levelMatch.groups.levelSummary.trim(),
content: levelMatch.groups.levelContent.trim(),
},
};

_.merge(sections, level);
} else if (stepMatch) {
const step = {
[stepMatch.groups.levelId]: {
steps: {
[stepMatch.groups.stepId]: {
id: stepMatch.groups.stepId,
// title: stepMatch.groups.stepTitle, //Not using at this momemnt
content: stepMatch.groups.stepContent.trim(),
},
},
},
};

_.merge(sections, step);
}
});

// @ts-ignore
return sections;
}

export function parse(_content: string, _config: string): T.Tutorial {
const mdContent: TutorialFrame = parseMdContent(_content);
// Parse tutorial to JSON
const tutorial: T.Tutorial = yamlParser.load(_config);

// Add the summary to the tutorial file
tutorial["summary"] = mdContent.summary;

// merge content and tutorial
if (tutorial.levels) {
tutorial.levels.forEach((level: T.Level) => {
const levelContent = mdContent[level.id];
if (!levelContent) {
console.log(`Markdown content not found for ${level.id}`);
return;
}
const { steps, ...content } = levelContent;

if (steps) {
steps.forEach((step: T.Step) => _.merge(step, steps[step.id]));
}

_.merge(level, content);
});
}

return tutorial;
}
52 changes: 52 additions & 0 deletionstests/parse.test.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
import { parse } from "../src/utils/parse";

describe("parse", () => {
it("should parse summary", () => {
const md = `# Insert Tutorial's Title here

Short description to be shown as a tutorial's subtitle.

`;

const yaml = `version: "0.1.0"`;
const result = parse(md, yaml);
const expected = {
summary: {
description: "Short description to be shown as a tutorial's subtitle.",
title: "Insert Tutorial's Title here",
},
};
expect(result.summary).toEqual(expected.summary);
});

it("should parse a level with a summary", () => {
const md = `# Title

Description.

## L1 Put Level's title here

> Level's summary: a short description of the level's content in one line.

Some text
`;

const yaml = `version: "0.1.0"
levels:
- id: L1
`;
const result = parse(md, yaml);
const expected = {
levels: [
{
id: "L1",
title: "Put Level's title here",
summary:
"Level's summary: a short description of the level's content in one line.",
content: "Some text",
},
],
};
expect(result.levels).toEqual(expected.levels);
});
});
Loading

[8]ページ先頭

©2009-2025 Movatter.jp