jee-default 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ slides_dir="${1:-notes}"
5
+ output_file="${2:-illustration.md}"
6
+ pattern="${3:-*question.png}"
7
+
8
+ if [ "$slides_dir" = "-h" ] || [ "$slides_dir" = "--help" ]; then
9
+ cat <<'EOF'
10
+ Usage: ./generate-question-illustration.sh [slides-dir] [output-file] [pattern]
11
+
12
+ slides-dir Directory to scan recursively for question images.
13
+ output-file Markdown file to generate (default: illustration.md).
14
+ pattern Filename pattern to match question images (default: '*question.png').
15
+
16
+ Example:
17
+ ./generate-question-illustration.sh notes/typeOfChargesAndTheirProperties illustration.md
18
+ ./generate-question-illustration.sh notes illustration.md '*question.png'
19
+ EOF
20
+ exit 0
21
+ fi
22
+
23
+ if [ ! -d "$slides_dir" ]; then
24
+ echo "Error: slides directory not found: $slides_dir" >&2
25
+ exit 1
26
+ fi
27
+
28
+ if ! command -v node >/dev/null 2>&1; then
29
+ echo "Error: Node.js is required. Install Node.js to continue." >&2
30
+ exit 1
31
+ fi
32
+
33
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
34
+ node "$SCRIPT_DIR/question-illustration.js" "$slides_dir" "$output_file" "$pattern"
35
+ exit $?
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ source_dir="${1:-questoinPractices}"
5
+ output_file="${2:-questionSheet.md}"
6
+ pattern="${3:-*.png}"
7
+
8
+ if [ "$source_dir" = "-h" ] || [ "$source_dir" = "--help" ]; then
9
+ cat <<'EOF'
10
+ Usage: ./generate-question-practice-sheet.sh [source-dir] [output-file] [pattern]
11
+
12
+ source-dir Directory containing practice question images.
13
+ output-file Markdown file to write (default: questionSheet.md).
14
+ pattern Filename glob to match images (default: '*.png').
15
+
16
+ Example:
17
+ ./generate-question-practice-sheet.sh questoinPractices questionSheet.md
18
+ ./generate-question-practice-sheet.sh questoinPractices questionSheet.md 'slide*question.png'
19
+ EOF
20
+ exit 0
21
+ fi
22
+
23
+ if [ ! -d "$source_dir" ]; then
24
+ echo "Error: source directory not found: $source_dir" >&2
25
+ exit 1
26
+ fi
27
+
28
+ if ! command -v node >/dev/null 2>&1; then
29
+ echo "Error: Node.js is required. Install Node.js to continue." >&2
30
+ exit 1
31
+ fi
32
+
33
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
34
+ node "$SCRIPT_DIR/question-practice-sheet.js" "$source_dir" "$output_file" "$pattern"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jee-default",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Generate DSA question practice sheets instantly",
5
5
  "main": "./bin/cli.js",
6
6
  "bin": {
@@ -8,6 +8,11 @@
8
8
  },
9
9
  "files": [
10
10
  "bin/",
11
+ "generate-question-illustration.sh",
12
+ "generate-question-practice-sheet.sh",
13
+ "pdf-to-slides.sh",
14
+ "question-illustration.js",
15
+ "question-practice-sheet.js",
11
16
  "questionPractices/"
12
17
  ],
13
18
  "keywords": [
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ pdf_source="${1:-source.pdf}"
5
+ out_dir="${2:-notes}"
6
+ pages="${3:-all}"
7
+
8
+ tmp_dir=$(mktemp -d)
9
+ trap 'rm -rf "$tmp_dir"' EXIT
10
+
11
+ if [[ "$pdf_source" =~ ^https?:// ]]; then
12
+ pdf_file="$tmp_dir/source.pdf"
13
+ if command -v curl >/dev/null 2>&1; then
14
+ curl -L -o "$pdf_file" "$pdf_source"
15
+ elif command -v wget >/dev/null 2>&1; then
16
+ wget -O "$pdf_file" "$pdf_source"
17
+ else
18
+ echo "Error: curl or wget is required to download PDF from URL." >&2
19
+ exit 1
20
+ fi
21
+ else
22
+ pdf_file="$pdf_source"
23
+ fi
24
+
25
+ mkdir -p "$out_dir"
26
+
27
+ if command -v pdf-parse >/dev/null 2>&1; then
28
+ pdfparse_cmd=(pdf-parse)
29
+ elif command -v npx >/dev/null 2>&1; then
30
+ pdfparse_cmd=(npx --yes pdf-parse)
31
+ elif [ -x "./node_modules/.bin/pdf-parse" ]; then
32
+ pdfparse_cmd=(./node_modules/.bin/pdf-parse)
33
+ else
34
+ echo "Error: pdf-parse CLI not found. Install it globally with 'npm install -g pdf-parse' or use npx." >&2
35
+ exit 1
36
+ fi
37
+
38
+ if [ "$pages" = "all" ]; then
39
+ pages_arg=()
40
+ else
41
+ pages_arg=(--pages "$pages")
42
+ fi
43
+
44
+ "${pdfparse_cmd[@]}" screenshot "$pdf_file" "${pages_arg[@]}" --output "$tmp_dir"
45
+
46
+ # Rename generated screenshot files in page order
47
+ count=1
48
+ while IFS= read -r -d '' img; do
49
+ cp "$img" "$out_dir/slide${count}.png"
50
+ count=$((count + 1))
51
+ done < <(find "$tmp_dir" -maxdepth 1 -type f -name '*_screenshot.png' -print0 | sort -z -V)
52
+
53
+ echo "Created $((count - 1)) slide images in '$out_dir' from '$pdf_file'."
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ function usage() {
6
+ console.log('Usage: node question-illustration.js <slides-dir> <output-file> [pattern]');
7
+ console.log('Example: node question-illustration.js notes illustration.md "*question.png"');
8
+ }
9
+
10
+ function patternToRegex(pattern) {
11
+ const escaped = pattern.replace(/[-[\]{}()+?.,\\^$|#\s*]/g, '\\$&');
12
+ const regex = '^' + escaped.replace(/\\\*/g, '.*').replace(/\\\?/g, '.') + '$';
13
+ return new RegExp(regex, 'i');
14
+ }
15
+
16
+ function walkDir(dir, matcher) {
17
+ const files = [];
18
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
19
+ const fullPath = path.join(dir, entry.name);
20
+ if (entry.isDirectory()) {
21
+ files.push(...walkDir(fullPath, matcher));
22
+ } else if (entry.isFile() && matcher(entry.name)) {
23
+ files.push(fullPath);
24
+ }
25
+ }
26
+ return files.sort();
27
+ }
28
+
29
+ function cleanTitle(name) {
30
+ let title = name.replace(/question$/i, '');
31
+ title = title.replace(/[-_]+$/, '');
32
+ title = title.replace(/[-_]+/g, ' ');
33
+ title = title.trim();
34
+ if (!title) title = name;
35
+ return title.charAt(0).toUpperCase() + title.slice(1);
36
+ }
37
+
38
+ function relativePath(from, to) {
39
+ let rel = path.relative(from, to).replace(/\\/g, '/');
40
+ if (!rel.startsWith('.')) rel = './' + rel;
41
+ return rel;
42
+ }
43
+
44
+ async function run() {
45
+ const [,, slidesDir, outputFile, patternArg] = process.argv;
46
+ if (!slidesDir || !outputFile) {
47
+ usage();
48
+ process.exit(1);
49
+ }
50
+
51
+ const pattern = patternArg || '*question.png';
52
+ const matcher = patternToRegex(pattern);
53
+
54
+ if (!fs.existsSync(slidesDir) || !fs.statSync(slidesDir).isDirectory()) {
55
+ console.error(`Error: slides directory not found: ${slidesDir}`);
56
+ process.exit(1);
57
+ }
58
+
59
+ const images = walkDir(slidesDir, name => matcher.test(name));
60
+ if (images.length === 0) {
61
+ console.error(`No files matching pattern ${pattern} found under ${slidesDir}`);
62
+ process.exit(1);
63
+ }
64
+
65
+ const outputDir = path.dirname(outputFile) || '.';
66
+ fs.mkdirSync(outputDir, { recursive: true });
67
+
68
+ const lines = [];
69
+ lines.push('# Question Illustration');
70
+ lines.push('');
71
+ lines.push('Generated from images in `' + slidesDir + '` on ' + new Date().toISOString());
72
+ lines.push('');
73
+
74
+ for (const imagePath of images) {
75
+ const relativeImage = relativePath(outputDir, imagePath);
76
+ const baseName = path.basename(imagePath, path.extname(imagePath));
77
+ const title = cleanTitle(baseName);
78
+
79
+ lines.push(`## ${title}`);
80
+ lines.push('');
81
+ lines.push(`![${title}](${relativeImage})`);
82
+ lines.push('');
83
+ lines.push('---');
84
+ lines.push('');
85
+ }
86
+
87
+ fs.writeFileSync(outputFile, lines.join('\n'), 'utf8');
88
+ console.log(`\nGenerated ${outputFile} with ${images.length} entries.`);
89
+ }
90
+
91
+ run().catch(err => {
92
+ console.error(err);
93
+ process.exit(1);
94
+ });
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ function usage() {
6
+ console.log('Usage: node question-practice-sheet.js <source-dir> <output-file> [pattern]');
7
+ console.log('Example: node question-practice-sheet.js questoinPractices questionSheet.md "*.png"');
8
+ }
9
+
10
+ function wildcardToRegex(pattern) {
11
+ const regex = pattern
12
+ .split('')
13
+ .map(char => {
14
+ if (char === '*') return '.*';
15
+ if (char === '?') return '.';
16
+ return char.replace(/[.+^${}()|[\]\\]/g, '\\$&');
17
+ })
18
+ .join('');
19
+ return new RegExp(`^${regex}$`, 'i');
20
+ }
21
+
22
+ function findImages(dir, matcher) {
23
+ const matches = [];
24
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
25
+ const fullPath = path.join(dir, entry.name);
26
+ if (entry.isDirectory()) {
27
+ matches.push(...findImages(fullPath, matcher));
28
+ } else if (entry.isFile() && matcher.test(entry.name)) {
29
+ matches.push(fullPath);
30
+ }
31
+ }
32
+ return matches.sort();
33
+ }
34
+
35
+ function makeTitle(filename) {
36
+ let name = path.basename(filename, path.extname(filename));
37
+ name = name.replace(/question$/i, '');
38
+ name = name.replace(/[-_]+/g, ' ');
39
+ name = name.replace(/\s+/g, ' ').trim();
40
+ if (!name) {
41
+ name = path.basename(filename);
42
+ }
43
+ return name
44
+ .split(' ')
45
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
46
+ .join(' ');
47
+ }
48
+
49
+ function relativeMarkdownPath(from, to) {
50
+ let rel = path.relative(from, to).replace(/\\/g, '/');
51
+ if (!rel.startsWith('.') && !rel.startsWith('/')) {
52
+ rel = './' + rel;
53
+ }
54
+ return rel;
55
+ }
56
+
57
+ function groupByFolder(files, rootDir) {
58
+ const groups = new Map();
59
+ for (const file of files) {
60
+ const folder = path.relative(rootDir, path.dirname(file)) || '.';
61
+ if (!groups.has(folder)) {
62
+ groups.set(folder, []);
63
+ }
64
+ groups.get(folder).push(file);
65
+ }
66
+ return Array.from(groups.entries()).sort(([a], [b]) => a.localeCompare(b));
67
+ }
68
+
69
+ function buildMarkdown(groups, rootDir, outputDir) {
70
+ const lines = [];
71
+ lines.push('# Question Practice Sheet');
72
+ lines.push('');
73
+ lines.push(`Generated from images in \`${rootDir}\` on ${new Date().toISOString()}`);
74
+ lines.push('');
75
+
76
+ for (const [folder, files] of groups) {
77
+ const section = folder === '.' ? 'General' : folder.replace(/[-_]+/g, ' ');
78
+ lines.push(`## ${section}`);
79
+ lines.push('');
80
+
81
+ for (const file of files) {
82
+ const title = makeTitle(file);
83
+ const imagePath = relativeMarkdownPath(outputDir, file);
84
+ lines.push(`### ${title}`);
85
+ lines.push('');
86
+ lines.push(`![${title}](${imagePath})`);
87
+ lines.push('');
88
+ }
89
+
90
+ lines.push('---');
91
+ lines.push('');
92
+ }
93
+
94
+ return lines.join('\n');
95
+ }
96
+
97
+ function main() {
98
+ const [,, sourceDir, outputFile, patternArg] = process.argv;
99
+ if (!sourceDir || !outputFile) {
100
+ usage();
101
+ process.exit(1);
102
+ }
103
+
104
+ const pattern = patternArg || '*.png';
105
+ const matcher = wildcardToRegex(pattern);
106
+
107
+ if (!fs.existsSync(sourceDir) || !fs.statSync(sourceDir).isDirectory()) {
108
+ console.error(`Error: source directory not found: ${sourceDir}`);
109
+ process.exit(1);
110
+ }
111
+
112
+ const imageFiles = findImages(sourceDir, matcher);
113
+ if (imageFiles.length === 0) {
114
+ console.error(`No images matching ${pattern} found under ${sourceDir}`);
115
+ process.exit(1);
116
+ }
117
+
118
+ const outputDir = path.dirname(outputFile) || '.';
119
+ fs.mkdirSync(outputDir, { recursive: true });
120
+
121
+ const groups = groupByFolder(imageFiles, sourceDir);
122
+ const markdown = buildMarkdown(groups, sourceDir, outputDir);
123
+
124
+ fs.writeFileSync(outputFile, markdown, 'utf8');
125
+ console.log(`Generated ${outputFile} with ${imageFiles.length} questions.`);
126
+ }
127
+
128
+ main();