Spaces:
Running
Running
| import os | |
| import re | |
| import sys | |
| from graphviz import Digraph | |
| import esprima | |
| def detect_file_dependencies(root_dir): | |
| """ | |
| Menelusuri semua file dalam root_dir dan mendeteksi dependency sederhana. | |
| Jika sebuah file (HTML) menautkan file lain (JS/CSS) melalui tag <script> atau <link>, | |
| maka dependency tersebut dicatat. | |
| """ | |
| dep_graph = {} | |
| for subdir, _, files in os.walk(root_dir): | |
| for file in files: | |
| ext = os.path.splitext(file)[1].lower() | |
| if ext in ['.html', '.js', '.css']: | |
| filepath = os.path.join(subdir, file) | |
| try: | |
| with open(filepath, 'r', encoding='utf-8', errors='ignore') as f: | |
| content = f.read() | |
| except Exception as e: | |
| print(f"Error reading {filepath}: {e}") | |
| continue | |
| dependencies = [] | |
| if ext == '.html': | |
| scripts = re.findall(r'<script\s+[^>]*src=["\'](.*?)["\']', content, re.IGNORECASE) | |
| links = re.findall(r'<link\s+[^>]*href=["\'](.*?)["\']', content, re.IGNORECASE) | |
| dependencies.extend(scripts) | |
| dependencies.extend(links) | |
| dep_graph[filepath] = dependencies | |
| return dep_graph | |
| def build_file_dependency_flowchart(dep_graph, output_file='results/project_file_dependencies'): | |
| """ | |
| Membuat diagram flowchart dependency antar file menggunakan Graphviz. | |
| Jika string dependency (misalnya, 'script.js') ditemukan dalam nama file lain, dibuat edge. | |
| """ | |
| dot = Digraph(comment='Project File Dependencies') | |
| for file in dep_graph: | |
| dot.node(file, os.path.basename(file)) | |
| for file, deps in dep_graph.items(): | |
| for dep in deps: | |
| for candidate in dep_graph: | |
| if dep in os.path.basename(candidate): | |
| dot.edge(file, candidate) | |
| dot.render(output_file, view=True) | |
| print(f"Diagram dependency file disimpan sebagai {output_file}.pdf") | |
| def generate_full_js_flowchart(js_file): | |
| """ | |
| Menghasilkan flowchart yang mencoba mengidentifikasi seluruh _syntax_ yang mempengaruhi | |
| alur kontrol pada file JavaScript dengan mengurai AST menggunakan esprima. | |
| Node-node yang dihasilkan mencakup FunctionDeclaration, IfStatement, loop, SwitchStatement, | |
| ReturnStatement, CallExpression, dan jenis node lainnya. | |
| """ | |
| try: | |
| with open(js_file, 'r', encoding='utf-8') as f: | |
| code = f.read() | |
| except Exception as e: | |
| print(f"Error reading {js_file}: {e}") | |
| return None | |
| try: | |
| ast = esprima.parseScript(code, tolerant=True) | |
| except Exception as e: | |
| print(f"Error parsing {js_file}: {e}") | |
| return None | |
| flowchart = Digraph(comment=f'Full JS Flowchart: {os.path.basename(js_file)}') | |
| node_counter = 0 | |
| def new_node(label): | |
| nonlocal node_counter | |
| node_id = f"node{node_counter}" | |
| node_counter += 1 | |
| flowchart.node(node_id, label) | |
| return node_id | |
| def traverse_full(node, parent_node=None): | |
| if isinstance(node, dict): | |
| node_type = node.get('type') | |
| current_node = None | |
| if node_type == 'FunctionDeclaration': | |
| func_name = node.get('id', {}).get('name', 'anonymous') | |
| current_node = new_node(f'Function: {func_name}') | |
| elif node_type == 'IfStatement': | |
| current_node = new_node('If Statement') | |
| elif node_type in ['ForStatement', 'WhileStatement', 'DoWhileStatement']: | |
| current_node = new_node(node_type) | |
| elif node_type == 'SwitchStatement': | |
| current_node = new_node('Switch Statement') | |
| elif node_type == 'ReturnStatement': | |
| current_node = new_node('Return') | |
| elif node_type == 'CallExpression': | |
| callee = node.get('callee') | |
| if callee and callee.get('type') == 'Identifier': | |
| current_node = new_node(f'Call: {callee.get("name")}') | |
| else: | |
| current_node = new_node(node_type) | |
| if parent_node and current_node: | |
| flowchart.edge(parent_node, current_node) | |
| new_parent = current_node if current_node else parent_node | |
| for key, value in node.items(): | |
| if key in ['loc', 'range', 'raw']: | |
| continue | |
| traverse_full(value, parent_node=new_parent) | |
| elif isinstance(node, list): | |
| for item in node: | |
| traverse_full(item, parent_node=parent_node) | |
| traverse_full(ast.toDict(), parent_node=None) | |
| return flowchart | |
| def build_all_full_js_flowcharts(root_dir, output_folder='results/full_js_flowcharts'): | |
| """ | |
| Menelusuri seluruh file dalam root_dir, dan untuk setiap file JS menghasilkan flowchart | |
| lengkap dari seluruh syntax yang mempengaruhi alur. Flowchart disimpan di output_folder. | |
| """ | |
| if not os.path.exists(output_folder): | |
| os.makedirs(output_folder) | |
| for subdir, _, files in os.walk(root_dir): | |
| for file in files: | |
| ext = os.path.splitext(file)[1].lower() | |
| if ext == '.js': | |
| js_file = os.path.join(subdir, file) | |
| print(f"Memproses {js_file} untuk flowchart lengkap...") | |
| flowchart = generate_full_js_flowchart(js_file) | |
| if flowchart: | |
| base_name = os.path.splitext(os.path.basename(js_file))[0] | |
| output_name = os.path.join(output_folder, base_name + '_full_flowchart') | |
| flowchart.render(output_name, view=False) | |
| print(f"Flowchart lengkap untuk {js_file} disimpan sebagai {output_name}.pdf") | |
| if __name__ == '__main__': | |
| root_directory = '/content/drive/MyDrive/Developer/Project/Competition/Alhazen Coding Quest 20 Days Ramadhan Challenge/FINAL PROJECT' | |
| dependency_graph = detect_file_dependencies(root_directory) | |
| print("Dependency Graph Antar File:") | |
| for file, deps in dependency_graph.items(): | |
| print(f"{file}: {deps}") | |
| build_file_dependency_flowchart(dependency_graph) | |
| build_all_full_js_flowcharts(root_directory) | |
| sys.stdout.flush() | |
| input("Tekan Enter untuk keluar...") |