codemap-python 0.1.0__tar.gz → 0.1.1__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.
- {codemap_python-0.1.0 → codemap_python-0.1.1}/PKG-INFO +15 -9
- {codemap_python-0.1.0 → codemap_python-0.1.1}/README.md +12 -7
- {codemap_python-0.1.0 → codemap_python-0.1.1}/codemap_python.egg-info/PKG-INFO +15 -9
- {codemap_python-0.1.0 → codemap_python-0.1.1}/codemap_python.egg-info/requires.txt +2 -1
- {codemap_python-0.1.0 → codemap_python-0.1.1}/pyproject.toml +3 -2
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/app.py +22 -1
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/static/app.js +50 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/static/styles.css +127 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/templates/index.html +30 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/architecture/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/architecture/architecture_engine.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/architecture/dependency_cycles.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/architecture/risk_radar.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/call_extractor.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/call_graph_builder.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/call_resolver.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/context_models.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/cross_file_resolver.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/execution_tracker.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/flow_builder.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/call_graph/models.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/core/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/core/ast_context.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/core/ast_parser.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/core/class_extractor.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/core/function_extractor.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/core/import_extractor.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/docstring_extractor.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/explain_runner.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/repo_summary_generator.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/return_analyzer.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/risk_flags.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/signature_extractor.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/explain/summary_generator.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/graph/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/graph/callgraph_index.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/graph/entrypoint_detector.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/graph/impact_analyzer.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/indexing/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/indexing/import_resolver.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/indexing/symbol_index.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/runners/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/runners/phase4_runner.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/utils/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/utils/ast_helpers.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/utils/cache_manager.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/utils/path_resolver.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/analysis/utils/repo_fetcher.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/cli.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/codemap_cli.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/codemap_python.egg-info/SOURCES.txt +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/codemap_python.egg-info/dependency_links.txt +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/codemap_python.egg-info/entry_points.txt +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/codemap_python.egg-info/top_level.txt +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/security_utils.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/setup.cfg +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_cache_cli_commands.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_cache_retention.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_no_key_persistence.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_registry_session_mode.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_security_cli_integration.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_security_redaction.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_symbol_explain_cache.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_symbol_info_endpoint.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_ui_private_mode_security.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/tests/test_ui_retention_controls.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/device_id.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/utils/__init__.py +0 -0
- {codemap_python-0.1.0 → codemap_python-0.1.1}/ui/utils/registry_manager.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codemap-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Local Python code analysis tool - understand architecture, dependencies, and call graphs
|
|
5
5
|
Author-email: ADITYA <aditykushwaha69@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -22,8 +22,9 @@ Requires-Python: >=3.10
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
Requires-Dist: fastapi>=0.110
|
|
24
24
|
Requires-Dist: uvicorn>=0.23
|
|
25
|
-
Requires-Dist: jinja2>=3.1
|
|
25
|
+
Requires-Dist: jinja2>=3.1.4
|
|
26
26
|
Requires-Dist: requests>=2.31
|
|
27
|
+
Requires-Dist: starlette==0.40.0
|
|
27
28
|
|
|
28
29
|
# CodeMap
|
|
29
30
|
|
|
@@ -47,12 +48,8 @@ Requires-Dist: requests>=2.31
|
|
|
47
48
|
### Step 1️⃣: Install CodeMap
|
|
48
49
|
|
|
49
50
|
```bash
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
cd codemap_ai
|
|
53
|
-
|
|
54
|
-
# Install as a local package
|
|
55
|
-
pip install -e .
|
|
51
|
+
# Install from PyPI (easiest)
|
|
52
|
+
pip install codemap-python
|
|
56
53
|
```
|
|
57
54
|
|
|
58
55
|
**Verify installation:**
|
|
@@ -65,6 +62,13 @@ You should see:
|
|
|
65
62
|
usage: codemap [-h] {analyze,dashboard,open,cache} ...
|
|
66
63
|
```
|
|
67
64
|
|
|
65
|
+
> **For developers:** To modify source code or contribute, clone the repository:
|
|
66
|
+
> ```bash
|
|
67
|
+
> git clone https://github.com/ADITYA-kus/codemap_ai.git
|
|
68
|
+
> cd codemap_ai
|
|
69
|
+
> pip install -e .
|
|
70
|
+
> ```
|
|
71
|
+
|
|
68
72
|
---
|
|
69
73
|
|
|
70
74
|
### Step 2️⃣: Analyze Your First Repository
|
|
@@ -188,8 +192,10 @@ echo "YOUR_TOKEN" | codemap analyze --github https://github.com/owner/repo --tok
|
|
|
188
192
|
|
|
189
193
|
## Directory Structure
|
|
190
194
|
|
|
195
|
+
This is the source code structure for developers. **If you installed via pip, these files are automatically installed in your Python environment.**
|
|
196
|
+
|
|
191
197
|
```
|
|
192
|
-
|
|
198
|
+
codemap_ai/ (source code)
|
|
193
199
|
├── README.md # This file
|
|
194
200
|
├── cli.py # Command-line interface
|
|
195
201
|
├── security_utils.py # Security & secret redaction
|
|
@@ -20,12 +20,8 @@
|
|
|
20
20
|
### Step 1️⃣: Install CodeMap
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
cd codemap_ai
|
|
26
|
-
|
|
27
|
-
# Install as a local package
|
|
28
|
-
pip install -e .
|
|
23
|
+
# Install from PyPI (easiest)
|
|
24
|
+
pip install codemap-python
|
|
29
25
|
```
|
|
30
26
|
|
|
31
27
|
**Verify installation:**
|
|
@@ -38,6 +34,13 @@ You should see:
|
|
|
38
34
|
usage: codemap [-h] {analyze,dashboard,open,cache} ...
|
|
39
35
|
```
|
|
40
36
|
|
|
37
|
+
> **For developers:** To modify source code or contribute, clone the repository:
|
|
38
|
+
> ```bash
|
|
39
|
+
> git clone https://github.com/ADITYA-kus/codemap_ai.git
|
|
40
|
+
> cd codemap_ai
|
|
41
|
+
> pip install -e .
|
|
42
|
+
> ```
|
|
43
|
+
|
|
41
44
|
---
|
|
42
45
|
|
|
43
46
|
### Step 2️⃣: Analyze Your First Repository
|
|
@@ -161,8 +164,10 @@ echo "YOUR_TOKEN" | codemap analyze --github https://github.com/owner/repo --tok
|
|
|
161
164
|
|
|
162
165
|
## Directory Structure
|
|
163
166
|
|
|
167
|
+
This is the source code structure for developers. **If you installed via pip, these files are automatically installed in your Python environment.**
|
|
168
|
+
|
|
164
169
|
```
|
|
165
|
-
|
|
170
|
+
codemap_ai/ (source code)
|
|
166
171
|
├── README.md # This file
|
|
167
172
|
├── cli.py # Command-line interface
|
|
168
173
|
├── security_utils.py # Security & secret redaction
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codemap-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Local Python code analysis tool - understand architecture, dependencies, and call graphs
|
|
5
5
|
Author-email: ADITYA <aditykushwaha69@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -22,8 +22,9 @@ Requires-Python: >=3.10
|
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
Requires-Dist: fastapi>=0.110
|
|
24
24
|
Requires-Dist: uvicorn>=0.23
|
|
25
|
-
Requires-Dist: jinja2>=3.1
|
|
25
|
+
Requires-Dist: jinja2>=3.1.4
|
|
26
26
|
Requires-Dist: requests>=2.31
|
|
27
|
+
Requires-Dist: starlette==0.40.0
|
|
27
28
|
|
|
28
29
|
# CodeMap
|
|
29
30
|
|
|
@@ -47,12 +48,8 @@ Requires-Dist: requests>=2.31
|
|
|
47
48
|
### Step 1️⃣: Install CodeMap
|
|
48
49
|
|
|
49
50
|
```bash
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
cd codemap_ai
|
|
53
|
-
|
|
54
|
-
# Install as a local package
|
|
55
|
-
pip install -e .
|
|
51
|
+
# Install from PyPI (easiest)
|
|
52
|
+
pip install codemap-python
|
|
56
53
|
```
|
|
57
54
|
|
|
58
55
|
**Verify installation:**
|
|
@@ -65,6 +62,13 @@ You should see:
|
|
|
65
62
|
usage: codemap [-h] {analyze,dashboard,open,cache} ...
|
|
66
63
|
```
|
|
67
64
|
|
|
65
|
+
> **For developers:** To modify source code or contribute, clone the repository:
|
|
66
|
+
> ```bash
|
|
67
|
+
> git clone https://github.com/ADITYA-kus/codemap_ai.git
|
|
68
|
+
> cd codemap_ai
|
|
69
|
+
> pip install -e .
|
|
70
|
+
> ```
|
|
71
|
+
|
|
68
72
|
---
|
|
69
73
|
|
|
70
74
|
### Step 2️⃣: Analyze Your First Repository
|
|
@@ -188,8 +192,10 @@ echo "YOUR_TOKEN" | codemap analyze --github https://github.com/owner/repo --tok
|
|
|
188
192
|
|
|
189
193
|
## Directory Structure
|
|
190
194
|
|
|
195
|
+
This is the source code structure for developers. **If you installed via pip, these files are automatically installed in your Python environment.**
|
|
196
|
+
|
|
191
197
|
```
|
|
192
|
-
|
|
198
|
+
codemap_ai/ (source code)
|
|
193
199
|
├── README.md # This file
|
|
194
200
|
├── cli.py # Command-line interface
|
|
195
201
|
├── security_utils.py # Security & secret redaction
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codemap-python"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Local Python code analysis tool - understand architecture, dependencies, and call graphs"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -36,8 +36,9 @@ classifiers = [
|
|
|
36
36
|
dependencies = [
|
|
37
37
|
"fastapi>=0.110",
|
|
38
38
|
"uvicorn>=0.23",
|
|
39
|
-
"jinja2>=3.1",
|
|
39
|
+
"jinja2>=3.1.4",
|
|
40
40
|
"requests>=2.31",
|
|
41
|
+
"starlette==0.40.0",
|
|
41
42
|
]
|
|
42
43
|
|
|
43
44
|
[project.urls]
|
|
@@ -35,6 +35,23 @@ from ui.utils.registry_manager import (
|
|
|
35
35
|
from security_utils import redact_payload, redact_secrets
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
# Custom cache class that doesn't cache (to avoid TypeError with unhashable Request objects)
|
|
39
|
+
class NoCache:
|
|
40
|
+
"""A cache implementation that doesn't cache anything.
|
|
41
|
+
|
|
42
|
+
This prevents Jinja2 from trying to cache templates with unhashable objects
|
|
43
|
+
like the Starlette Request in the context.
|
|
44
|
+
"""
|
|
45
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
|
46
|
+
return default
|
|
47
|
+
|
|
48
|
+
def set(self, key: Any, value: Any, timeout: Any = None) -> None:
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
def clear(self) -> None:
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
38
55
|
PROJECT_ROOT = os.path.dirname(os.path.dirname(__file__))
|
|
39
56
|
ANALYSIS_ROOT = os.path.join(PROJECT_ROOT, "analysis")
|
|
40
57
|
DEFAULT_REPO = os.getenv("CODEMAP_UI_REPO", "testing_repo")
|
|
@@ -50,7 +67,11 @@ _SESSION_WORKSPACE_READY = False
|
|
|
50
67
|
|
|
51
68
|
|
|
52
69
|
app = FastAPI(title="CodeMap UI")
|
|
53
|
-
|
|
70
|
+
templates_dir = os.path.join(os.path.dirname(__file__), "templates")
|
|
71
|
+
templates = Jinja2Templates(directory=templates_dir)
|
|
72
|
+
# Disable Jinja2 template caching to prevent TypeError with unhashable Request objects
|
|
73
|
+
# This avoids issues when Jinja2 tries to cache templates containing the Request context
|
|
74
|
+
templates.env.cache = NoCache()
|
|
54
75
|
app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "static")), name="static")
|
|
55
76
|
SEARCH_INDEX_CACHE: Dict[str, List[Dict[str, Any]]] = {}
|
|
56
77
|
GRAPH_INDEX_CACHE: Dict[str, Dict[str, Any]] = {}
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
const repoSelectEl = document.getElementById("repo-select");
|
|
6
6
|
const addRepoBtnEl = document.getElementById("add-repo-btn");
|
|
7
7
|
const aiSettingsBtnEl = document.getElementById("ai-settings-btn");
|
|
8
|
+
const themeToggleBtnEl = document.getElementById("theme-toggle-btn");
|
|
9
|
+
const themeWhiteOptionEl = document.getElementById("theme-white");
|
|
10
|
+
const themeDarkOptionEl = document.getElementById("theme-dark");
|
|
8
11
|
const repoListModePillEl = document.getElementById("repo-list-mode-pill");
|
|
9
12
|
const treeStatusEl = document.getElementById("tree-status");
|
|
10
13
|
const treeEl = document.getElementById("tree");
|
|
@@ -2014,6 +2017,53 @@
|
|
|
2014
2017
|
}
|
|
2015
2018
|
|
|
2016
2019
|
function bindAiSettingsControls() {
|
|
2020
|
+
// Theme toggle handlers
|
|
2021
|
+
const setTheme = (themeName) => {
|
|
2022
|
+
localStorage.setItem("codemap-theme", themeName);
|
|
2023
|
+
if (themeName === "dark") {
|
|
2024
|
+
document.documentElement.classList.add("dark-theme");
|
|
2025
|
+
document.body.classList.add("dark-theme");
|
|
2026
|
+
if (themeToggleBtnEl) themeToggleBtnEl.textContent = "☀️ Light";
|
|
2027
|
+
if (themeDarkOptionEl) {
|
|
2028
|
+
themeDarkOptionEl.classList.add("active");
|
|
2029
|
+
}
|
|
2030
|
+
if (themeWhiteOptionEl) {
|
|
2031
|
+
themeWhiteOptionEl.classList.remove("active");
|
|
2032
|
+
}
|
|
2033
|
+
} else {
|
|
2034
|
+
document.documentElement.classList.remove("dark-theme");
|
|
2035
|
+
document.body.classList.remove("dark-theme");
|
|
2036
|
+
if (themeToggleBtnEl) themeToggleBtnEl.textContent = "🌙 Dark";
|
|
2037
|
+
if (themeWhiteOptionEl) {
|
|
2038
|
+
themeWhiteOptionEl.classList.add("active");
|
|
2039
|
+
}
|
|
2040
|
+
if (themeDarkOptionEl) {
|
|
2041
|
+
themeDarkOptionEl.classList.remove("active");
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
|
|
2046
|
+
// Initialize theme from localStorage (default is DARK)
|
|
2047
|
+
const savedTheme = localStorage.getItem("codemap-theme") || "dark";
|
|
2048
|
+
setTheme(savedTheme);
|
|
2049
|
+
|
|
2050
|
+
// Theme toggle button (top bar)
|
|
2051
|
+
if (themeToggleBtnEl) {
|
|
2052
|
+
themeToggleBtnEl.addEventListener("click", () => {
|
|
2053
|
+
const isDark = document.documentElement.classList.contains("dark-theme");
|
|
2054
|
+
setTheme(isDark ? "light" : "dark");
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
// Theme option buttons (settings modal)
|
|
2059
|
+
if (themeWhiteOptionEl) {
|
|
2060
|
+
themeWhiteOptionEl.addEventListener("click", () => setTheme("light"));
|
|
2061
|
+
}
|
|
2062
|
+
if (themeDarkOptionEl) {
|
|
2063
|
+
themeDarkOptionEl.addEventListener("click", () => setTheme("dark"));
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
// Original AI settings handlers
|
|
2017
2067
|
if (aiSettingsBtnEl) {
|
|
2018
2068
|
aiSettingsBtnEl.addEventListener("click", async () => {
|
|
2019
2069
|
await openAiSettingsModal();
|
|
@@ -9,6 +9,18 @@
|
|
|
9
9
|
--active-border: #4f84ff;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
html.dark-theme,
|
|
13
|
+
body.dark-theme {
|
|
14
|
+
--bg: #1a1a1a;
|
|
15
|
+
--panel: #252525;
|
|
16
|
+
--line: #404040;
|
|
17
|
+
--text: #e5e5e5;
|
|
18
|
+
--muted: #a0a0a0;
|
|
19
|
+
--accent: #4fa3ff;
|
|
20
|
+
--active-bg: #2a3a4a;
|
|
21
|
+
--active-border: #5fa3ff;
|
|
22
|
+
}
|
|
23
|
+
|
|
12
24
|
* {
|
|
13
25
|
box-sizing: border-box;
|
|
14
26
|
}
|
|
@@ -1200,6 +1212,121 @@ body.modal-open {
|
|
|
1200
1212
|
margin: 10px 0;
|
|
1201
1213
|
}
|
|
1202
1214
|
|
|
1215
|
+
.theme-selector {
|
|
1216
|
+
display: flex;
|
|
1217
|
+
gap: 10px;
|
|
1218
|
+
margin-bottom: 10px;
|
|
1219
|
+
padding: 8px;
|
|
1220
|
+
background: var(--panel);
|
|
1221
|
+
border-radius: 8px;
|
|
1222
|
+
border: 1px solid var(--line);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
.theme-option {
|
|
1226
|
+
flex: 1;
|
|
1227
|
+
display: flex;
|
|
1228
|
+
flex-direction: column;
|
|
1229
|
+
align-items: center;
|
|
1230
|
+
gap: 6px;
|
|
1231
|
+
padding: 12px;
|
|
1232
|
+
border: 2px solid var(--line);
|
|
1233
|
+
border-radius: 8px;
|
|
1234
|
+
background: var(--panel);
|
|
1235
|
+
color: var(--text);
|
|
1236
|
+
cursor: pointer;
|
|
1237
|
+
transition: all 200ms ease;
|
|
1238
|
+
font-size: 12px;
|
|
1239
|
+
font-weight: 500;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.theme-option:hover {
|
|
1243
|
+
border-color: var(--accent);
|
|
1244
|
+
box-shadow: 0 0 0 3px rgba(79, 132, 255, 0.15);
|
|
1245
|
+
transform: translateY(-1px);
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
.theme-option.active {
|
|
1249
|
+
border-color: var(--accent);
|
|
1250
|
+
background: var(--active-bg);
|
|
1251
|
+
color: #0f3f9c;
|
|
1252
|
+
font-weight: 600;
|
|
1253
|
+
box-shadow: 0 0 0 3px rgba(79, 132, 255, 0.2);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
body.dark-theme .theme-option.active {
|
|
1257
|
+
background: #3a4a5f;
|
|
1258
|
+
color: #4fa3ff;
|
|
1259
|
+
border-color: #4fa3ff;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
.theme-icon {
|
|
1263
|
+
font-size: 20px;
|
|
1264
|
+
line-height: 1;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
.theme-label {
|
|
1268
|
+
font-size: 11px;
|
|
1269
|
+
text-transform: uppercase;
|
|
1270
|
+
letter-spacing: 0.04em;
|
|
1271
|
+
font-weight: 600;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
/* Dark theme specific styles */
|
|
1275
|
+
html.dark-theme .topbar,
|
|
1276
|
+
body.dark-theme .topbar {
|
|
1277
|
+
background: #2a2a2a;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
html.dark-theme .card,
|
|
1281
|
+
html.dark-theme .repo-row,
|
|
1282
|
+
html.dark-theme .confirm-card,
|
|
1283
|
+
html.dark-theme .modal-form input,
|
|
1284
|
+
html.dark-theme .modal-form select,
|
|
1285
|
+
html.dark-theme .repo-select,
|
|
1286
|
+
html.dark-theme .repo-btn,
|
|
1287
|
+
html.dark-theme .tab-btn,
|
|
1288
|
+
html.dark-theme .graph-controls select,
|
|
1289
|
+
html.dark-theme .graph-controls input[type="text"],
|
|
1290
|
+
html.dark-theme .search-results,
|
|
1291
|
+
html.dark-theme .graph-node,
|
|
1292
|
+
html.dark-theme .kpi-card,
|
|
1293
|
+
html.dark-theme .risk-file-row,
|
|
1294
|
+
html.dark-theme .risk-target,
|
|
1295
|
+
html.dark-theme .impact-file-row,
|
|
1296
|
+
body.dark-theme .card,
|
|
1297
|
+
body.dark-theme .repo-row,
|
|
1298
|
+
body.dark-theme .confirm-card,
|
|
1299
|
+
body.dark-theme .modal-form input,
|
|
1300
|
+
body.dark-theme .modal-form select,
|
|
1301
|
+
body.dark-theme .repo-select,
|
|
1302
|
+
body.dark-theme .repo-btn,
|
|
1303
|
+
body.dark-theme .tab-btn,
|
|
1304
|
+
body.dark-theme .graph-controls select,
|
|
1305
|
+
body.dark-theme .graph-controls input[type="text"],
|
|
1306
|
+
body.dark-theme .search-results,
|
|
1307
|
+
body.dark-theme .graph-node,
|
|
1308
|
+
body.dark-theme .kpi-card,
|
|
1309
|
+
body.dark-theme .risk-file-row,
|
|
1310
|
+
body.dark-theme .risk-target,
|
|
1311
|
+
body.dark-theme .impact-file-row {
|
|
1312
|
+
background: var(--panel);
|
|
1313
|
+
color: var(--text);
|
|
1314
|
+
border-color: var(--line);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
html.dark-theme #symbol-search-input,
|
|
1318
|
+
body.dark-theme #symbol-search-input {
|
|
1319
|
+
background: var(--panel);
|
|
1320
|
+
color: var(--text);
|
|
1321
|
+
border-color: var(--line);
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
html.dark-theme .toast,
|
|
1325
|
+
body.dark-theme .toast {
|
|
1326
|
+
background: #2a2a2a;
|
|
1327
|
+
color: #e5e5e5;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1203
1330
|
@media (max-width: 1000px) {
|
|
1204
1331
|
.layout {
|
|
1205
1332
|
grid-template-columns: 1fr;
|
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>CodeMap UI</title>
|
|
7
7
|
<link rel="stylesheet" href="/static/styles.css" />
|
|
8
|
+
<script>
|
|
9
|
+
// Apply theme IMMEDIATELY on page load, before rendering
|
|
10
|
+
(function() {
|
|
11
|
+
try {
|
|
12
|
+
const theme = localStorage.getItem("codemap-theme") || "dark";
|
|
13
|
+
if (theme === "dark") {
|
|
14
|
+
document.documentElement.classList.add("dark-theme");
|
|
15
|
+
}
|
|
16
|
+
} catch (e) {
|
|
17
|
+
// fallback: use dark as default
|
|
18
|
+
document.documentElement.classList.add("dark-theme");
|
|
19
|
+
}
|
|
20
|
+
})();
|
|
21
|
+
</script>
|
|
8
22
|
</head>
|
|
9
23
|
<body>
|
|
10
24
|
<header class="topbar">
|
|
@@ -18,6 +32,7 @@
|
|
|
18
32
|
<div class="workspace-controls">
|
|
19
33
|
<select id="repo-select" class="repo-select"></select>
|
|
20
34
|
<button id="add-repo-btn" class="repo-btn" type="button">+ Add repo...</button>
|
|
35
|
+
<button id="theme-toggle-btn" class="repo-btn" type="button" title="Toggle theme">🌙 Dark</button>
|
|
21
36
|
<button id="ai-settings-btn" class="repo-btn" type="button" onclick="var m=document.getElementById('ai-settings-modal'); if(m){ m.classList.remove('hidden'); document.body.classList.add('modal-open'); }">Settings</button>
|
|
22
37
|
<span id="repo-list-mode-pill" class="repo-badge">Session Mode</span>
|
|
23
38
|
</div>
|
|
@@ -73,6 +88,21 @@
|
|
|
73
88
|
<div id="ai-settings-modal" class="confirm-modal hidden">
|
|
74
89
|
<div class="confirm-card settings-card">
|
|
75
90
|
<div class="section-title">Settings</div>
|
|
91
|
+
<div class="path">Appearance</div>
|
|
92
|
+
<label class="path">
|
|
93
|
+
<span>Theme</span>
|
|
94
|
+
</label>
|
|
95
|
+
<div class="theme-selector">
|
|
96
|
+
<button id="theme-white" class="theme-option" type="button" data-theme="light">
|
|
97
|
+
<span class="theme-icon">☀️</span>
|
|
98
|
+
<span class="theme-label">Light</span>
|
|
99
|
+
</button>
|
|
100
|
+
<button id="theme-dark" class="theme-option active" type="button" data-theme="dark">
|
|
101
|
+
<span class="theme-icon">🌙</span>
|
|
102
|
+
<span class="theme-label">Dark</span>
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="divider"></div>
|
|
76
106
|
<div class="path">General</div>
|
|
77
107
|
<label class="path">
|
|
78
108
|
<input id="ai-settings-remember-repos" type="checkbox" />
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|