Skip to content

Commit ec4b3c1

Browse files
committed
feat: add doc generator
1 parent dc94daa commit ec4b3c1

File tree

61 files changed

+573
-133
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+573
-133
lines changed

.genrc.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"sections": [
3+
"10-Days-Of-Javascript",
4+
"Interview-Preparation-Kit",
5+
"Algorithms",
6+
"Data-Structures"
7+
]
8+
}

.templates/header.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Hackerrank-js
2+
Hackerrank Problem Solving with Javascript.

.templates/problems.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{{#each sections}}
2+
3+
## {{makeTitle title}}
4+
{{#each categories}}
5+
### {{title}}
6+
| Difficulty | Problem | Solution |
7+
| --- | --- | --- |
8+
{{#each problems}}
9+
| {{difficulty}} | [{{title}}]({{link}}) | [Solution]({{path}})|
10+
{{/each}}
11+
{{/each}}
12+
{{/each}}
13+

.templates/toc.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## Table of contents
2+
{{#each sections}}
3+
* [{{makeTitle title}}](#{{makeAnchor title}})
4+
{{/each}}

.tool/readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#

.tool/src/comparators.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const compareCategories = (categoryA, categoryB) => categoryA.title.localeCompare(categoryB.title)
2+
3+
const DIFFICULTIES = {
4+
Easy: 0,
5+
Medium: 1,
6+
Hard: 2,
7+
};
8+
const compareDifficulties = (difficultyA, difficultyB) => (
9+
DIFFICULTIES[difficultyA] - DIFFICULTIES[difficultyB]
10+
);
11+
12+
const compareTitles = (titleA, titleB) => (
13+
titleA.localeCompare(titleB)
14+
);
15+
16+
const compareProblems = (problemA, problemB) => {
17+
const difficultyDiff = compareDifficulties(problemA.difficulty, problemB.difficulty);
18+
if (difficultyDiff !== 0) {
19+
return difficultyDiff;
20+
}
21+
return compareTitles(problemA.title, problemB.title);
22+
};
23+
24+
module.exports = {
25+
compareCategories,
26+
compareProblems,
27+
};

.tool/src/index.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const parse = require('./parse');
2+
const {
3+
Config,
4+
HEADER_TEMPLATE_PATH,
5+
TOC_TEMPLATE_PATH,
6+
PROBLEMS_TEMPLATE_PATH
7+
} = require('./utils');
8+
const {
9+
compareCategories,
10+
compareProblems,
11+
} = require('./comparators');
12+
const template = require('./template');
13+
const fs = require('fs');
14+
const path = require('path');
15+
const sections = Config.getSections();
16+
const parsed = parse(sections);
17+
18+
parsed.sections.forEach(section => {
19+
section.categories.sort(compareCategories);
20+
section.categories.forEach(category => {
21+
category.problems.sort(compareProblems);
22+
});
23+
});
24+
25+
const templates = template([
26+
{path: HEADER_TEMPLATE_PATH, obj: null},
27+
{path: TOC_TEMPLATE_PATH, obj: parsed},
28+
{path: PROBLEMS_TEMPLATE_PATH, obj: parsed}
29+
]);
30+
31+
const readme = templates.reduce((md,cur) => {
32+
return md + cur;
33+
}, '');
34+
const readmePath = path.resolve('./README.md');
35+
const createREADME = (newReadme) => {
36+
if (fs.existsSync(readmePath)) {
37+
fs.unlinkSync(readmePath)
38+
}
39+
fs.writeFileSync(readmePath, newReadme);
40+
};
41+
createREADME(readme);
42+
43+

.tool/src/parse.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const path = require('path');
2+
const parseComment = require('comment-parser');
3+
const {
4+
readdirSync,
5+
readFileSync
6+
} = require('fs');
7+
const {
8+
isTag,
9+
getContentFromSource,
10+
getTitleFromPath,
11+
getGithubPath,
12+
isDir
13+
} = require('./utils');
14+
15+
const parseSolution = (solutionFile) => {
16+
const solutionSource = readFileSync(solutionFile, 'utf8');
17+
const parsedResult = Object.create(null);
18+
const parsed = parseComment(solutionSource);
19+
if (parsed.length <= 0) {
20+
return null;
21+
}
22+
const tags = parsed[0].tags;
23+
tags.forEach(({tag, source}) => {
24+
if (isTag(tag)) {
25+
parsedResult[tag] = getContentFromSource(tag, source);
26+
}
27+
});
28+
parsedResult.path = getGithubPath(solutionFile);
29+
return parsedResult;
30+
};
31+
32+
const parseCategory = (categoryDir) => {
33+
const parsedResult = {
34+
title: getTitleFromPath(categoryDir),
35+
problems: [],
36+
};
37+
const solutionFiles = readdirSync(categoryDir);
38+
39+
solutionFiles.forEach(solutionFile => {
40+
const result = parseSolution(path.join(categoryDir, solutionFile));
41+
if (result) {
42+
parsedResult.problems.push(result);
43+
}
44+
});
45+
return parsedResult;
46+
};
47+
48+
const parseSection = (sectionDir) => {
49+
const parsedResult = {
50+
title: getTitleFromPath(sectionDir),
51+
categories: [],
52+
};
53+
const categoryDirs = readdirSync(sectionDir);
54+
categoryDirs.forEach((categoryDir) => {
55+
if (isDir(path.join(sectionDir, categoryDir))) {
56+
const result = parseCategory(path.join(sectionDir, categoryDir));
57+
parsedResult.categories.push(result);
58+
}
59+
});
60+
return parsedResult;
61+
};
62+
63+
const parse = (sectionDirs) => {
64+
const parsedResult = {
65+
sections: [],
66+
};
67+
sectionDirs.forEach((sectionDir) => {
68+
if (isDir(sectionDir)) {
69+
const result = parseSection(path.resolve(sectionDir));
70+
parsedResult.sections.push(result);
71+
}
72+
});
73+
return parsedResult;
74+
};
75+
76+
module.exports = parse;

.tool/src/template.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const {existsSync, readFileSync} = require('fs');
2+
const handlebars = require('handlebars');
3+
const replaceAll = (str, search, replacement) => str.split(search).join(replacement);
4+
handlebars.registerHelper('makeTitle', (title) => replaceAll(title, '-', ' '));
5+
handlebars.registerHelper('makeAnchor', (title) => replaceAll(title, ' ', '-'));
6+
7+
const getTemplate = ({path, obj}) => {
8+
if (!existsSync(path)) {
9+
throw new Error(`File Not Found: ${path}`);
10+
}
11+
const templateSource = readFileSync(path, 'utf8');
12+
return handlebars.compile(templateSource)(obj);
13+
};
14+
15+
module.exports = (templatePairs) => (
16+
templatePairs
17+
.map((pair) => getTemplate(pair))
18+
);

.tool/src/utils.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const path = require('path');
2+
const fs = require('fs');
3+
4+
const TAG_TYPES = ['difficulty', 'link', 'title'];
5+
6+
const isTag = (tag) => TAG_TYPES.includes(tag);
7+
const getContentFromSource = (tag, source) => source.replace(`@${tag}`, '').trim();
8+
const getTitleFromPath = (filePath) => filePath.slice(filePath.lastIndexOf('/') + 1).trim();
9+
const getGithubPath = (filePath) => filePath.replace(path.resolve('./'), '.').trim();
10+
const isDir = (dir) => !(/\./g.test(dir)) && fs.lstatSync(dir).isDirectory();
11+
12+
const CONFIG_PATH = path.resolve('./.genrc.json');
13+
const HEADER_TEMPLATE_PATH = path.resolve('./.templates/header.md');
14+
const PROBLEMS_TEMPLATE_PATH = path.resolve('./.templates/problems.md');
15+
const TOC_TEMPLATE_PATH = path.resolve('./.templates/toc.md');
16+
17+
18+
const Config = (() => {
19+
const configFile = fs.readFileSync(CONFIG_PATH);
20+
const config = JSON.parse(configFile);
21+
return {
22+
getSections: () => config.sections
23+
};
24+
})();
25+
26+
27+
module.exports = {
28+
isTag,
29+
getContentFromSource,
30+
getTitleFromPath,
31+
Config,
32+
getGithubPath,
33+
HEADER_TEMPLATE_PATH,
34+
PROBLEMS_TEMPLATE_PATH,
35+
TOC_TEMPLATE_PATH,
36+
isDir
37+
};

10DaysOfJavascript/Day0/data-types.js 10-Days-Of-Javascript/Day0/data-types.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-data-types/problem
1+
/**
2+
* @title Data Types
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-data-types/problem
5+
*/
26

37
const performOperation = (secondInteger, secondDecimal, secondString) => {
48
const firstInteger = 4;
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @title Hello, World!
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-hello-world/problem
5+
*/
6+
7+
const greeting = parameterVariable => {
8+
console.log('Hello, World!');
9+
console.log(parameterVariable);
10+
};
11+

10DaysOfJavascript/Day1/arithmetic-oprators.js 10-Days-Of-Javascript/Day1/arithmetic-oprators.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-arithmetic-operators/problem
1+
/**
2+
* @title Arithmetic Operators
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-arithmetic-operators/problem
5+
*/
26

37
const getArea = (length, width) => {
48
const area = length * width;
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @title Functions
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-function/problem
5+
*/
6+
7+
const factorial = n => {
8+
let ret = 1;
9+
for (let i = 1; i <= n; i++) {
10+
ret *= i;
11+
}
12+
13+
return ret;
14+
};

10DaysOfJavascript/Day1/let-and-const.js 10-Days-Of-Javascript/Day1/let-and-const.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
// https://www.hackerrank.com/challenges/js10-let-and-const/problem
1+
/**
2+
* @title Let and Const
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-let-and-const/problem
5+
*/
6+
27
/* global readLine b:writable */
38
/* eslint-disable no-const-assign */
49

10DaysOfJavascript/Day2/conditional-statements-if-else.js 10-Days-Of-Javascript/Day2/conditional-statements-if-else.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-if-else/problem
1+
/**
2+
* @title Conditional Statements: If-Else
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-if-else/problem
5+
*/
26

37
const getGrade = score => {
48
let grade;

10DaysOfJavascript/Day2/conditional-statements-switch.js 10-Days-Of-Javascript/Day2/conditional-statements-switch.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-switch/problem
1+
/**
2+
* @title Conditional Statements: Switch
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-switch/problem
5+
*/
26

37
const isGroupA = firstLetter => /^a|e|i|o|u/.test(firstLetter);
48

10DaysOfJavascript/Day2/loops.js 10-Days-Of-Javascript/Day2/loops.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-loops/problem
1+
/**
2+
* @title Loops
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-loops/problem
5+
*/
26

37
const isVowel = letter => /^a|e|i|o|u/.test(letter);
48
const isConsonant = letter => !isVowel(letter);

10DaysOfJavascript/Day3/arrays.js 10-Days-Of-Javascript/Day3/arrays.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-arrays/problem
1+
/**
2+
* @title Arrays
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-arrays/problem
5+
*/
26

37
const compareNumber = (a, b) => b - a;
48

10DaysOfJavascript/Day3/throw.js 10-Days-Of-Javascript/Day3/throw.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-throw/problem
1+
/**
2+
* @title Throw
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-throw/problem
5+
*/
26

37
const isPositive = num => {
48
if (num > 0) {

10DaysOfJavascript/Day3/try-catch-and-finally.js 10-Days-Of-Javascript/Day3/try-catch-and-finally.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-try-catch-and-finally/problem
1+
/**
2+
* @title Try, Catch, and Finally
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-try-catch-and-finally/problem
5+
*/
26

37
const reverseString = s => {
48
try {

10DaysOfJavascript/Day4/create-a-rectangle-object.js 10-Days-Of-Javascript/Day4/create-a-rectangle-object.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/js10-objects/problem
1+
/**
2+
* @title Create a Rectangle Object
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/js10-objects/problem
5+
*/
26

37
function Rectangle(length, width) {
48
this.length = length;

10DaysOfJavascript/Day0/hello-world.js

-7
This file was deleted.

10DaysOfJavascript/Day1/functions.js

-11
This file was deleted.

ProblemSolving/Sorting/big-sorting.js Algorithms/Sorting/big-sorting.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// https://www.hackerrank.com/challenges/big-sorting/problem
1+
/**
2+
* @title Big Sorting
3+
* @difficulty Easy
4+
* @link https://www.hackerrank.com/challenges/big-sorting/problem
5+
*/
26

37
const bigNumCompareFunc = (numStrA, numStrB) => {
48
const {length: strLengthA} = numStrA;

0 commit comments

Comments
 (0)