Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import json | |
| from rule_extractor import get_rules_from_url, format_rules_for_display | |
| from doc_analyzer import analyze_document | |
| def combine_rules(url_rules, pasted_rules): | |
| """Combine URL-extracted rules and manually pasted rules""" | |
| combined_rules = "" | |
| # Check if URL rules are in JSON format and convert if needed | |
| if url_rules and (url_rules.strip().startswith('[') or url_rules.strip().startswith('{')): | |
| try: | |
| # Try to parse as JSON | |
| rules_data = json.loads(url_rules) | |
| if isinstance(rules_data, list) and len(rules_data) > 0: | |
| rules_data = rules_data[0] | |
| # Format the rules | |
| url_rules = format_rules_for_display(rules_data) | |
| except Exception as e: | |
| # If parsing fails, use as is | |
| pass | |
| # Add URL-extracted rules if available | |
| if url_rules: | |
| combined_rules += url_rules | |
| # Add pasted rules if available | |
| if pasted_rules: | |
| if url_rules: # If we already have URL rules, add a separator | |
| combined_rules += "\n\n## Additional Manually Pasted Rules\n\n" + pasted_rules | |
| else: # If no URL rules, just use pasted rules | |
| combined_rules = "# Manually Pasted Rules\n\n" + pasted_rules | |
| return combined_rules | |
| st.set_page_config( | |
| page_title="FormatReview", | |
| page_icon="🔎", | |
| layout="wide", | |
| ) | |
| st.title("FormatReview") | |
| st.markdown("Analyze your manuscript against any journal's formatting guidelines.") | |
| # Initialize session state for storing rules | |
| if "rules" not in st.session_state: | |
| st.session_state.rules = None | |
| if "results" not in st.session_state: | |
| st.session_state.results = None | |
| if "url_rules" not in st.session_state: | |
| st.session_state.url_rules = None | |
| if "pasted_rules" not in st.session_state: | |
| st.session_state.pasted_rules = None | |
| # Create tabs | |
| tab1, tab2, tab3 = st.tabs(["Document Upload", "Formatting Rules", "Analysis Results"]) | |
| with tab1: | |
| # --- UI Components --- | |
| uploaded_file = st.file_uploader("Upload your manuscript (PDF or DOCX)", type=["pdf", "docx"]) | |
| # Rules input section | |
| st.subheader("Formatting Rules") | |
| st.markdown("You can provide formatting rules by URL, paste them directly, or both.") | |
| # URL input | |
| journal_url = st.text_input("Enter the URL to the journal's 'Instructions for Authors' page (optional if pasting rules)") | |
| # Pasted rules input | |
| pasted_rules = st.text_area( | |
| "Or paste formatting rules directly (optional if providing URL)", | |
| height=200, | |
| placeholder="Paste journal formatting guidelines here..." | |
| ) | |
| if st.button("Analyze Document"): | |
| if uploaded_file is None: | |
| st.error("Please upload your manuscript.") | |
| elif not journal_url and not pasted_rules: | |
| st.error("Please either enter the journal's URL or paste formatting rules.") | |
| else: | |
| # Initialize combined rules | |
| combined_rules = "" | |
| # Extract rules from URL if provided | |
| if journal_url: | |
| with st.spinner("Extracting rules from URL..."): | |
| url_rules = get_rules_from_url(journal_url) | |
| st.session_state.url_rules = url_rules | |
| if url_rules: | |
| combined_rules += url_rules | |
| # Add pasted rules if provided | |
| if pasted_rules: | |
| st.session_state.pasted_rules = pasted_rules | |
| if journal_url: # If we already have URL rules, combine them | |
| # Make sure URL rules are formatted before combining | |
| if st.session_state.url_rules and ( | |
| st.session_state.url_rules.strip().startswith('[') or | |
| st.session_state.url_rules.strip().startswith('{') | |
| ): | |
| try: | |
| # Try to parse as JSON | |
| rules_data = json.loads(st.session_state.url_rules) | |
| if isinstance(rules_data, list) and len(rules_data) > 0: | |
| rules_data = rules_data[0] | |
| # Format and update the URL rules | |
| formatted_url_rules = format_rules_for_display(rules_data) | |
| st.session_state.url_rules = formatted_url_rules | |
| except Exception as e: | |
| # If parsing fails, use as is | |
| pass | |
| combined_rules = combine_rules(st.session_state.url_rules, pasted_rules) | |
| else: # If no URL rules, just use pasted rules | |
| combined_rules = "# Manually Pasted Rules\n\n" + pasted_rules | |
| # Store the combined rules | |
| st.session_state.rules = combined_rules | |
| # Analyze the document | |
| with st.spinner("Analyzing document..."): | |
| st.session_state.results = analyze_document(uploaded_file, st.session_state.rules) | |
| st.success("Analysis complete! View the results in the 'Analysis Results' tab.") | |
| with tab2: | |
| st.header("Formatting Rules") | |
| if st.session_state.url_rules or st.session_state.pasted_rules: | |
| # Display URL-extracted rules if available | |
| if st.session_state.url_rules: | |
| st.subheader("Rules Extracted from URL") | |
| st.markdown(st.session_state.url_rules) | |
| # Display pasted rules if available | |
| if st.session_state.pasted_rules: | |
| st.subheader("Manually Pasted Rules") | |
| st.text_area("", value=st.session_state.pasted_rules, height=150, disabled=True) | |
| # Display combined rules used for analysis | |
| if st.session_state.rules and (st.session_state.url_rules and st.session_state.pasted_rules): | |
| st.subheader("Combined Rules (Used for Analysis)") | |
| # The combined rules should already be formatted, but check just in case | |
| if isinstance(st.session_state.rules, str) and ( | |
| st.session_state.rules.strip().startswith('[') or | |
| st.session_state.rules.strip().startswith('{') | |
| ): | |
| try: | |
| # Try to parse as JSON | |
| rules_data = json.loads(st.session_state.rules) | |
| if isinstance(rules_data, list) and len(rules_data) > 0: | |
| rules_data = rules_data[0] | |
| # Format and display the rules | |
| formatted_rules = format_rules_for_display(rules_data) | |
| st.markdown(formatted_rules) | |
| except Exception as e: | |
| # If parsing fails, just display as is | |
| st.markdown(st.session_state.rules) | |
| else: | |
| # If not JSON, just display as is | |
| st.markdown(st.session_state.rules) | |
| else: | |
| st.info("Provide formatting rules via URL or direct input to view them here.") | |
| with tab3: | |
| st.header("Analysis Results") | |
| if st.session_state.results: | |
| results = st.session_state.results | |
| if "error" in results: | |
| st.error(results["error"]) | |
| else: | |
| # Display summary | |
| st.subheader("Summary") | |
| summary = results.get("summary", {}) | |
| st.write(f"**Overall Assessment**: {summary.get('overall_assessment', 'N/A')}") | |
| st.write(f"**Total Issues**: {summary.get('total_issues', 'N/A')}") | |
| st.write(f"**Critical Issues**: {summary.get('critical_issues', 'N/A')}") | |
| st.write(f"**Warning Issues**: {summary.get('warning_issues', 'N/A')}") | |
| # Display recommendations | |
| st.subheader("Recommendations") | |
| recommendations = results.get("recommendations", []) | |
| if recommendations: | |
| for rec in recommendations: | |
| st.write(f"- {rec}") | |
| else: | |
| st.write("No recommendations.") | |
| # Display detailed report | |
| st.subheader("Detailed Report") | |
| issues = results.get("issues", []) | |
| if issues: | |
| for issue in issues: | |
| severity = issue.get('severity', 'N/A').lower() | |
| message = f"**{issue.get('severity', 'N/A').upper()}**: {issue.get('message', 'N/A')}" | |
| if severity == 'critical': | |
| st.error(message) | |
| elif severity == 'warning': | |
| st.warning(message) | |
| elif severity == 'info': | |
| st.info(message) | |
| else: | |
| st.success(message) | |
| st.write(f"**Location**: {issue.get('location', 'N/A')}") | |
| st.write(f"**Suggestion**: {issue.get('suggestion', 'N/A')}") | |
| st.divider() | |
| else: | |
| st.success("No issues found.") | |
| else: | |
| st.info("Analyze a document to view results here.") | |