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

Commit3c214e7

Browse files
authored
Merge pull requestcoderoad#57 from coderoad/feature/subtasks
Feature/subtasks
2 parents71e9c79 +859d8e5 commit3c214e7

File tree

3 files changed

+115
-31
lines changed

3 files changed

+115
-31
lines changed

‎src/utils/parse.ts

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ type TutorialFrame = {
77
levels:T.Level[];
88
};
99

10+
constR={
11+
summary:/^#\s(?<tutorialTitle>.*)[\n\r]+(?<tutorialDescription>[^]*)/,
12+
level:/^(#{2}\s(?<levelId>L?\d+\.?)\s(?<levelTitle>.*)[\n\r]*(>\s(?<levelSummary>.*))?[\n\r]+(?<levelContent>[^]*))/,
13+
step:/^(#{3}\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/,
14+
hints:/^(#{4}\sHINTS[\n\r]+([\*|\-]\s(?<hintContent>[^]*))[\n\r]+)+/,
15+
subtasks:/^(#{4}\sSUBTASKS[\n\r]+([\*|\-]\s(?<subtaskContent>[^]*))[\n\r]+)+/,
16+
listItem:/[\n\r]+[\*|\-]\s/,
17+
};
18+
1019
exportfunctionparseMdContent(md:string):TutorialFrame|never{
1120
letstart:number=-1;
1221
constparts:any[]=[];
@@ -34,9 +43,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
3443
};
3544

3645
// Capture summary
37-
constsummaryMatch=parts
38-
.shift()
39-
.match(/^#\s(?<tutorialTitle>.*)[\n\r]+(?<tutorialDescription>[^]*)/);
46+
constsummaryMatch=parts.shift().match(R.summary);
4047
if(summaryMatch.groups.tutorialTitle){
4148
mdContent.summary.title=summaryMatch.groups.tutorialTitle.trim();
4249
}
@@ -49,8 +56,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
4956
// Identify each part of the content
5057
parts.forEach((section:string)=>{
5158
// match level
52-
constlevelRegex=/^(#{2}\s(?<levelId>L?\d+\.?)\s(?<levelTitle>.*)[\n\r]*(>\s(?<levelSummary>.*))?[\n\r]+(?<levelContent>[^]*))/;
53-
constlevelMatch:RegExpMatchArray|null=section.match(levelRegex);
59+
constlevelMatch:RegExpMatchArray|null=section.match(R.level);
5460

5561
if(levelMatch&&levelMatch.groups){
5662
constlevelId=levelMatch.groups.levelId.replace(".","");
@@ -77,8 +83,7 @@ export function parseMdContent(md: string): TutorialFrame | never {
7783
};
7884
}else{
7985
// match step
80-
conststepRegex=/^(#{3}\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/;
81-
conststepMatch:RegExpMatchArray|null=section.match(stepRegex);
86+
conststepMatch:RegExpMatchArray|null=section.match(R.step);
8287
if(stepMatch&&stepMatch.groups){
8388
current={
8489
levelId:current.levelId,
@@ -91,20 +96,36 @@ export function parseMdContent(md: string): TutorialFrame | never {
9196
content:stepContent.trim(),
9297
};
9398
}else{
94-
// parse hints from stepContent
95-
consthintDetectRegex=/^(#{4}\sHINTS[\n\r]+([\*|\-]\s(?<hintContent>[^]*))[\n\r]+)+/;
96-
consthintMatch=section.match(hintDetectRegex);
97-
if(!!hintMatch){
98-
consthintItemRegex=/[\n\r]+[\*|\-]\s/;
99-
consthints=section
100-
.split(hintItemRegex)
101-
.slice(1)// remove #### HINTS
102-
.map((h)=>h.trim());
103-
if(hints.length){
104-
mdContent.levels[current.levelIndex].steps[
105-
current.stepIndex
106-
].hints=hints;
107-
}
99+
consthintMatch=section.match(R.hints);
100+
constsubtaskMatch=section.match(R.subtasks);
101+
102+
switch(true){
103+
// parse hints from stepContent
104+
case!!hintMatch:
105+
consthints=section
106+
.split(R.listItem)
107+
.slice(1)// remove #### HINTS
108+
.map((h)=>h.trim());
109+
if(hints.length){
110+
mdContent.levels[current.levelIndex].steps[
111+
current.stepIndex
112+
].hints=hints;
113+
}
114+
return;
115+
// parse subtasks from stepContent
116+
case!!subtaskMatch:
117+
constsubtasks=section
118+
.split(R.listItem)
119+
.slice(1)// remove #### SUBTASKS
120+
.map((h)=>h.trim());
121+
if(subtasks.length){
122+
mdContent.levels[current.levelIndex].steps[
123+
current.stepIndex
124+
].subtasks=subtasks;
125+
}
126+
return;
127+
default:
128+
console.warn(`No build parser match found for:\n${section}\n`);
108129
}
109130
}
110131
}

‎tests/parse.test.ts

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,6 @@ The first step
541541
files:["someFile.js"],
542542
watchers:["someFile.js"],
543543
filter:"someFilter",
544-
subtasks:true,
545544
},
546545
solution:{
547546
commands:["npm install"],
@@ -579,7 +578,6 @@ The first step
579578
files:["someFile.js"],
580579
watchers:["someFile.js"],
581580
filter:"someFilter",
582-
subtasks:true,
583581
},
584582
solution:{
585583
commits:["1gfedcba","987654321"],
@@ -631,7 +629,6 @@ The third step
631629
files:["someFile.js"],
632630
watchers:["someFile.js"],
633631
filter:"someFilter",
634-
subtasks:true,
635632
},
636633
solution:{
637634
commands:["npm install"],
@@ -645,7 +642,6 @@ The third step
645642
files:["someFile.js"],
646643
watchers:["someFile.js"],
647644
filter:"someFilter",
648-
subtasks:true,
649645
},
650646
solution:{
651647
commands:["npm install"],
@@ -666,7 +662,6 @@ The third step
666662
files:["someFile.js"],
667663
watchers:["someFile.js"],
668664
filter:"someFilter",
669-
subtasks:true,
670665
},
671666
solution:{
672667
commands:["npm install"],
@@ -709,7 +704,6 @@ The third step
709704
files:["someFile.js"],
710705
watchers:["someFile.js"],
711706
filter:"someFilter",
712-
subtasks:true,
713707
},
714708
solution:{
715709
commits:["1fedcba","987654321"],
@@ -726,7 +720,6 @@ The third step
726720
files:["someFile.js"],
727721
watchers:["someFile.js"],
728722
filter:"someFilter",
729-
subtasks:true,
730723
},
731724
solution:{
732725
commits:["3abcdef"],
@@ -751,7 +744,6 @@ The third step
751744
files:["someFile.js"],
752745
watchers:["someFile.js"],
753746
filter:"someFilter",
754-
subtasks:true,
755747
},
756748
solution:{
757749
commits:["5abcdef"],
@@ -1419,4 +1411,75 @@ The second uninterrupted step
14191411
expect(result.levels[0]).toEqual(expected.levels[0]);
14201412
});
14211413
});
1414+
describe("subtasks",()=>{
1415+
it("should parse subtasks",()=>{
1416+
constmd=`# Subtask Demo
1417+
1418+
A demo demonstrating how to use subtasks
1419+
1420+
## 1. Subtask Example
1421+
1422+
A subtask example
1423+
1424+
### 1.1
1425+
1426+
Create a function \`add\` that can take a variety of params.
1427+
1428+
#### SUBTASKS
1429+
1430+
- Add one number
1431+
- Add two numbers
1432+
- Add three numbers
1433+
`;
1434+
constskeleton={
1435+
levels:[
1436+
{
1437+
id:"1",
1438+
steps:[
1439+
{
1440+
id:"1.1",
1441+
},
1442+
],
1443+
},
1444+
],
1445+
};
1446+
constexpected={
1447+
levels:[
1448+
{
1449+
id:"1",
1450+
title:"Subtask Example",
1451+
summary:"A subtask example",
1452+
content:"A subtask example",
1453+
steps:[
1454+
{
1455+
id:"1.1",
1456+
setup:{
1457+
commits:["abcdef1"],
1458+
},
1459+
content:
1460+
"Create a function `add` that can take a variety of params.",
1461+
solution:{
1462+
commits:["abcdef2"],
1463+
},
1464+
subtasks:[
1465+
"Add one number",
1466+
"Add two numbers",
1467+
"Add three numbers",
1468+
],
1469+
},
1470+
],
1471+
},
1472+
],
1473+
};
1474+
constresult=parse({
1475+
text:md,
1476+
skeleton,
1477+
commits:{
1478+
"1.1:T":["abcdef1"],
1479+
"1.1:S":["abcdef2"],
1480+
},
1481+
});
1482+
expect(result.levels[0]).toEqual(expected.levels[0]);
1483+
});
1484+
});
14221485
});

‎typings/tutorial.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export type Step = {
2727
content:string;
2828
setup?:StepActions;
2929
solution?:Maybe<StepActions>;
30-
subtasks?:{[testName:string]:boolean};
30+
subtasks?:string[];
3131
hints?:string[];
3232
};
3333

@@ -52,7 +52,7 @@ export type StepActions = {
5252
files?:string[];
5353
watchers?:string[];
5454
filter?:string;
55-
subtasks?:boolean;
55+
subtasks?:string[];
5656
};
5757

5858
exportinterfaceTestRunnerArgs{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp