Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
df751bb
feat(backend): add rule options for empty section structure with avai…
void0xf Apr 27, 2026
fb1257b
feat(backend): enhance validation severity normalization to include I…
void0xf Apr 27, 2026
9970dac
refactor(backend): update EmptySectionStructureRule to use options fo…
void0xf Apr 27, 2026
0af0a4b
refactor(backend): enhance ThesisValidatorService to support empty se…
void0xf Apr 27, 2026
e934123
refactor(backend): add configuration options for EmptySectionStructur…
void0xf Apr 27, 2026
eada51b
refactor(backend): update GetAvailableRules to filter based on EmptyS…
void0xf Apr 27, 2026
5f447df
refactor(tests): add unit tests for EmptySectionStructureRule configu…
void0xf Apr 27, 2026
09b093d
refactor(rules): abstract rule options into base rule option base class
void0xf Apr 27, 2026
49449d5
feat(rules): introduce centralized rule configuration service
void0xf Apr 27, 2026
d9dc553
refactor(backend): integrate configuration service into pipeline and …
void0xf Apr 27, 2026
0f857ee
feat(rules): implement dynamic configuration for font family rule
void0xf Apr 27, 2026
32ee096
refactor(rules): remove deprecated figure caption rule and unused fon…
void0xf Apr 27, 2026
3e1defa
feat(rules): implement dynamic configuration for heading style usage …
void0xf Apr 27, 2026
f89a82c
feat(rules): add HierarchyDepthRule with configuration options and va…
void0xf Apr 27, 2026
8d3050a
feat(rules): add LineSpacingDependencyRule with configuration options…
void0xf Apr 27, 2026
80c43c6
feat: Implement List Punctuation and Indentation Consistency Rules
void0xf Apr 27, 2026
62f3501
feat(rules): add Missing Figure Caption Rule with configuration optio…
void0xf Apr 27, 2026
9d5a302
refactor(tests): remove deprecated figure caption rules test file
void0xf Apr 27, 2026
0402e57
refactor(rules): update core rule definition and validation result fa…
void0xf Apr 27, 2026
98192cf
feat(rules): implement dynamic configuration for table of contents rules
void0xf Apr 27, 2026
40f1c17
feat(rules): implement dynamic configuration for paragraph formatting…
void0xf Apr 27, 2026
c44555d
feat(rules): implement dynamic configuration for titles rule
void0xf Apr 27, 2026
7928f31
refactor(backend): wire up legacy formatting rule configurations and …
void0xf Apr 27, 2026
946ba09
feat(frontend): update validation models to reflect rule updates
void0xf Apr 27, 2026
1aaef03
feat(rules): add FigureCaptionFormatRule and associated options with …
void0xf Apr 28, 2026
4198cf2
feat(tests): add RuleConfigurationTestSupport and RecordingRule for v…
void0xf Apr 28, 2026
47e6d04
feat(rules): add FigureCaptionPositionRule with configuration options…
void0xf Apr 28, 2026
9255058
feat(rules): add GrammarRule with configuration options and tests
void0xf Apr 28, 2026
234d968
feat(rules): add configuration options for FigureCaptionPositionRule,…
void0xf Apr 28, 2026
c1fe2cf
refactor(models): clean up validation models and update app configura…
void0xf Apr 29, 2026
bc16a41
feat(framework): introduce modern validation rule primitives
void0xf Apr 29, 2026
22a2aa1
feat(engine): add structured document content analysis
void0xf Apr 29, 2026
afabd7d
feat(engine): implement modern rule orchestration
void0xf Apr 29, 2026
8d6dd2a
refactor(rules): migrate FontFamilyRule to modern framework
void0xf Apr 29, 2026
2ece5a8
refactor(rules): migrate EmptySectionStructureRule to modern framework
void0xf Apr 29, 2026
f96332f
refactor(core): bridge legacy validation services with modern framework
void0xf Apr 29, 2026
64c3d15
refactor(api): upgrade endpoints to modern execution pipeline
void0xf Apr 29, 2026
05ea152
refactor(bootstrap): register modern validation components in DI
void0xf Apr 29, 2026
da4066b
refactor(formatting): implement ModernFormattingResolver for font fam…
void0xf Apr 29, 2026
5ccef26
refactor(engine): remove legacy analysis, structure, and skipping ser…
void0xf Apr 30, 2026
8247373
feat(engine): introduce modern structure, skipping, and formatting se…
void0xf Apr 30, 2026
f102c29
refactor(options): consolidate rule options into strongly-typed models
void0xf Apr 30, 2026
824d695
refactor(rules): migrate layout and formatting rules to modern framework
void0xf Apr 30, 2026
a377733
refactor(rules): migrate structural rules (Figures, ToC, Lists)
void0xf Apr 30, 2026
593a7ca
feat(api): rewire Endpoints and DI for the modern validation engine
void0xf Apr 30, 2026
47008d7
feat(frontend): adapt UI to the normalized validation results structure
void0xf Apr 30, 2026
a9276c9
refactor(engine): final cleanups, test alignments, and untouched rules
void0xf Apr 30, 2026
5a1ff5d
Add domain models and validation response schemas
void0xf Apr 30, 2026
b29fb54
Add Rule Framework core interfaces and primitives
void0xf Apr 30, 2026
2677c25
Add Application layer logic for thesis validation
void0xf Apr 30, 2026
882a407
Add Document Processing content and context extraction
void0xf Apr 30, 2026
cd74e24
Add formatting, list, and paragraph analyzer services
void0xf Apr 30, 2026
44a35b5
Add detectors for figures, code blocks, and table of contents
void0xf Apr 30, 2026
0a37b2c
Add LanguageTool infrastructure client
void0xf Apr 30, 2026
9728a2a
Add Formatting validation rules
void0xf Apr 30, 2026
710da83
Add Layout validation rules
void0xf Apr 30, 2026
fe63869
Add Structure validation rules
void0xf Apr 30, 2026
88cb0a1
Add Language validation rules
void0xf Apr 30, 2026
bd35544
Remove legacy ModernServices and flat Rules structure
void0xf Apr 30, 2026
3f7507d
Add Document Annotation formatting components
void0xf Apr 30, 2026
1f4a07f
Update API endpoints and dependency injection for new domain model
void0xf Apr 30, 2026
0908160
Update tests to align with new application and rule components
void0xf Apr 30, 2026
90ca1fe
refactor: recovered remvoed files
void0xf Apr 30, 2026
89b1610
chore: update cors/configs and remove unused http file
void0xf Apr 30, 2026
98d8ab6
refactor(core): extract DocumentLocation and ParagraphIndexKind into …
void0xf Apr 30, 2026
b49478e
refactor(core): rename ValidationResult to ValidationIssue in domain …
void0xf Apr 30, 2026
acfaba1
refactor(api): restructure documents endpoint into vertical slice wit…
void0xf Apr 30, 2026
eab2fcb
refactor(host): extract service registration and middleware pipeline …
void0xf Apr 30, 2026
b42f235
test: align suite with ValidationIssue rename and vertical slice arch…
void0xf Apr 30, 2026
a8f25eb
refactor: redesinged main folder sturcture
void0xf Apr 30, 2026
8444e9a
chore: add CI workflow for frontend and backend builds and tests
void0xf Apr 30, 2026
8c71b12
feat(api): add Postman collection for Thesis Validator API testing
void0xf Apr 30, 2026
50724d7
feat(docs): add new screenshots for MainPage, RuleSettings, and Valid…
void0xf Apr 30, 2026
e20d9de
refactor(docs): update README with detailed app features and tech sta…
void0xf Apr 30, 2026
3605366
fix: update .gitignore to include additional dotnet-home directory an…
void0xf Apr 30, 2026
edb98b3
refactor: clean up .gitignore and remove unused test document
void0xf Apr 30, 2026
6888a2b
refactor: remove unused font and test document references from projec…
void0xf Apr 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
frontend:
name: Frontend build
runs-on: ubuntu-latest

defaults:
run:
working-directory: src/frontend

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: src/frontend/package-lock.json

- name: Install dependencies
run: npm ci

- name: Build frontend
run: npm run build

backend:
name: Backend build and tests
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x

- name: Restore backend
run: dotnet restore ThesisValidator.sln

- name: Build backend
run: dotnet build src/backend/ThesisValidator.Api.csproj --configuration Release --no-restore

- name: Run backend tests
run: dotnet test tests/backend.Tests/ThesisValidator.Api.Tests.csproj --configuration Release --no-restore --verbosity normal
86 changes: 12 additions & 74 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,75 +1,13 @@
/backend.Tests/bin
tests/backend.Tests/bin
/.dotnet/
/.dotnet-home/
/.codex-*
/.idea
/backend.Tests/obj
/backend/.idea
/backend/bin
/backend/obj
backend/output/hello_validated_20260201_085806.docx
backend/output/test_validated_20260130_023857.zip
backend/output/test_validated_20260131_190122.docx
backend/output/test_validated_20260201_085634.docx
backend/output/test_validated_20260130_023857/\[Content_Types].xml
backend/output/test_validated_20260130_023857/hello.docx
backend/output/test_validated_20260130_023857/_rels/.rels
backend/output/test_validated_20260130_023857/customXml/item1.xml
backend/output/test_validated_20260130_023857/customXml/item2.xml
backend/output/test_validated_20260130_023857/customXml/item3.xml
backend/output/test_validated_20260130_023857/customXml/item4.xml
backend/output/test_validated_20260130_023857/customXml/itemProps1.xml
backend/output/test_validated_20260130_023857/customXml/itemProps2.xml
backend/output/test_validated_20260130_023857/customXml/itemProps3.xml
backend/output/test_validated_20260130_023857/customXml/itemProps4.xml
backend/output/test_validated_20260130_023857/customXml/_rels/item1.xml.rels
backend/output/test_validated_20260130_023857/customXml/_rels/item2.xml.rels
backend/output/test_validated_20260130_023857/customXml/_rels/item3.xml.rels
backend/output/test_validated_20260130_023857/customXml/_rels/item4.xml.rels
backend/output/test_validated_20260130_023857/docProps/app.xml
backend/output/test_validated_20260130_023857/docProps/core.xml
backend/output/test_validated_20260130_023857/docProps/custom.xml
backend/output/test_validated_20260130_023857/hello/\[Content_Types].xml
backend/output/test_validated_20260130_023857/hello/_rels/.rels
backend/output/test_validated_20260130_023857/hello/customXml/item1.xml
backend/output/test_validated_20260130_023857/hello/customXml/itemProps1.xml
backend/output/test_validated_20260130_023857/hello/customXml/_rels/item1.xml.rels
backend/output/test_validated_20260130_023857/hello/docProps/app.xml
backend/output/test_validated_20260130_023857/hello/docProps/core.xml
backend/output/test_validated_20260130_023857/hello/word/document.xml
backend/output/test_validated_20260130_023857/hello/word/fontTable.xml
backend/output/test_validated_20260130_023857/hello/word/settings.xml
backend/output/test_validated_20260130_023857/hello/word/styles.xml
backend/output/test_validated_20260130_023857/hello/word/webSettings.xml
backend/output/test_validated_20260130_023857/hello/word/_rels/document.xml.rels
backend/output/test_validated_20260130_023857/hello/word/theme/theme1.xml
backend/output/test_validated_20260130_023857/word/comments.xml
backend/output/test_validated_20260130_023857/word/document.xml
backend/output/test_validated_20260130_023857/word/endnotes.xml
backend/output/test_validated_20260130_023857/word/fontTable.xml
backend/output/test_validated_20260130_023857/word/footer1.xml
backend/output/test_validated_20260130_023857/word/footnotes.xml
backend/output/test_validated_20260130_023857/word/numbering.xml
backend/output/test_validated_20260130_023857/word/settings.xml
backend/output/test_validated_20260130_023857/word/styles.xml
backend/output/test_validated_20260130_023857/word/webSettings.xml
backend/output/test_validated_20260130_023857/word/_rels/document.xml.rels
backend/output/test_validated_20260130_023857/word/glossary/document.xml
backend/output/test_validated_20260130_023857/word/glossary/fontTable.xml
backend/output/test_validated_20260130_023857/word/glossary/settings.xml
backend/output/test_validated_20260130_023857/word/glossary/styles.xml
backend/output/test_validated_20260130_023857/word/glossary/webSettings.xml
backend/output/test_validated_20260130_023857/word/glossary/_rels/document.xml.rels
backend/output/test_validated_20260130_023857/word/media/image1.png
backend/output/test_validated_20260130_023857/word/media/image2.png
backend/output/test_validated_20260130_023857/word/media/image3.png
backend/output/test_validated_20260130_023857/word/theme/theme1.xml
backend/output/hello.docx
backend.Tests/Fixtures/test.docx
/backend.Tests/Fixtures
frontend/.vscode/extensions.json
frontend/.vscode/launch.json
frontend/.vscode/tasks.json
frontend/.vscode/extensions.json
frontend/.vscode/launch.json
frontend/.vscode/tasks.json
presentation/architecture.md
presentation/architecture.pdf
presentation/architecture.pptx
tests/backend.Tests/obj
src/backend/.idea
src/backend/bin
src/backend/obj
src/backend/output/
src/frontend/.vscode/extensions.json
src/frontend/.vscode/launch.json
src/frontend/.vscode/tasks.json
199 changes: 199 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Thesis Validator

A full-stack web app for validating `.docx` thesis documents against formatting, layout, structure, and grammar rules.

## Demo

Screenshots from the current app:

![Main page](docs/screenshots/MainPage.png)

![Rule settings](docs/screenshots/RuleSettings.png)

![Validation results](docs/screenshots/ValidationResult.png)

## Overview

Thesis Validator helps students check Word thesis documents before submission. Users upload a `.docx` file, choose validation rules, review grouped issues, and can download an annotated copy with comments placed in the document.

I built this project to practice a realistic full-stack workflow: document parsing, rule-based validation, API design, frontend state management, and automated backend testing. The app is useful for students who want a faster way to catch formatting and structure problems that are easy to miss during manual review.

## Features

- Upload and validate `.docx` thesis files from an Angular interface.
- Select validation rules by category before running a check.
- Validate formatting rules such as font family, single spaces, title punctuation, and text justification.
- Check layout and structure rules including paragraph spacing, indentation, heading depth, table of contents, empty sections, and figure captions.
- Run grammar checks through a local LanguageTool service.
- Skip front matter before the table of contents and skip Word text boxes when needed.
- View validation results grouped by category with error and warning counts.
- Download an annotated `.docx` file with comments marking detected issues.

## Tech Stack

- Frontend: Angular 18, TypeScript, RxJS, Tailwind CSS, lucide-angular
- Backend: ASP.NET Core 9, C#, Minimal APIs, Swagger/OpenAPI
- Database: None
- Auth: None
- Testing: xUnit, Moq, coverlet, Angular/Karma test setup
- Deployment: GitHub Actions CI for frontend build and backend build/tests
- Other: Docker Compose, LanguageTool, DocumentFormat.OpenXml, Postman collection

## Getting Started

### 1. Clone the repository

```bash
git clone <repository-url>
cd thesis-validator
```

### 2. Install dependencies

Install the frontend packages:

```bash
cd src/frontend
npm ci
```

Restore the .NET solution from the repository root:

```bash
cd ../..
dotnet restore ThesisValidator.sln
```

### 3. Configure environment variables

The default local configuration works for basic development. The backend reads its local settings from `src/backend/appsettings.json` and `src/backend/appsettings.Development.json`.

Start the local grammar service before using grammar validation:

```bash
docker compose -f docker/docker-compose.yml up -d
```

### 4. Run the development servers

Start the backend API from the repository root:

```bash
dotnet run --project src/backend/ThesisValidator.Api.csproj --launch-profile http
```

In a second terminal, start the Angular frontend:

```bash
cd src/frontend
npm start
```

### 5. Open the app locally

- Frontend: `http://localhost:4200`
- Backend API: `http://localhost:5213`
- Swagger UI: `http://localhost:5213/swagger`
- LanguageTool service: `http://localhost:8010`

The Angular dev server proxies `/api` requests to `http://localhost:5213` through `src/frontend/proxy.conf.json`.

## Environment Variables

| Variable | Purpose | Required |
|---|---|---|
| `ASPNETCORE_ENVIRONMENT` | Sets the backend environment. The launch profile sets this to `Development` locally. | No |
| `LanguageTool__BaseUrl` | Overrides the LanguageTool service URL. Defaults to `http://localhost:8010`. | No |
| `Cors__AllowedOrigins__0` | Allows a frontend origin outside the default development origin. Defaults to `http://localhost:4200` in development. | No |

No secrets are required for basic local setup.

## Available Scripts

Frontend commands from `src/frontend/package.json`:

```bash
npm start
npm run build
npm run watch
npm test
```

Backend and solution commands:

```bash
dotnet restore ThesisValidator.sln
dotnet build src/backend/ThesisValidator.Api.csproj
dotnet test tests/backend.Tests/ThesisValidator.Api.Tests.csproj
dotnet run --project src/backend/ThesisValidator.Api.csproj --launch-profile http
```

Local service command:

```bash
docker compose -f docker/docker-compose.yml up -d
```

## Project Structure

```text
.
|-- .github/workflows/ci.yml
|-- docker/docker-compose.yml
|-- docs/screenshots/
|-- src/
| |-- backend/
| | |-- Annotation/
| | |-- Application/Validation/
| | |-- DocumentProcessing/
| | |-- Endpoints/Documents/
| | |-- Infrastructure/LanguageTool/
| | |-- Rules/
| | |-- Program.cs
| | `-- ThesisValidator.Api.csproj
| `-- frontend/
| |-- src/app/components/
| |-- src/app/models/
| |-- src/app/services/
| |-- proxy.conf.json
| `-- package.json
|-- tests/backend.Tests/
|-- ThesisValidator.postman_collection.json
`-- ThesisValidator.sln
```

## Architecture / Implementation Notes

The backend uses ASP.NET Core Minimal APIs. Document routes are grouped under `/api/documents` and include endpoints for validation, annotated downloads, available rules, and health checks.

Validation is rule-based. Each rule implements the shared validation rule framework and is registered through dependency injection by scanning the backend assembly. Rules are grouped around formatting, layout, structure, and language checks.

Document processing uses `DocumentFormat.OpenXml` to inspect Word documents, extract text, resolve formatting, detect headings, analyze lists, detect figure captions, and apply comments to annotated output files.

Grammar validation calls a local LanguageTool service through an injected HTTP client. Docker Compose provides the service for local development.

The Angular frontend uses standalone components, signals, computed state, and a `ValidationService` for API calls. The main app state moves between upload, validating, and results views. Validation results are normalized on the client before rendering.

The repository includes backend tests with xUnit and fixture `.docx` files. GitHub Actions builds the Angular frontend and runs the backend build and tests on pushes and pull requests to `main`.

## What I Learned

- I learned how to design a rule-based validation pipeline that can grow without hard-coding every rule into the API layer.
- I practiced reading and annotating Word documents with OpenXML instead of treating uploaded files as plain text.
- I learned how to connect an Angular dev server to a local ASP.NET Core API through a proxy configuration.
- I practiced separating document parsing, validation rules, API responses, and frontend rendering into smaller pieces.
- I learned how to test document validation behavior with real `.docx` fixtures.

## Future Improvements

- Add more frontend unit tests around file upload, rule selection, and result rendering.
- Add end-to-end tests for the upload-to-annotated-download workflow.
- Improve accessibility for keyboard navigation, focus states, and screen reader labels.
- Add CI checks for frontend tests once the test suite is expanded.
- Add deployment configuration and replace the demo placeholder with a hosted link.
- Add clearer validation profiles for different university thesis requirements.
- Document how to add a new backend validation rule.

## License

> No license has been added yet.
4 changes: 2 additions & 2 deletions thesis-validator.sln → ThesisValidator.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "backend", "backend\backend.csproj", "{B5CEE1AB-68C5-FCEC-EA61-653FFB609ED2}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThesisValidator.Api", "src\backend\ThesisValidator.Api.csproj", "{B5CEE1AB-68C5-FCEC-EA61-653FFB609ED2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "backend.Tests", "backend.Tests\backend.Tests.csproj", "{871FB478-6040-4FAA-A744-1F98C040DB41}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThesisValidator.Api.Tests", "tests\backend.Tests\ThesisValidator.Api.Tests.csproj", "{871FB478-6040-4FAA-A744-1F98C040DB41}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
Loading
Loading