learn_bash_from_session_data 1.0.4 → 1.0.6
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.
- package/bash-learner-output/run-2026-02-05-154214/index.html +3848 -0
- package/bash-learner-output/run-2026-02-05-154214/summary.json +148 -0
- package/bash-learner-output/run-2026-02-05-155427/index.html +3900 -0
- package/bash-learner-output/run-2026-02-05-155427/summary.json +157 -0
- package/bash-learner-output/run-2026-02-05-155949/index.html +4514 -0
- package/bash-learner-output/run-2026-02-05-155949/summary.json +163 -0
- package/package.json +7 -3
- package/scripts/html_generator.py +135 -58
- package/scripts/knowledge_base.py +5624 -1593
- package/scripts/main.py +110 -5
- package/scripts/quiz_generator.py +163 -48
- package/vectors.db +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
{
|
|
2
|
+
"metadata": {
|
|
3
|
+
"generated_at": "2026-02-05T15:59:49.814630",
|
|
4
|
+
"run_id": "run-2026-02-05-155949",
|
|
5
|
+
"version": "1.0.5"
|
|
6
|
+
},
|
|
7
|
+
"input": {
|
|
8
|
+
"sessions_processed": 10,
|
|
9
|
+
"session_files": [
|
|
10
|
+
{
|
|
11
|
+
"filename": "081cfcfd-cde6-4304-89ca-6ac61faf8d85.jsonl",
|
|
12
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand-Development-Project-Workspace-active-development-session-with-chris/081cfcfd-cde6-4304-89ca-6ac61faf8d85.jsonl",
|
|
13
|
+
"size": "759.1 KB",
|
|
14
|
+
"modified": "2026-02-05 11:01:08"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"filename": "2ee58010-e794-48d8-a1b7-0ba14e06e7b7.jsonl",
|
|
18
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/2ee58010-e794-48d8-a1b7-0ba14e06e7b7.jsonl",
|
|
19
|
+
"size": "1.8 KB",
|
|
20
|
+
"modified": "2026-02-05 10:22:23"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"filename": "ef6494ae-aca1-43b1-800d-d5586069d42c.jsonl",
|
|
24
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/ef6494ae-aca1-43b1-800d-d5586069d42c.jsonl",
|
|
25
|
+
"size": "1.8 KB",
|
|
26
|
+
"modified": "2026-01-23 14:32:05"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"filename": "6b1fb6cd-5865-4a5f-97f9-5e1e46d79f81.jsonl",
|
|
30
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/6b1fb6cd-5865-4a5f-97f9-5e1e46d79f81.jsonl",
|
|
31
|
+
"size": "3.7 KB",
|
|
32
|
+
"modified": "2026-01-19 22:44:52"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"filename": "9db5f466-5bc4-4778-94ba-b10d72e8c464.jsonl",
|
|
36
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/9db5f466-5bc4-4778-94ba-b10d72e8c464.jsonl",
|
|
37
|
+
"size": "916.0 B",
|
|
38
|
+
"modified": "2026-01-19 09:25:47"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"filename": "dfc82e92-9786-4baf-a5df-44046f21f90a.jsonl",
|
|
42
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand-Development-Project-Workspace-active-development-en-consulta/dfc82e92-9786-4baf-a5df-44046f21f90a.jsonl",
|
|
43
|
+
"size": "1.0 KB",
|
|
44
|
+
"modified": "2026-01-16 06:42:34"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"filename": "b3c0facc-2728-48a5-a1d0-0fed6b049cf2.jsonl",
|
|
48
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/b3c0facc-2728-48a5-a1d0-0fed6b049cf2.jsonl",
|
|
49
|
+
"size": "116.0 B",
|
|
50
|
+
"modified": "2026-01-08 21:01:17"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"filename": "846d1c3c-05e3-4d86-9aae-c8bd266962d4.jsonl",
|
|
54
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/846d1c3c-05e3-4d86-9aae-c8bd266962d4.jsonl",
|
|
55
|
+
"size": "1.8 KB",
|
|
56
|
+
"modified": "2026-01-08 21:00:57"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"filename": "agent-a979d7c.jsonl",
|
|
60
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/agent-a979d7c.jsonl",
|
|
61
|
+
"size": "2.0 KB",
|
|
62
|
+
"modified": "2026-01-06 20:47:47"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"filename": "agent-a1fb460.jsonl",
|
|
66
|
+
"path": "/mnt/c/Users/brand/.claude/projects/C--Users-brand/agent-a1fb460.jsonl",
|
|
67
|
+
"size": "1.9 KB",
|
|
68
|
+
"modified": "2026-01-06 20:47:44"
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"total_entries": 438
|
|
72
|
+
},
|
|
73
|
+
"analysis": {
|
|
74
|
+
"raw_commands_found": 37,
|
|
75
|
+
"unique_commands": 53,
|
|
76
|
+
"categories": [
|
|
77
|
+
"Unknown",
|
|
78
|
+
"Package Management",
|
|
79
|
+
"Text Processing",
|
|
80
|
+
"File System",
|
|
81
|
+
"Shell Builtins",
|
|
82
|
+
"Development",
|
|
83
|
+
"Git",
|
|
84
|
+
"Search & Navigation",
|
|
85
|
+
"Process & System"
|
|
86
|
+
],
|
|
87
|
+
"category_counts": {
|
|
88
|
+
"Unknown": 5,
|
|
89
|
+
"Package Management": 4,
|
|
90
|
+
"Text Processing": 3,
|
|
91
|
+
"File System": 7,
|
|
92
|
+
"Shell Builtins": 3,
|
|
93
|
+
"Development": 5,
|
|
94
|
+
"Git": 24,
|
|
95
|
+
"Search & Navigation": 1,
|
|
96
|
+
"Process & System": 1
|
|
97
|
+
},
|
|
98
|
+
"top_base_commands": [
|
|
99
|
+
{
|
|
100
|
+
"command": "cd",
|
|
101
|
+
"count": 18
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"command": "git",
|
|
105
|
+
"count": 17
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"command": "gh",
|
|
109
|
+
"count": 9
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"command": "python",
|
|
113
|
+
"count": 5
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"command": "mkdir",
|
|
117
|
+
"count": 3
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"command": "ls",
|
|
121
|
+
"count": 3
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"command": "echo",
|
|
125
|
+
"count": 3
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"command": "session-slides",
|
|
129
|
+
"count": 3
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"command": "pip",
|
|
133
|
+
"count": 2
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"command": "head",
|
|
137
|
+
"count": 2
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
"operators_used": {
|
|
141
|
+
"||": 4,
|
|
142
|
+
"|": 3,
|
|
143
|
+
"2>&1": 8,
|
|
144
|
+
"2>/dev/null": 5,
|
|
145
|
+
"&&": 29,
|
|
146
|
+
">": 5,
|
|
147
|
+
"<": 13
|
|
148
|
+
},
|
|
149
|
+
"complexity_distribution": {
|
|
150
|
+
"1": 10,
|
|
151
|
+
"2": 23,
|
|
152
|
+
"3": 15,
|
|
153
|
+
"4": 3,
|
|
154
|
+
"5": 2
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"output": {
|
|
158
|
+
"quiz_questions": 20,
|
|
159
|
+
"html_files": [
|
|
160
|
+
"bash-learner-output/run-2026-02-05-155949/index.html"
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "learn_bash_from_session_data",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Learn bash from your Claude Code sessions - extracts commands and generates interactive HTML lessons",
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Learn bash from your Claude Code sessions - extracts commands and generates interactive HTML lessons with 400+ commands, quizzes, and comprehensive coverage",
|
|
5
5
|
"main": "bin/learn-bash.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"learn-bash": "bin/learn-bash.js",
|
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
"claude",
|
|
17
17
|
"cli",
|
|
18
18
|
"terminal",
|
|
19
|
-
"shell"
|
|
19
|
+
"shell",
|
|
20
|
+
"quiz",
|
|
21
|
+
"commands",
|
|
22
|
+
"interactive",
|
|
23
|
+
"education"
|
|
20
24
|
],
|
|
21
25
|
"author": "",
|
|
22
26
|
"license": "MIT",
|
|
@@ -114,19 +114,52 @@ def _generate_html_impl(analysis_result: dict[str, Any], quizzes: list[dict[str,
|
|
|
114
114
|
</html>'''
|
|
115
115
|
|
|
116
116
|
|
|
117
|
+
def _generate_operators_html(operators_used: dict, operator_descriptions: dict) -> str:
|
|
118
|
+
"""Generate HTML for the operators used section."""
|
|
119
|
+
if not operators_used:
|
|
120
|
+
return '<p class="empty-state">No bash operators detected in these commands</p>'
|
|
121
|
+
|
|
122
|
+
operators_html = ""
|
|
123
|
+
# Sort by count descending
|
|
124
|
+
sorted_ops = sorted(operators_used.items(), key=lambda x: -x[1])
|
|
125
|
+
max_count = sorted_ops[0][1] if sorted_ops else 1
|
|
126
|
+
|
|
127
|
+
for op, count in sorted_ops:
|
|
128
|
+
name, desc = operator_descriptions.get(op, (op, 'Bash operator'))
|
|
129
|
+
bar_width = (count / max_count) * 100
|
|
130
|
+
operators_html += f'''
|
|
131
|
+
<div class="operator-item">
|
|
132
|
+
<div class="operator-symbol"><code>{html.escape(op)}</code></div>
|
|
133
|
+
<div class="operator-info">
|
|
134
|
+
<div class="operator-name">{html.escape(name)}</div>
|
|
135
|
+
<div class="operator-desc">{html.escape(desc)}</div>
|
|
136
|
+
</div>
|
|
137
|
+
<div class="operator-bar-container">
|
|
138
|
+
<div class="operator-bar" style="width: {bar_width}%"></div>
|
|
139
|
+
</div>
|
|
140
|
+
<div class="operator-count">{count}</div>
|
|
141
|
+
</div>'''
|
|
142
|
+
return operators_html
|
|
143
|
+
|
|
144
|
+
|
|
117
145
|
def render_overview_tab(stats: dict[str, Any], commands: list[dict], categories: dict) -> str:
|
|
118
146
|
"""Render the overview/dashboard tab content."""
|
|
119
147
|
total_commands = stats.get("total_commands", 0)
|
|
120
148
|
unique_commands = stats.get("unique_commands", 0)
|
|
121
149
|
unique_utilities = stats.get("unique_utilities", 0)
|
|
122
150
|
date_range = stats.get("date_range", {"start": "N/A", "end": "N/A"})
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
151
|
+
# Get operators data for the "Bash Operators Used" section
|
|
152
|
+
operators_used = stats.get("operators_used", {})
|
|
153
|
+
operator_descriptions = {
|
|
154
|
+
'|': ('Pipe', 'Sends output of one command to input of another'),
|
|
155
|
+
'||': ('OR operator', 'Run next command if previous failed'),
|
|
156
|
+
'&&': ('AND operator', 'Run next command if previous succeeded'),
|
|
157
|
+
'2>&1': ('Redirect stderr', 'Combines error output with standard output'),
|
|
158
|
+
'2>/dev/null': ('Suppress errors', 'Discards error messages'),
|
|
159
|
+
'>': ('Redirect output', 'Writes output to a file (overwrites)'),
|
|
160
|
+
'>>': ('Append output', 'Appends output to a file'),
|
|
161
|
+
'<': ('Redirect input', 'Reads input from a file'),
|
|
162
|
+
}
|
|
130
163
|
|
|
131
164
|
# Top 10 commands by frequency - use pre-computed data if available
|
|
132
165
|
top_commands_data = stats.get("top_commands", [])
|
|
@@ -237,29 +270,9 @@ def render_overview_tab(stats: dict[str, Any], commands: list[dict], categories:
|
|
|
237
270
|
|
|
238
271
|
<div class="charts-row">
|
|
239
272
|
<div class="chart-card">
|
|
240
|
-
<h3>
|
|
241
|
-
<div class="
|
|
242
|
-
|
|
243
|
-
<span class="complexity-label simple">Simple</span>
|
|
244
|
-
<div class="complexity-bar-bg">
|
|
245
|
-
<div class="complexity-bar simple" style="width: {simple_pct}%"></div>
|
|
246
|
-
</div>
|
|
247
|
-
<span class="complexity-count">{complexity_dist.get("simple", 0)}</span>
|
|
248
|
-
</div>
|
|
249
|
-
<div class="complexity-row">
|
|
250
|
-
<span class="complexity-label intermediate">Intermediate</span>
|
|
251
|
-
<div class="complexity-bar-bg">
|
|
252
|
-
<div class="complexity-bar intermediate" style="width: {intermediate_pct}%"></div>
|
|
253
|
-
</div>
|
|
254
|
-
<span class="complexity-count">{complexity_dist.get("intermediate", 0)}</span>
|
|
255
|
-
</div>
|
|
256
|
-
<div class="complexity-row">
|
|
257
|
-
<span class="complexity-label advanced">Advanced</span>
|
|
258
|
-
<div class="complexity-bar-bg">
|
|
259
|
-
<div class="complexity-bar advanced" style="width: {advanced_pct}%"></div>
|
|
260
|
-
</div>
|
|
261
|
-
<span class="complexity-count">{complexity_dist.get("advanced", 0)}</span>
|
|
262
|
-
</div>
|
|
273
|
+
<h3>Bash Operators Used</h3>
|
|
274
|
+
<div class="operators-list">
|
|
275
|
+
{_generate_operators_html(operators_used, operator_descriptions)}
|
|
263
276
|
</div>
|
|
264
277
|
</div>
|
|
265
278
|
|
|
@@ -385,11 +398,10 @@ def render_commands_tab(commands: list[dict]) -> str:
|
|
|
385
398
|
</div>'''
|
|
386
399
|
|
|
387
400
|
commands_html += f'''
|
|
388
|
-
<div class="command-card" data-category="{category}" data-
|
|
401
|
+
<div class="command-card" data-category="{category}" data-frequency="{frequency}" data-name="{base_cmd}">
|
|
389
402
|
<div class="command-header" onclick="toggleCommand('{cmd_id}')">
|
|
390
403
|
<div class="command-main">
|
|
391
404
|
<code class="cmd">{base_cmd}</code>
|
|
392
|
-
<span class="complexity-badge {complexity}">{complexity}</span>
|
|
393
405
|
<span class="category-badge">{category}</span>
|
|
394
406
|
</div>
|
|
395
407
|
<div class="command-meta">
|
|
@@ -504,7 +516,6 @@ def render_lessons_tab(categories: dict, commands: list[dict]) -> str:
|
|
|
504
516
|
<div class="lesson-command">
|
|
505
517
|
<div class="lesson-command-header">
|
|
506
518
|
<code class="cmd">{base_cmd}</code>
|
|
507
|
-
<span class="complexity-badge {complexity}">{complexity}</span>
|
|
508
519
|
</div>
|
|
509
520
|
<pre class="syntax-highlighted">{highlighted}</pre>
|
|
510
521
|
<p class="lesson-description">{description}</p>
|
|
@@ -548,20 +559,17 @@ def render_lessons_tab(categories: dict, commands: list[dict]) -> str:
|
|
|
548
559
|
def _get_category_concept(category: str) -> str:
|
|
549
560
|
"""Get concept overview for a category."""
|
|
550
561
|
concepts = {
|
|
551
|
-
"File
|
|
552
|
-
"Text Processing": "Tools for searching, filtering,
|
|
553
|
-
"
|
|
554
|
-
"
|
|
555
|
-
"
|
|
556
|
-
"
|
|
557
|
-
"
|
|
558
|
-
"
|
|
559
|
-
"
|
|
560
|
-
"
|
|
561
|
-
"
|
|
562
|
-
"Compression": "Tools for compressing, archiving, and extracting files.",
|
|
563
|
-
"Search": "Commands for finding files, searching content, and locating resources.",
|
|
564
|
-
"Permissions": "Tools for managing file permissions, ownership, and access control.",
|
|
562
|
+
"File System": "Commands for navigating, viewing, creating, and managing files and directories in the filesystem.",
|
|
563
|
+
"Text Processing": "Tools for viewing, searching, filtering, and transforming text content in files and streams.",
|
|
564
|
+
"Git": "Version control system commands for tracking changes, managing branches, and collaborating on code.",
|
|
565
|
+
"Package Management": "Package managers for installing, updating, and managing software dependencies across languages and platforms.",
|
|
566
|
+
"Process & System": "Commands for monitoring, managing, and controlling running processes and system resources.",
|
|
567
|
+
"Networking": "Commands for network operations, file transfers, remote access, and connectivity diagnostics.",
|
|
568
|
+
"Permissions": "Commands for managing file ownership, access permissions, and user/group administration.",
|
|
569
|
+
"Compression": "Commands for compressing, archiving, and extracting files using various algorithms.",
|
|
570
|
+
"Search & Navigation": "Commands for finding files, searching content, and navigating the filesystem efficiently.",
|
|
571
|
+
"Development": "Development tools for building, testing, compiling, and running code across languages.",
|
|
572
|
+
"Shell Builtins": "Built-in shell commands for scripting, variable management, and interactive shell use.",
|
|
565
573
|
}
|
|
566
574
|
return concepts.get(category, f"Commands related to {category.lower()} operations and utilities.")
|
|
567
575
|
|
|
@@ -569,20 +577,17 @@ def _get_category_concept(category: str) -> str:
|
|
|
569
577
|
def _get_category_icon(category: str) -> str:
|
|
570
578
|
"""Get icon for a category."""
|
|
571
579
|
icons = {
|
|
572
|
-
"File
|
|
580
|
+
"File System": "📁",
|
|
573
581
|
"Text Processing": "📄",
|
|
574
|
-
"
|
|
575
|
-
"Network": "🌐",
|
|
582
|
+
"Git": "📊",
|
|
576
583
|
"Package Management": "📦",
|
|
577
|
-
"
|
|
578
|
-
"
|
|
579
|
-
"User Management": "👤",
|
|
580
|
-
"Disk Management": "💿",
|
|
581
|
-
"Shell Scripting": "❯",
|
|
582
|
-
"Development": "💻",
|
|
583
|
-
"Compression": "📦",
|
|
584
|
-
"Search": "🔍",
|
|
584
|
+
"Process & System": "⚙",
|
|
585
|
+
"Networking": "🌐",
|
|
585
586
|
"Permissions": "🔒",
|
|
587
|
+
"Compression": "📦",
|
|
588
|
+
"Search & Navigation": "🔍",
|
|
589
|
+
"Development": "💻",
|
|
590
|
+
"Shell Builtins": "❯",
|
|
586
591
|
}
|
|
587
592
|
return icons.get(category, "📌")
|
|
588
593
|
|
|
@@ -990,6 +995,77 @@ def get_inline_css() -> str:
|
|
|
990
995
|
color: var(--text-secondary);
|
|
991
996
|
}
|
|
992
997
|
|
|
998
|
+
/* Operators List */
|
|
999
|
+
.operators-list {
|
|
1000
|
+
display: flex;
|
|
1001
|
+
flex-direction: column;
|
|
1002
|
+
gap: 12px;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
.operator-item {
|
|
1006
|
+
display: grid;
|
|
1007
|
+
grid-template-columns: 80px 1fr 120px 50px;
|
|
1008
|
+
align-items: center;
|
|
1009
|
+
gap: 12px;
|
|
1010
|
+
padding: 8px 0;
|
|
1011
|
+
border-bottom: 1px solid var(--border-color);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
.operator-item:last-child {
|
|
1015
|
+
border-bottom: none;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
.operator-symbol {
|
|
1019
|
+
font-family: var(--font-mono);
|
|
1020
|
+
font-size: 1rem;
|
|
1021
|
+
font-weight: 600;
|
|
1022
|
+
color: var(--accent-primary);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.operator-symbol code {
|
|
1026
|
+
background: var(--bg-tertiary);
|
|
1027
|
+
padding: 4px 8px;
|
|
1028
|
+
border-radius: var(--radius-sm);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
.operator-info {
|
|
1032
|
+
display: flex;
|
|
1033
|
+
flex-direction: column;
|
|
1034
|
+
gap: 2px;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
.operator-name {
|
|
1038
|
+
font-size: 0.9rem;
|
|
1039
|
+
font-weight: 600;
|
|
1040
|
+
color: var(--text-primary);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
.operator-desc {
|
|
1044
|
+
font-size: 0.8rem;
|
|
1045
|
+
color: var(--text-secondary);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
.operator-bar-container {
|
|
1049
|
+
height: 20px;
|
|
1050
|
+
background: var(--bg-tertiary);
|
|
1051
|
+
border-radius: var(--radius-sm);
|
|
1052
|
+
overflow: hidden;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
.operator-bar {
|
|
1056
|
+
height: 100%;
|
|
1057
|
+
background: var(--accent-primary);
|
|
1058
|
+
border-radius: var(--radius-sm);
|
|
1059
|
+
transition: width 0.5s ease;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
.operator-count {
|
|
1063
|
+
font-size: 0.9rem;
|
|
1064
|
+
font-weight: 600;
|
|
1065
|
+
text-align: right;
|
|
1066
|
+
color: var(--text-secondary);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
993
1069
|
/* Pie Chart */
|
|
994
1070
|
.pie-container {
|
|
995
1071
|
display: flex;
|
|
@@ -2081,6 +2157,7 @@ def generate_html_files(
|
|
|
2081
2157
|
'complexity_avg': stats.get('average_complexity', 2),
|
|
2082
2158
|
'complexity_distribution': complexity_distribution,
|
|
2083
2159
|
'top_commands': top_10_commands, # Pre-computed top commands with frequencies
|
|
2160
|
+
'operators_used': analysis.get('operators_used', {}), # Bash operators like ||, &&, |, 2>&1
|
|
2084
2161
|
},
|
|
2085
2162
|
'commands': formatted_commands,
|
|
2086
2163
|
'categories': {cat: [c.get('command', '') for c in cmds] for cat, cmds in categories.items()},
|