web-prac 0.1.0__tar.gz
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.
- web_prac-0.1.0/PKG-INFO +46 -0
- web_prac-0.1.0/README.md +39 -0
- web_prac-0.1.0/pyproject.toml +14 -0
- web_prac-0.1.0/setup.cfg +4 -0
- web_prac-0.1.0/tests/test_web.py +61 -0
- web_prac-0.1.0/web/__init__.py +50 -0
- web_prac-0.1.0/web/_core.py +51 -0
- web_prac-0.1.0/web/exp2.py +100 -0
- web_prac-0.1.0/web/exp3.py +185 -0
- web_prac-0.1.0/web/exp4.py +130 -0
- web_prac-0.1.0/web/exp5.py +236 -0
- web_prac-0.1.0/web/exp7.py +157 -0
- web_prac-0.1.0/web/exp8.py +166 -0
- web_prac-0.1.0/web_prac.egg-info/PKG-INFO +46 -0
- web_prac-0.1.0/web_prac.egg-info/SOURCES.txt +15 -0
- web_prac-0.1.0/web_prac.egg-info/dependency_links.txt +1 -0
- web_prac-0.1.0/web_prac.egg-info/top_level.txt +1 -0
web_prac-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: web-prac
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Ready-to-run code scaffolder for Web Lab practicals (HTML, CSS, TypeScript, React, Node.js, Flask)
|
|
5
|
+
Requires-Python: >=3.8
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
# web-prac (`import web`)
|
|
9
|
+
|
|
10
|
+
Direct, ready-to-run file scaffolder for Web Lab experiments (HTML, CSS, TypeScript, React, Node.js, Flask).
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install web-prac
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
In any Python script or interactive Python shell in VS Code:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
import web
|
|
24
|
+
|
|
25
|
+
# Exp 2: HTML5/CSS3 Personal Resume
|
|
26
|
+
web.exp2()
|
|
27
|
+
|
|
28
|
+
# Exp 3: Student Registration Form (HTML, CSS, JS with factorial & fibonacci)
|
|
29
|
+
web.exp3()
|
|
30
|
+
|
|
31
|
+
# Exp 4: TypeScript (Primitives, enums, objects, OOP inheritance)
|
|
32
|
+
web.exp4()
|
|
33
|
+
|
|
34
|
+
# Exp 5: React Single Page Application (React Router DOM, components, styles)
|
|
35
|
+
web.exp5()
|
|
36
|
+
|
|
37
|
+
# Exp 7: Node.js File Server & File Handling (HTTP server + fs operations)
|
|
38
|
+
web.exp7()
|
|
39
|
+
|
|
40
|
+
# Exp 8: Flask Feedback Application (GET/POST form handling)
|
|
41
|
+
web.exp8()
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Folder Handling
|
|
45
|
+
- **If a project folder is already open in VS Code**, the files are written directly into your active folder.
|
|
46
|
+
- **If no folder is open**, it automatically creates a `prac/` folder and opens it directly in VS Code.
|
web_prac-0.1.0/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# web-prac (`import web`)
|
|
2
|
+
|
|
3
|
+
Direct, ready-to-run file scaffolder for Web Lab experiments (HTML, CSS, TypeScript, React, Node.js, Flask).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install web-prac
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
In any Python script or interactive Python shell in VS Code:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import web
|
|
17
|
+
|
|
18
|
+
# Exp 2: HTML5/CSS3 Personal Resume
|
|
19
|
+
web.exp2()
|
|
20
|
+
|
|
21
|
+
# Exp 3: Student Registration Form (HTML, CSS, JS with factorial & fibonacci)
|
|
22
|
+
web.exp3()
|
|
23
|
+
|
|
24
|
+
# Exp 4: TypeScript (Primitives, enums, objects, OOP inheritance)
|
|
25
|
+
web.exp4()
|
|
26
|
+
|
|
27
|
+
# Exp 5: React Single Page Application (React Router DOM, components, styles)
|
|
28
|
+
web.exp5()
|
|
29
|
+
|
|
30
|
+
# Exp 7: Node.js File Server & File Handling (HTTP server + fs operations)
|
|
31
|
+
web.exp7()
|
|
32
|
+
|
|
33
|
+
# Exp 8: Flask Feedback Application (GET/POST form handling)
|
|
34
|
+
web.exp8()
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Folder Handling
|
|
38
|
+
- **If a project folder is already open in VS Code**, the files are written directly into your active folder.
|
|
39
|
+
- **If no folder is open**, it automatically creates a `prac/` folder and opens it directly in VS Code.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "web-prac"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Ready-to-run code scaffolder for Web Lab practicals (HTML, CSS, TypeScript, React, Node.js, Flask)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
dependencies = []
|
|
12
|
+
|
|
13
|
+
[tool.setuptools]
|
|
14
|
+
packages = ["web"]
|
web_prac-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import tempfile
|
|
4
|
+
import unittest
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
PKG_ROOT = Path(__file__).resolve().parents[1]
|
|
8
|
+
if str(PKG_ROOT) not in sys.path:
|
|
9
|
+
sys.path.insert(0, str(PKG_ROOT))
|
|
10
|
+
|
|
11
|
+
import web
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestWebPractical(unittest.TestCase):
|
|
15
|
+
def test_get_code(self):
|
|
16
|
+
for exp in ["exp2", "exp3", "exp4", "exp5", "exp7", "exp8"]:
|
|
17
|
+
files = web.get_code(exp)
|
|
18
|
+
self.assertIsInstance(files, dict)
|
|
19
|
+
self.assertGreater(len(files), 0)
|
|
20
|
+
|
|
21
|
+
def test_exp2_creation(self):
|
|
22
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
23
|
+
web.exp2(path=tmp)
|
|
24
|
+
self.assertTrue((Path(tmp) / "index.html").exists())
|
|
25
|
+
|
|
26
|
+
def test_exp3_creation(self):
|
|
27
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
28
|
+
web.exp3(path=tmp)
|
|
29
|
+
self.assertTrue((Path(tmp) / "index.html").exists())
|
|
30
|
+
self.assertTrue((Path(tmp) / "styles.css").exists())
|
|
31
|
+
self.assertTrue((Path(tmp) / "script.js").exists())
|
|
32
|
+
|
|
33
|
+
def test_exp4_creation(self):
|
|
34
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
35
|
+
web.exp4(path=tmp)
|
|
36
|
+
self.assertTrue((Path(tmp) / "index.ts").exists())
|
|
37
|
+
self.assertTrue((Path(tmp) / "tsconfig.json").exists())
|
|
38
|
+
|
|
39
|
+
def test_exp5_creation(self):
|
|
40
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
41
|
+
web.exp5(path=tmp)
|
|
42
|
+
self.assertTrue((Path(tmp) / "src" / "App.jsx").exists())
|
|
43
|
+
self.assertTrue((Path(tmp) / "src" / "App.css").exists())
|
|
44
|
+
self.assertTrue((Path(tmp) / "package.json").exists())
|
|
45
|
+
|
|
46
|
+
def test_exp7_creation(self):
|
|
47
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
48
|
+
web.exp7(path=tmp)
|
|
49
|
+
self.assertTrue((Path(tmp) / "server.js").exists())
|
|
50
|
+
self.assertTrue((Path(tmp) / "file_ops.js").exists())
|
|
51
|
+
self.assertTrue((Path(tmp) / "file.txt").exists())
|
|
52
|
+
|
|
53
|
+
def test_exp8_creation(self):
|
|
54
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
55
|
+
web.exp8(path=tmp)
|
|
56
|
+
self.assertTrue((Path(tmp) / "app.py").exists())
|
|
57
|
+
self.assertTrue((Path(tmp) / "templates" / "feedback.html").exists())
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
unittest.main()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""web-prac: Ready-to-run code scaffolder for Web Lab experiments."""
|
|
2
|
+
|
|
3
|
+
from .exp2 import exp2, resume
|
|
4
|
+
from .exp3 import exp3, registration
|
|
5
|
+
from .exp4 import exp4, typescript
|
|
6
|
+
from .exp5 import exp5, react
|
|
7
|
+
from .exp7 import exp7, nodejs
|
|
8
|
+
from .exp8 import exp8, flask
|
|
9
|
+
|
|
10
|
+
_EXP_MAP = {
|
|
11
|
+
"exp2": ".exp2",
|
|
12
|
+
"resume": ".exp2",
|
|
13
|
+
"exp3": ".exp3",
|
|
14
|
+
"registration": ".exp3",
|
|
15
|
+
"exp4": ".exp4",
|
|
16
|
+
"typescript": ".exp4",
|
|
17
|
+
"exp5": ".exp5",
|
|
18
|
+
"react": ".exp5",
|
|
19
|
+
"exp7": ".exp7",
|
|
20
|
+
"nodejs": ".exp7",
|
|
21
|
+
"exp8": ".exp8",
|
|
22
|
+
"flask": ".exp8",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_code(exp_name: str) -> dict:
|
|
27
|
+
"""Returns the dictionary of {filename: content} for an experiment without writing to disk."""
|
|
28
|
+
name = exp_name.lower().replace("-", "_")
|
|
29
|
+
if name not in _EXP_MAP:
|
|
30
|
+
raise ValueError(f"Unknown experiment: {exp_name}. Available: {list(_EXP_MAP.keys())}")
|
|
31
|
+
import importlib
|
|
32
|
+
mod = importlib.import_module(_EXP_MAP[name], __name__)
|
|
33
|
+
return mod.FILES
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"exp2",
|
|
38
|
+
"exp3",
|
|
39
|
+
"exp4",
|
|
40
|
+
"exp5",
|
|
41
|
+
"exp7",
|
|
42
|
+
"exp8",
|
|
43
|
+
"resume",
|
|
44
|
+
"registration",
|
|
45
|
+
"typescript",
|
|
46
|
+
"react",
|
|
47
|
+
"nodejs",
|
|
48
|
+
"flask",
|
|
49
|
+
"get_code",
|
|
50
|
+
]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Dict, Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_target_dir(custom_path: Optional[str] = None) -> Path:
|
|
8
|
+
if custom_path:
|
|
9
|
+
target = Path(custom_path).resolve()
|
|
10
|
+
target.mkdir(parents=True, exist_ok=True)
|
|
11
|
+
return target
|
|
12
|
+
|
|
13
|
+
cwd = Path.cwd().resolve()
|
|
14
|
+
user_home = Path.home().resolve()
|
|
15
|
+
|
|
16
|
+
is_home_or_root = (
|
|
17
|
+
cwd == user_home
|
|
18
|
+
or cwd == Path(cwd.anchor).resolve()
|
|
19
|
+
or cwd.name.lower() in ("system32", "windows", "temp")
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
if is_home_or_root:
|
|
23
|
+
target = cwd / "prac"
|
|
24
|
+
target.mkdir(parents=True, exist_ok=True)
|
|
25
|
+
try:
|
|
26
|
+
subprocess.Popen(["code", str(target)], shell=True)
|
|
27
|
+
except Exception:
|
|
28
|
+
try:
|
|
29
|
+
os.startfile(target)
|
|
30
|
+
except Exception:
|
|
31
|
+
pass
|
|
32
|
+
return target
|
|
33
|
+
else:
|
|
34
|
+
return cwd
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def write_files(files: Dict[str, str], exp_name: str, custom_path: Optional[str] = None) -> Path:
|
|
38
|
+
target = get_target_dir(custom_path)
|
|
39
|
+
created = []
|
|
40
|
+
for rel_path, content in files.items():
|
|
41
|
+
file_path = target / rel_path
|
|
42
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
file_path.write_text(content.strip() + "\n", encoding="utf-8")
|
|
44
|
+
created.append(rel_path)
|
|
45
|
+
|
|
46
|
+
print(f"\n[web] Successfully created {exp_name} files in:")
|
|
47
|
+
print(f" {target}")
|
|
48
|
+
for f in created:
|
|
49
|
+
print(f" -> {f}")
|
|
50
|
+
print()
|
|
51
|
+
return target
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from ._core import write_files
|
|
2
|
+
|
|
3
|
+
FILES = {
|
|
4
|
+
"index.html": """<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="UTF-8">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
9
|
+
<title>Veer Gopani</title>
|
|
10
|
+
<style>
|
|
11
|
+
* { margin:0; padding:0; box-sizing:border-box; font-family:'Trebuchet MS', Verdana, sans-serif; }
|
|
12
|
+
body { background:#d0d5dc; color:#222; display:flex; justify-content:center; align-items:center; min-height:100vh; padding:1.5rem; }
|
|
13
|
+
.container { width:85%; max-width:900px; background:#f5f6f8; border-radius:15px; overflow:hidden; box-shadow:0 8px 20px rgba(0,0,0,0.2); }
|
|
14
|
+
.header { background:linear-gradient(135deg, #1a1a1a, #3a3a3a); color:#f0f0f0; text-align:center; padding:2rem 1.5rem; }
|
|
15
|
+
.header img { width:130px; height:130px; border-radius:50%; border:4px solid #888; object-fit:cover; margin-bottom:12px; background:#555; }
|
|
16
|
+
.header h1 { font-size:2.2rem; letter-spacing:1px; color:#ffffff; }
|
|
17
|
+
.header p { font-size:1rem; margin-top:6px; font-style:italic; opacity:0.85; color:#c0c0c0; }
|
|
18
|
+
.section { padding:1.5rem 2rem; border-bottom:1px solid #d0d0d0; background:#f8f9fa; }
|
|
19
|
+
.section:nth-child(even) { background:#eef0f2; }
|
|
20
|
+
.section h2 { color:#1a1a1a; margin-bottom:12px; border-left:5px solid #555; padding-left:12px; font-size:1.2rem; }
|
|
21
|
+
.section p { line-height:1.7; color:#2a2a2a; }
|
|
22
|
+
.skills span { display:inline-block; background:#3a3a3a; color:#f0f0f0; padding:6px 18px; border-radius:25px; margin:5px; transition:0.3s; cursor:default; font-size:0.9rem; }
|
|
23
|
+
.skills span:hover { background:#1a1a1a; transform:scale(1.05); }
|
|
24
|
+
ul { margin-left:20px; list-style:none; }
|
|
25
|
+
li { margin-bottom:8px; padding-left:1.2rem; position:relative; line-height:1.6; color:#2a2a2a; }
|
|
26
|
+
li::before { content:"▹"; position:absolute; left:0; color:#555; font-weight:600; }
|
|
27
|
+
.contact p { margin:6px 0; padding-left:0; }
|
|
28
|
+
.contact p::before { content:none; }
|
|
29
|
+
.contact p strong { display:inline-block; min-width:80px; color:#1a1a1a; }
|
|
30
|
+
footer { background:#1a1a1a; color:#c0c0c0; text-align:center; padding:16px; font-size:0.9rem; }
|
|
31
|
+
@media(max-width:600px){ .container{width:98%;} .header img{width:100px;height:100px;} .header h1{font-size:1.6rem;} .section{padding:1.2rem;} .contact p strong{min-width:70px;} }
|
|
32
|
+
</style>
|
|
33
|
+
</head>
|
|
34
|
+
<body>
|
|
35
|
+
<div class="container">
|
|
36
|
+
<div class="header">
|
|
37
|
+
<img src="image.png" alt="Profile Picture">
|
|
38
|
+
<h1>Veer Gopani</h1>
|
|
39
|
+
<p>Information Technology Student | Web Developer | UI Enthusiast</p>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="section">
|
|
42
|
+
<h2>About Me</h2>
|
|
43
|
+
<p><i>"Dream big, stay focused, and never stop learning."</i></p>
|
|
44
|
+
<br>
|
|
45
|
+
<p>I am <strong>Veer Gopani</strong>, an Information Technology student with a keen interest in web development and software programming. I enjoy designing responsive websites, learning new technologies, and improving my coding skills through projects.</p>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="section contact">
|
|
48
|
+
<h2>Personal Details</h2>
|
|
49
|
+
<p><strong>Name:</strong> Veer Gopani</p>
|
|
50
|
+
<p><strong>Age:</strong> 20 Years</p>
|
|
51
|
+
<p><strong>Email:</strong> veergopani70@gmail.com</p>
|
|
52
|
+
<p><strong>Phone:</strong> +91 9833009090</p>
|
|
53
|
+
<p><strong>Address:</strong> Mumbai, Maharashtra</p>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="section">
|
|
56
|
+
<h2>Academic Qualifications</h2>
|
|
57
|
+
<ul>
|
|
58
|
+
<li><strong>T.E. Information Technology</strong> - St. Francis Institute of Technology (Pursuing)</li>
|
|
59
|
+
<li><strong>HSC</strong> - Nirmala Memorial Foundation Jr. College</li>
|
|
60
|
+
<li><strong>SSC</strong> - Kapol Vidhyanidhi International School</li>
|
|
61
|
+
</ul>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="section">
|
|
64
|
+
<h2>Skills</h2>
|
|
65
|
+
<div class="skills">
|
|
66
|
+
<span>JS</span><span>TS</span><span>Python</span>
|
|
67
|
+
<span>Java</span><span>Flutter</span><span>C/C++</span>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="section">
|
|
71
|
+
<h2>Projects</h2>
|
|
72
|
+
<ul>
|
|
73
|
+
<li>TransitOS: Unified Mobility Kernel</li>
|
|
74
|
+
<li>Null Geodesic Raytracer</li>
|
|
75
|
+
<li>AgriNext</li>
|
|
76
|
+
</ul>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="section">
|
|
79
|
+
<h2>Achievements</h2>
|
|
80
|
+
<ul>
|
|
81
|
+
<li>1st Place in the Blockchain Track in CodeSangram Online Hackathon 2026</li>
|
|
82
|
+
</ul>
|
|
83
|
+
</div>
|
|
84
|
+
<footer><p>© 2026 Veer Gopani</p></footer>
|
|
85
|
+
</div>
|
|
86
|
+
</body>
|
|
87
|
+
</html>
|
|
88
|
+
"""
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def exp2(path=None):
|
|
93
|
+
"""Experiment 2: HTML5/CSS3 Personal Resume Layout."""
|
|
94
|
+
return write_files(FILES, "Experiment 2 (Resume)", path)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
resume = exp2
|
|
98
|
+
|
|
99
|
+
if __name__ == "__main__":
|
|
100
|
+
exp2()
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
from ._core import write_files
|
|
2
|
+
|
|
3
|
+
FILES = {
|
|
4
|
+
"index.html": """<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="UTF-8">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
9
|
+
<title>Student Registration Form</title>
|
|
10
|
+
<link rel="stylesheet" href="styles.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div class="card">
|
|
14
|
+
<h2>Student Registration</h2>
|
|
15
|
+
|
|
16
|
+
<div class="field">
|
|
17
|
+
<label for="firstName">First Name *</label>
|
|
18
|
+
<input type="text" id="firstName" placeholder="First name">
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="field">
|
|
22
|
+
<label for="middleName">Middle Name</label>
|
|
23
|
+
<input type="text" id="middleName" placeholder="Middle name">
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="field">
|
|
27
|
+
<label for="lastName">Last Name *</label>
|
|
28
|
+
<input type="text" id="lastName" placeholder="Last name">
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="field">
|
|
32
|
+
<label for="rollNo">Roll No *</label>
|
|
33
|
+
<input type="number" id="rollNo" placeholder="Enter roll number">
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="field">
|
|
37
|
+
<label for="mobileNo">Mobile Number *</label>
|
|
38
|
+
<input type="text" id="mobileNo" placeholder="10-digit mobile number">
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="field">
|
|
42
|
+
<label for="address">Address *</label>
|
|
43
|
+
<textarea id="address" rows="3" placeholder="Enter full address"></textarea>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="field">
|
|
47
|
+
<label for="factorial-input">Enter the factorial number</label>
|
|
48
|
+
<input type="number" id="factorial-input" placeholder="enter factorial no">
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="field">
|
|
52
|
+
<label for="fibonacci-input">Enter the number of terms</label>
|
|
53
|
+
<input type="number" id="fibonacci-input" placeholder="enter no of terms">
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<button onclick="submitValues()">Submit</button>
|
|
57
|
+
|
|
58
|
+
<div id="output"></div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<script src="script.js"></script>
|
|
62
|
+
</body>
|
|
63
|
+
</html>
|
|
64
|
+
""",
|
|
65
|
+
"styles.css": """.card {
|
|
66
|
+
background-color: #2c1b27;
|
|
67
|
+
padding: 25px 30px;
|
|
68
|
+
border-radius: 8px;
|
|
69
|
+
box-shadow: 0 4px 10px rgba(233, 229, 229, 0.1);
|
|
70
|
+
width: 100%;
|
|
71
|
+
max-width: 380px;
|
|
72
|
+
margin: 30px auto;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
h2 {
|
|
76
|
+
margin-top: 0;
|
|
77
|
+
text-align: center;
|
|
78
|
+
color: #ffffff;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.field {
|
|
82
|
+
margin-bottom: 12px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
label {
|
|
86
|
+
display: block;
|
|
87
|
+
margin-bottom: 4px;
|
|
88
|
+
font-weight: bold;
|
|
89
|
+
font-size: 14px;
|
|
90
|
+
color: #ffffff;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
input, textarea {
|
|
94
|
+
width: 100%;
|
|
95
|
+
padding: 8px;
|
|
96
|
+
box-sizing: border-box;
|
|
97
|
+
border: 1px solid #ccc;
|
|
98
|
+
border-radius: 4px;
|
|
99
|
+
background-color: #fafafa;
|
|
100
|
+
font-size: 14px;
|
|
101
|
+
font-family: inherit;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
button {
|
|
105
|
+
width: 100%;
|
|
106
|
+
padding: 10px;
|
|
107
|
+
background-color: #28a745;
|
|
108
|
+
color: white;
|
|
109
|
+
border: none;
|
|
110
|
+
border-radius: 4px;
|
|
111
|
+
cursor: pointer;
|
|
112
|
+
font-size: 16px;
|
|
113
|
+
margin-top: 10px;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
button:hover {
|
|
117
|
+
background-color: #218838;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#output {
|
|
121
|
+
margin-top: 15px;
|
|
122
|
+
font-weight: bold;
|
|
123
|
+
font-size: 14px;
|
|
124
|
+
line-height: 1.5;
|
|
125
|
+
}
|
|
126
|
+
""",
|
|
127
|
+
"script.js": """function submitValues() {
|
|
128
|
+
let firstName = document.getElementById("firstName").value;
|
|
129
|
+
let middleName = document.getElementById("middleName").value;
|
|
130
|
+
let lastName = document.getElementById("lastName").value;
|
|
131
|
+
let rollNo = document.getElementById("rollNo").value;
|
|
132
|
+
let mobileNo = document.getElementById("mobileNo").value;
|
|
133
|
+
let address = document.getElementById("address").value;
|
|
134
|
+
let factorial_input = document.getElementById("factorial-input").value;
|
|
135
|
+
let fibonacci_input = document.getElementById("fibonacci-input").value;
|
|
136
|
+
|
|
137
|
+
let output = document.getElementById("output");
|
|
138
|
+
|
|
139
|
+
let factorial_output = 1;
|
|
140
|
+
for (let index = 1; index <= factorial_input; index++) {
|
|
141
|
+
factorial_output = factorial_output * index;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let fib_num = parseInt(fibonacci_input) || 0;
|
|
145
|
+
let fib_sequence = [];
|
|
146
|
+
let a = 0, b = 1;
|
|
147
|
+
for (let index = 0; index < fib_num; index++) {
|
|
148
|
+
fib_sequence.push(a);
|
|
149
|
+
let next = a + b;
|
|
150
|
+
a = b;
|
|
151
|
+
b = next;
|
|
152
|
+
}
|
|
153
|
+
let fibonacci_output = fib_sequence.join(", ") || "None";
|
|
154
|
+
|
|
155
|
+
if (firstName == "" || lastName == "" || rollNo == "" || mobileNo == "" || address == "") {
|
|
156
|
+
output.innerText = "Please fill in all required (*) fields!";
|
|
157
|
+
output.style.color = "red";
|
|
158
|
+
} else {
|
|
159
|
+
let fullName = firstName + (middleName ? " " + middleName : "") + " " + lastName;
|
|
160
|
+
|
|
161
|
+
output.style.color = "#ffffff";
|
|
162
|
+
output.innerHTML =
|
|
163
|
+
"<hr>" +
|
|
164
|
+
"<strong>Registration Details:</strong><br>" +
|
|
165
|
+
"Name: " + fullName + "<br>" +
|
|
166
|
+
"Roll No: " + rollNo + "<br>" +
|
|
167
|
+
"Mobile: " + mobileNo + "<br>" +
|
|
168
|
+
"Address: " + address + "<br>" +
|
|
169
|
+
"Factorial Output: " + factorial_output + "<br>" +
|
|
170
|
+
"Fibonacci Series: " + fibonacci_output;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
"""
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def exp3(path=None):
|
|
178
|
+
"""Experiment 3: Student Registration Form with Validation, Factorial, and Fibonacci."""
|
|
179
|
+
return write_files(FILES, "Experiment 3 (Student Registration)", path)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
registration = exp3
|
|
183
|
+
|
|
184
|
+
if __name__ == "__main__":
|
|
185
|
+
exp3()
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
from ._core import write_files
|
|
2
|
+
|
|
3
|
+
FILES = {
|
|
4
|
+
"index.ts": """// Primitive datatypes
|
|
5
|
+
let a: number = 47901;
|
|
6
|
+
let b: string = "Veer";
|
|
7
|
+
let c: boolean = true;
|
|
8
|
+
let d: null = null;
|
|
9
|
+
let e: undefined = undefined;
|
|
10
|
+
|
|
11
|
+
console.log("Number:", a);
|
|
12
|
+
console.log("String:", b);
|
|
13
|
+
console.log("Boolean:", c);
|
|
14
|
+
console.log("Null:", d);
|
|
15
|
+
console.log("Undefined:", e);
|
|
16
|
+
|
|
17
|
+
// Non-primitive datatypes
|
|
18
|
+
let marks: number[] = [85, 99, 100]; // array
|
|
19
|
+
console.log("Marks array:", marks);
|
|
20
|
+
|
|
21
|
+
let student1: [number, string] = [60, "Veer"]; // tuple
|
|
22
|
+
console.log("Student tuple:", student1);
|
|
23
|
+
|
|
24
|
+
// User-defined datatypes: enum
|
|
25
|
+
enum Day {
|
|
26
|
+
Monday = "Monday",
|
|
27
|
+
Tuesday = "Tuesday",
|
|
28
|
+
Wednesday = "Wednesday",
|
|
29
|
+
Thursday = "Thursday",
|
|
30
|
+
Friday = "Friday",
|
|
31
|
+
Saturday = "Saturday",
|
|
32
|
+
Sunday = "Sunday"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let today: Day = Day.Sunday;
|
|
36
|
+
console.log("Enum Day:", today);
|
|
37
|
+
|
|
38
|
+
// Typed Object
|
|
39
|
+
let student: {
|
|
40
|
+
name: string;
|
|
41
|
+
age: number;
|
|
42
|
+
} = {
|
|
43
|
+
name: "Veer",
|
|
44
|
+
age: 21
|
|
45
|
+
};
|
|
46
|
+
console.log("Student Object:", student.name, student.age);
|
|
47
|
+
|
|
48
|
+
// Inheritance: Base class
|
|
49
|
+
class Company {
|
|
50
|
+
companyName: string;
|
|
51
|
+
constructor(companyName: string) {
|
|
52
|
+
this.companyName = companyName;
|
|
53
|
+
}
|
|
54
|
+
displayCompany() {
|
|
55
|
+
console.log("Company Name:", this.companyName);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Single Inheritance
|
|
60
|
+
class Employee extends Company {
|
|
61
|
+
employeeName: string;
|
|
62
|
+
employeeId: number;
|
|
63
|
+
constructor(companyName: string, employeeName: string, employeeId: number) {
|
|
64
|
+
super(companyName);
|
|
65
|
+
this.employeeName = employeeName;
|
|
66
|
+
this.employeeId = employeeId;
|
|
67
|
+
}
|
|
68
|
+
displayEmployee() {
|
|
69
|
+
console.log("Employee Name:", this.employeeName);
|
|
70
|
+
console.log("Employee ID:", this.employeeId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const employee1 = new Employee("Ballers Inc.", "Baller", 999);
|
|
75
|
+
employee1.displayCompany();
|
|
76
|
+
employee1.displayEmployee();
|
|
77
|
+
|
|
78
|
+
// Multilevel Inheritance
|
|
79
|
+
class Manager extends Employee {
|
|
80
|
+
department: string;
|
|
81
|
+
constructor(companyName: string, employeeName: string, employeeId: number, department: string) {
|
|
82
|
+
super(companyName, employeeName, employeeId);
|
|
83
|
+
this.department = department;
|
|
84
|
+
}
|
|
85
|
+
displayManager() {
|
|
86
|
+
console.log("Department:", this.department);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const manager1 = new Manager("Ballers Inc.", "Veer", 67, "Goonology");
|
|
91
|
+
manager1.displayCompany();
|
|
92
|
+
manager1.displayEmployee();
|
|
93
|
+
manager1.displayManager();
|
|
94
|
+
""",
|
|
95
|
+
"tsconfig.json": """{
|
|
96
|
+
"compilerOptions": {
|
|
97
|
+
"target": "ES2020",
|
|
98
|
+
"module": "commonjs",
|
|
99
|
+
"strict": true,
|
|
100
|
+
"esModuleInterop": true,
|
|
101
|
+
"skipLibCheck": true,
|
|
102
|
+
"forceConsistentCasingInFileNames": true
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
""",
|
|
106
|
+
"package.json": """{
|
|
107
|
+
"name": "exp4-typescript",
|
|
108
|
+
"version": "1.0.0",
|
|
109
|
+
"scripts": {
|
|
110
|
+
"build": "tsc",
|
|
111
|
+
"start": "npx ts-node index.ts"
|
|
112
|
+
},
|
|
113
|
+
"devDependencies": {
|
|
114
|
+
"ts-node": "^10.9.2",
|
|
115
|
+
"typescript": "^5.0.0"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
"""
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def exp4(path=None):
|
|
123
|
+
"""Experiment 4: TypeScript Datatypes, Enums, Interfaces, and Multilevel Inheritance."""
|
|
124
|
+
return write_files(FILES, "Experiment 4 (TypeScript)", path)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
typescript = exp4
|
|
128
|
+
|
|
129
|
+
if __name__ == "__main__":
|
|
130
|
+
exp4()
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
from ._core import write_files
|
|
2
|
+
|
|
3
|
+
FILES = {
|
|
4
|
+
"index.html": """<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="UTF-8" />
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
+
<title>Web Lab - React SPA</title>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="root"></div>
|
|
13
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
16
|
+
""",
|
|
17
|
+
"src/main.jsx": """import React from 'react';
|
|
18
|
+
import ReactDOM from 'react-dom/client';
|
|
19
|
+
import App from './App.jsx';
|
|
20
|
+
|
|
21
|
+
ReactDOM.createRoot(document.getElementById('root')).render(
|
|
22
|
+
<React.StrictMode>
|
|
23
|
+
<App />
|
|
24
|
+
</React.StrictMode>
|
|
25
|
+
);
|
|
26
|
+
""",
|
|
27
|
+
"src/App.jsx": """import './App.css';
|
|
28
|
+
import { BrowserRouter, Route, Routes, Link } from 'react-router-dom';
|
|
29
|
+
|
|
30
|
+
function Home() {
|
|
31
|
+
const topics = [
|
|
32
|
+
{ srNo: 1, topic: 'HTML & CSS' },
|
|
33
|
+
{ srNo: 2, topic: 'JavaScript' },
|
|
34
|
+
{ srNo: 3, topic: 'TypeScript' },
|
|
35
|
+
{ srNo: 4, topic: 'React' },
|
|
36
|
+
{ srNo: 5, topic: 'Node.js & Express' },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className="section-container">
|
|
41
|
+
<h4 className="section-title">Topics to be covered</h4>
|
|
42
|
+
<table className="topics-table">
|
|
43
|
+
<thead>
|
|
44
|
+
<tr>
|
|
45
|
+
<th>Sr. No.</th>
|
|
46
|
+
<th>Topics</th>
|
|
47
|
+
</tr>
|
|
48
|
+
</thead>
|
|
49
|
+
<tbody>
|
|
50
|
+
{topics.map((item) => (
|
|
51
|
+
<tr key={item.srNo}>
|
|
52
|
+
<td className="text-center">{item.srNo}</td>
|
|
53
|
+
<td>{item.topic}</td>
|
|
54
|
+
</tr>
|
|
55
|
+
))}
|
|
56
|
+
</tbody>
|
|
57
|
+
</table>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function About() {
|
|
63
|
+
return (
|
|
64
|
+
<div className="section-container">
|
|
65
|
+
<h4 className="section-title">Sessions=></h4>
|
|
66
|
+
<div className="content-box">
|
|
67
|
+
<p>
|
|
68
|
+
Web Course
|
|
69
|
+
<br />
|
|
70
|
+
Web Lab
|
|
71
|
+
<br />
|
|
72
|
+
Web Assignment
|
|
73
|
+
<br />
|
|
74
|
+
Web Experiment
|
|
75
|
+
</p>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function Contact() {
|
|
82
|
+
return (
|
|
83
|
+
<div className="section-container">
|
|
84
|
+
<h4 className="section-title">Contacts</h4>
|
|
85
|
+
<div className="content-box">
|
|
86
|
+
<p>Phone No: +91 9372771613</p>
|
|
87
|
+
<p className="margin-top-sm">
|
|
88
|
+
Email-ID: veergopani70@student.sfit.ac.in
|
|
89
|
+
</p>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function App() {
|
|
96
|
+
return (
|
|
97
|
+
<div className="app-root">
|
|
98
|
+
<BrowserRouter>
|
|
99
|
+
<nav className="navbar">
|
|
100
|
+
<span className="nav-title">Web Lab</span>
|
|
101
|
+
<Link to="/" className="nav-link nav-link-active">
|
|
102
|
+
Home
|
|
103
|
+
</Link>
|
|
104
|
+
<Link to="/about" className="nav-link">
|
|
105
|
+
Sessions
|
|
106
|
+
</Link>
|
|
107
|
+
<Link to="/contact" className="nav-link">
|
|
108
|
+
Contact
|
|
109
|
+
</Link>
|
|
110
|
+
</nav>
|
|
111
|
+
|
|
112
|
+
<main className="page-body">
|
|
113
|
+
<Routes>
|
|
114
|
+
<Route path="/" element={<Home />} />
|
|
115
|
+
<Route path="/about" element={<About />} />
|
|
116
|
+
<Route path="/contact" element={<Contact />} />
|
|
117
|
+
</Routes>
|
|
118
|
+
</main>
|
|
119
|
+
</BrowserRouter>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export default App;
|
|
125
|
+
""",
|
|
126
|
+
"src/App.css": """.app-root {
|
|
127
|
+
font-family: sans-serif;
|
|
128
|
+
margin: 0;
|
|
129
|
+
padding: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.navbar {
|
|
133
|
+
background-color: #e3f2fd;
|
|
134
|
+
padding: 10px 20px;
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
gap: 25px;
|
|
138
|
+
font-weight: bold;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.nav-title {
|
|
142
|
+
margin-right: auto;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.nav-link {
|
|
146
|
+
color: #000000;
|
|
147
|
+
text-decoration: none;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.nav-link-active {
|
|
151
|
+
color: #1565c0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.page-body {
|
|
155
|
+
padding: 0 20px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.section-container {
|
|
159
|
+
margin-top: 15px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.section-title {
|
|
163
|
+
margin: 5px 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.topics-table {
|
|
167
|
+
border-collapse: collapse;
|
|
168
|
+
width: 250px;
|
|
169
|
+
text-align: left;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.topics-table th,
|
|
173
|
+
.topics-table td {
|
|
174
|
+
border: 1px solid #000000;
|
|
175
|
+
padding: 4px 8px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.text-center {
|
|
179
|
+
text-align: center;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.content-box {
|
|
183
|
+
border: 1px solid #c2b588;
|
|
184
|
+
padding: 15px;
|
|
185
|
+
min-height: 80px;
|
|
186
|
+
max-width: 600px;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.content-box p {
|
|
190
|
+
margin: 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.margin-top-sm {
|
|
194
|
+
margin-top: 5px;
|
|
195
|
+
}
|
|
196
|
+
""",
|
|
197
|
+
"package.json": """{
|
|
198
|
+
"name": "exp5-react-spa",
|
|
199
|
+
"private": true,
|
|
200
|
+
"version": "0.0.0",
|
|
201
|
+
"type": "module",
|
|
202
|
+
"scripts": {
|
|
203
|
+
"dev": "vite",
|
|
204
|
+
"build": "vite build",
|
|
205
|
+
"preview": "vite preview"
|
|
206
|
+
},
|
|
207
|
+
"dependencies": {
|
|
208
|
+
"react": "^18.2.0",
|
|
209
|
+
"react-dom": "^18.2.0",
|
|
210
|
+
"react-router-dom": "^6.22.0"
|
|
211
|
+
},
|
|
212
|
+
"devDependencies": {
|
|
213
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
214
|
+
"vite": "^5.1.4"
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
""",
|
|
218
|
+
"vite.config.js": """import { defineConfig } from 'vite';
|
|
219
|
+
import react from '@vitejs/plugin-react';
|
|
220
|
+
|
|
221
|
+
export default defineConfig({
|
|
222
|
+
plugins: [react()],
|
|
223
|
+
});
|
|
224
|
+
"""
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def exp5(path=None):
|
|
229
|
+
"""Experiment 5: React Single Page Application using React Router."""
|
|
230
|
+
return write_files(FILES, "Experiment 5 (React SPA)", path)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
react = exp5
|
|
234
|
+
|
|
235
|
+
if __name__ == "__main__":
|
|
236
|
+
exp5()
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from ._core import write_files
|
|
2
|
+
|
|
3
|
+
FILES = {
|
|
4
|
+
"server.js": """const http = require('http');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const PORT = 5377;
|
|
8
|
+
|
|
9
|
+
const server = http.createServer((req, res) => {
|
|
10
|
+
const logMessage = `[${new Date().toISOString()}] Request received for: ${req.url}\\n`;
|
|
11
|
+
fs.appendFile('server.log', logMessage, (err) => {
|
|
12
|
+
if (err) console.error('Failed to write to log file:', err);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
if (req.url === '/' || req.url === '/index.html') {
|
|
16
|
+
fs.readFile(path.join(__dirname, 'index.html'), 'utf8', (err, data) => {
|
|
17
|
+
if (err) {
|
|
18
|
+
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
19
|
+
res.end('500 Internal Server Error: Missing HTML source.');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
23
|
+
res.end(data);
|
|
24
|
+
});
|
|
25
|
+
} else {
|
|
26
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
27
|
+
res.end('404 Page Not Found');
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
server.listen(PORT, () => {
|
|
32
|
+
console.log(`Server is actively running at http://localhost:${PORT}/`);
|
|
33
|
+
});
|
|
34
|
+
""",
|
|
35
|
+
"index.html": """<!DOCTYPE html>
|
|
36
|
+
<html lang="en">
|
|
37
|
+
<head>
|
|
38
|
+
<meta charset="UTF-8">
|
|
39
|
+
<title>Node.js Server</title>
|
|
40
|
+
</head>
|
|
41
|
+
<body>
|
|
42
|
+
<h1>Welcome to My Node.js Server!</h1>
|
|
43
|
+
<p>This file was handled and served using the built-in fs module.</p>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
46
|
+
""",
|
|
47
|
+
"file_ops.js": """const fs = require('fs');
|
|
48
|
+
const readline = require('readline');
|
|
49
|
+
|
|
50
|
+
const rl = readline.createInterface({
|
|
51
|
+
input: process.stdin,
|
|
52
|
+
output: process.stdout
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
console.log("=== Node.js File System Operations ===");
|
|
56
|
+
console.log("1. Read file");
|
|
57
|
+
console.log("2. Check access (file exists)");
|
|
58
|
+
console.log("3. Open/Create file");
|
|
59
|
+
console.log("4. Write to file (replace)");
|
|
60
|
+
console.log("5. Append to file");
|
|
61
|
+
console.log("6. Delete file");
|
|
62
|
+
|
|
63
|
+
rl.question("Enter your choice (1-6): ", (choice) => {
|
|
64
|
+
switch (choice.trim()) {
|
|
65
|
+
case "1":
|
|
66
|
+
rl.question("Enter file name to read: ", (filename) => {
|
|
67
|
+
fs.readFile(filename, 'utf8', (err, data) => {
|
|
68
|
+
if (err) console.error("Error reading file:", err.message);
|
|
69
|
+
else console.log("File Content:\\n" + data);
|
|
70
|
+
rl.close();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
break;
|
|
74
|
+
case "2":
|
|
75
|
+
rl.question("Enter file name to check: ", (filename) => {
|
|
76
|
+
fs.access(filename, fs.constants.F_OK, (err) => {
|
|
77
|
+
if (err) console.log("File does not exist.");
|
|
78
|
+
else console.log("File exists!");
|
|
79
|
+
rl.close();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
break;
|
|
83
|
+
case "3":
|
|
84
|
+
rl.question("Enter file name to open/create: ", (filename) => {
|
|
85
|
+
fs.open(filename, 'w', (err, fd) => {
|
|
86
|
+
if (err) console.error("Error opening file:", err.message);
|
|
87
|
+
else {
|
|
88
|
+
console.log("File opened/created successfully!");
|
|
89
|
+
fs.close(fd, () => {});
|
|
90
|
+
}
|
|
91
|
+
rl.close();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
break;
|
|
95
|
+
case "4":
|
|
96
|
+
rl.question("Enter file name to write: ", (filename) => {
|
|
97
|
+
rl.question("Enter content: ", (content) => {
|
|
98
|
+
fs.writeFile(filename, content, (err) => {
|
|
99
|
+
if (err) console.error("Error writing:", err.message);
|
|
100
|
+
else console.log("Written to file successfully!");
|
|
101
|
+
rl.close();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
break;
|
|
106
|
+
case "5":
|
|
107
|
+
rl.question("Enter file name to append to: ", (filename) => {
|
|
108
|
+
rl.question("Enter content to append: ", (content) => {
|
|
109
|
+
fs.appendFile(filename, content + "\\n", (err) => {
|
|
110
|
+
if (err) console.error("Error appending:", err.message);
|
|
111
|
+
else console.log("Appended successfully!");
|
|
112
|
+
rl.close();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
break;
|
|
117
|
+
case "6":
|
|
118
|
+
rl.question("Enter file name to delete: ", (filename) => {
|
|
119
|
+
fs.unlink(filename, (err) => {
|
|
120
|
+
if (err) console.error("Unable to delete:", err.message);
|
|
121
|
+
else console.log("File deleted successfully!");
|
|
122
|
+
rl.close();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
break;
|
|
126
|
+
default:
|
|
127
|
+
console.log("Invalid choice.");
|
|
128
|
+
rl.close();
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
""",
|
|
133
|
+
"file.txt": """Hello, this is a sample file for Node.js file operations.
|
|
134
|
+
St. Francis Institute of Technology - Web Lab Experiment 7.
|
|
135
|
+
""",
|
|
136
|
+
"package.json": """{
|
|
137
|
+
"name": "exp7-nodejs-server",
|
|
138
|
+
"version": "1.0.0",
|
|
139
|
+
"main": "server.js",
|
|
140
|
+
"scripts": {
|
|
141
|
+
"start": "node server.js",
|
|
142
|
+
"ops": "node file_ops.js"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
"""
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def exp7(path=None):
|
|
150
|
+
"""Experiment 7: Node.js Web Server & File System Handling."""
|
|
151
|
+
return write_files(FILES, "Experiment 7 (Node.js Server & File Handling)", path)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
nodejs = exp7
|
|
155
|
+
|
|
156
|
+
if __name__ == "__main__":
|
|
157
|
+
exp7()
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from ._core import write_files
|
|
2
|
+
|
|
3
|
+
FILES = {
|
|
4
|
+
"app.py": """from flask import Flask, render_template, request
|
|
5
|
+
|
|
6
|
+
app = Flask(__name__)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@app.route('/')
|
|
10
|
+
def show_feedback_form():
|
|
11
|
+
return render_template('feedback.html')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@app.route('/feedback', methods=['POST'])
|
|
15
|
+
def handle_feedback():
|
|
16
|
+
name = request.form.get('name')
|
|
17
|
+
email = request.form.get('email')
|
|
18
|
+
rating = request.form.get('rating')
|
|
19
|
+
comments = request.form.get('comments')
|
|
20
|
+
|
|
21
|
+
return f\"\"\"
|
|
22
|
+
<html>
|
|
23
|
+
<head>
|
|
24
|
+
<title>Feedback Received</title>
|
|
25
|
+
<style>
|
|
26
|
+
body {{ font-family: Arial, sans-serif; background: #f4f4f9; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; }}
|
|
27
|
+
.card {{ background: white; padding: 30px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); width: 380px; text-align: left; }}
|
|
28
|
+
h2 {{ color: #28a745; margin-top: 0; }}
|
|
29
|
+
a {{ display: inline-block; margin-top: 15px; color: #007bff; text-decoration: none; }}
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
<div class="card">
|
|
34
|
+
<h2>Thank You for Your Feedback!</h2>
|
|
35
|
+
<p><strong>Name:</strong> {name}</p>
|
|
36
|
+
<p><strong>Email:</strong> {email}</p>
|
|
37
|
+
<p><strong>Rating:</strong> {rating}/5</p>
|
|
38
|
+
<p><strong>Comments:</strong> {comments}</p>
|
|
39
|
+
<a href="/">← Submit another feedback</a>
|
|
40
|
+
</div>
|
|
41
|
+
</body>
|
|
42
|
+
</html>
|
|
43
|
+
\"\"\"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == '__main__':
|
|
47
|
+
print("Starting Flask Feedback Form at http://localhost:5000/ ...")
|
|
48
|
+
app.run(debug=True, port=5000)
|
|
49
|
+
""",
|
|
50
|
+
"templates/feedback.html": """<!DOCTYPE html>
|
|
51
|
+
<html lang="en">
|
|
52
|
+
<head>
|
|
53
|
+
<meta charset="UTF-8">
|
|
54
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
55
|
+
<title>Feedback Form</title>
|
|
56
|
+
<style>
|
|
57
|
+
body {
|
|
58
|
+
font-family: Arial, sans-serif;
|
|
59
|
+
background-color: #f4f4f9;
|
|
60
|
+
display: flex;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
align-items: center;
|
|
63
|
+
min-height: 100vh;
|
|
64
|
+
margin: 0;
|
|
65
|
+
padding: 20px 0;
|
|
66
|
+
}
|
|
67
|
+
.form-container {
|
|
68
|
+
background-color: #ffffff;
|
|
69
|
+
padding: 30px;
|
|
70
|
+
border-radius: 8px;
|
|
71
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
72
|
+
width: 380px;
|
|
73
|
+
}
|
|
74
|
+
.form-container h2 {
|
|
75
|
+
margin-top: 0;
|
|
76
|
+
margin-bottom: 20px;
|
|
77
|
+
text-align: center;
|
|
78
|
+
color: #333;
|
|
79
|
+
}
|
|
80
|
+
.form-group {
|
|
81
|
+
margin-bottom: 15px;
|
|
82
|
+
}
|
|
83
|
+
.form-group label {
|
|
84
|
+
display: block;
|
|
85
|
+
margin-bottom: 5px;
|
|
86
|
+
font-weight: bold;
|
|
87
|
+
color: #555;
|
|
88
|
+
}
|
|
89
|
+
.form-group input,
|
|
90
|
+
.form-group select,
|
|
91
|
+
.form-group textarea {
|
|
92
|
+
width: 100%;
|
|
93
|
+
padding: 8px;
|
|
94
|
+
box-sizing: border-box;
|
|
95
|
+
border: 1px solid #ccc;
|
|
96
|
+
border-radius: 4px;
|
|
97
|
+
font-size: 14px;
|
|
98
|
+
}
|
|
99
|
+
.form-group textarea {
|
|
100
|
+
resize: vertical;
|
|
101
|
+
height: 100px;
|
|
102
|
+
}
|
|
103
|
+
.submit-btn {
|
|
104
|
+
width: 100%;
|
|
105
|
+
padding: 10px;
|
|
106
|
+
background-color: #28a745;
|
|
107
|
+
color: white;
|
|
108
|
+
border: none;
|
|
109
|
+
border-radius: 4px;
|
|
110
|
+
cursor: pointer;
|
|
111
|
+
font-size: 16px;
|
|
112
|
+
}
|
|
113
|
+
.submit-btn:hover {
|
|
114
|
+
background-color: #218838;
|
|
115
|
+
}
|
|
116
|
+
</style>
|
|
117
|
+
</head>
|
|
118
|
+
<body>
|
|
119
|
+
|
|
120
|
+
<div class="form-container">
|
|
121
|
+
<h2>Feedback Form</h2>
|
|
122
|
+
<form action="/feedback" method="POST">
|
|
123
|
+
<div class="form-group">
|
|
124
|
+
<label for="name">Name:</label>
|
|
125
|
+
<input type="text" id="name" name="name" required>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="form-group">
|
|
128
|
+
<label for="email">Email:</label>
|
|
129
|
+
<input type="email" id="email" name="email" required>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="form-group">
|
|
132
|
+
<label for="rating">Rating:</label>
|
|
133
|
+
<select id="rating" name="rating" required>
|
|
134
|
+
<option value="">-- Select Rating --</option>
|
|
135
|
+
<option value="5">5 - Excellent</option>
|
|
136
|
+
<option value="4">4 - Very Good</option>
|
|
137
|
+
<option value="3">3 - Good</option>
|
|
138
|
+
<option value="2">2 - Fair</option>
|
|
139
|
+
<option value="1">1 - Poor</option>
|
|
140
|
+
</select>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="form-group">
|
|
143
|
+
<label for="comments">Comments / Suggestions:</label>
|
|
144
|
+
<textarea id="comments" name="comments" placeholder="Share your experience..." required></textarea>
|
|
145
|
+
</div>
|
|
146
|
+
<button type="submit" class="submit-btn">Submit Feedback</button>
|
|
147
|
+
</form>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
</body>
|
|
151
|
+
</html>
|
|
152
|
+
""",
|
|
153
|
+
"requirements.txt": """Flask>=2.0.0
|
|
154
|
+
"""
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def exp8(path=None):
|
|
159
|
+
"""Experiment 8: Design Feedback Form using Flask."""
|
|
160
|
+
return write_files(FILES, "Experiment 8 (Flask Feedback Form)", path)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
flask = exp8
|
|
164
|
+
|
|
165
|
+
if __name__ == "__main__":
|
|
166
|
+
exp8()
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: web-prac
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Ready-to-run code scaffolder for Web Lab practicals (HTML, CSS, TypeScript, React, Node.js, Flask)
|
|
5
|
+
Requires-Python: >=3.8
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
|
|
8
|
+
# web-prac (`import web`)
|
|
9
|
+
|
|
10
|
+
Direct, ready-to-run file scaffolder for Web Lab experiments (HTML, CSS, TypeScript, React, Node.js, Flask).
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install web-prac
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
In any Python script or interactive Python shell in VS Code:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
import web
|
|
24
|
+
|
|
25
|
+
# Exp 2: HTML5/CSS3 Personal Resume
|
|
26
|
+
web.exp2()
|
|
27
|
+
|
|
28
|
+
# Exp 3: Student Registration Form (HTML, CSS, JS with factorial & fibonacci)
|
|
29
|
+
web.exp3()
|
|
30
|
+
|
|
31
|
+
# Exp 4: TypeScript (Primitives, enums, objects, OOP inheritance)
|
|
32
|
+
web.exp4()
|
|
33
|
+
|
|
34
|
+
# Exp 5: React Single Page Application (React Router DOM, components, styles)
|
|
35
|
+
web.exp5()
|
|
36
|
+
|
|
37
|
+
# Exp 7: Node.js File Server & File Handling (HTTP server + fs operations)
|
|
38
|
+
web.exp7()
|
|
39
|
+
|
|
40
|
+
# Exp 8: Flask Feedback Application (GET/POST form handling)
|
|
41
|
+
web.exp8()
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Folder Handling
|
|
45
|
+
- **If a project folder is already open in VS Code**, the files are written directly into your active folder.
|
|
46
|
+
- **If no folder is open**, it automatically creates a `prac/` folder and opens it directly in VS Code.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
tests/test_web.py
|
|
4
|
+
web/__init__.py
|
|
5
|
+
web/_core.py
|
|
6
|
+
web/exp2.py
|
|
7
|
+
web/exp3.py
|
|
8
|
+
web/exp4.py
|
|
9
|
+
web/exp5.py
|
|
10
|
+
web/exp7.py
|
|
11
|
+
web/exp8.py
|
|
12
|
+
web_prac.egg-info/PKG-INFO
|
|
13
|
+
web_prac.egg-info/SOURCES.txt
|
|
14
|
+
web_prac.egg-info/dependency_links.txt
|
|
15
|
+
web_prac.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
web
|