Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

## [Unreleased] - .NET 8 / Open XML SDK 3.x Migration

### Added
- **DocxodusWeb — serverless redline & ticket web app** - ASP.NET Minimal API app for Cloud Run / serverless deployment
- `POST /api/compare` — Upload two DOCX files, receive a redlined DOCX with tracked changes
- `POST /api/compare/html` — Upload two DOCX files, receive HTML redline preview
- Rendering issue ticket system with SQLite storage — submit two DOCX files + description to report comparison bugs
- Tickets automatically run the Docxodus comparison and store original, modified, and redlined documents
- Simple HTML/CSS/JS frontend with redline tool, ticket list, and ticket submission tabs
- Dockerfile for containerized deployment (Google Cloud Run, AWS Fargate, etc.)
- Configurable via `DATA_DIR` environment variable for persistent storage

### Fixed (npm)
- **TypeScript subpath exports not resolving under `moduleResolution: "node"` (Issue #113)** - Added `typesVersions` fallback to npm package.json so `docxodus/react` and `docxodus/worker` subpath imports resolve types correctly under all TypeScript module resolution modes. Also reordered export conditions to put `types` before `import` per TypeScript requirements.

Expand Down
9 changes: 9 additions & 0 deletions Docxodus.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wasm", "wasm", "{1763F37B-6
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocxodusWasm", "wasm\DocxodusWasm\DocxodusWasm.csproj", "{A4D71AD0-DF96-4702-A2A3-10C91BBD90E3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{8A2B6F4E-1C3D-4E5F-9A7B-2D4E6F8A0B1C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocxodusWeb", "web\DocxodusWeb\DocxodusWeb.csproj", "{B5C7D9E1-2F4A-4B6C-8D0E-3F5A7B9C1D2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -46,10 +50,15 @@ Global
{A4D71AD0-DF96-4702-A2A3-10C91BBD90E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4D71AD0-DF96-4702-A2A3-10C91BBD90E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4D71AD0-DF96-4702-A2A3-10C91BBD90E3}.Release|Any CPU.Build.0 = Release|Any CPU
{B5C7D9E1-2F4A-4B6C-8D0E-3F5A7B9C1D2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5C7D9E1-2F4A-4B6C-8D0E-3F5A7B9C1D2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5C7D9E1-2F4A-4B6C-8D0E-3F5A7B9C1D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5C7D9E1-2F4A-4B6C-8D0E-3F5A7B9C1D2E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EDB9FC41-541D-41FE-A95C-4A25BF4823B6} = {3B57DC3E-0543-4470-B094-701C65C843D5}
{15EAF76F-3C7C-4747-A686-6F9FC65D2968} = {3B57DC3E-0543-4470-B094-701C65C843D5}
{A4D71AD0-DF96-4702-A2A3-10C91BBD90E3} = {1763F37B-6FCB-4FA2-B410-4E573BDBC84F}
{B5C7D9E1-2F4A-4B6C-8D0E-3F5A7B9C1D2E} = {8A2B6F4E-1C3D-4E5F-9A7B-2D4E6F8A0B1C}
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions web/DocxodusWeb/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bin/
obj/
appdata/
59 changes: 59 additions & 0 deletions web/DocxodusWeb/Data/TicketDbContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#nullable enable

using Microsoft.EntityFrameworkCore;

namespace DocxodusWeb.Data;

public class TicketDbContext : DbContext
{
public TicketDbContext(DbContextOptions<TicketDbContext> options) : base(options) { }

public DbSet<Ticket> Tickets => Set<Ticket>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Ticket>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Id).ValueGeneratedOnAdd();
entity.Property(e => e.Status).HasConversion<string>();
});
}
}

public class Ticket
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string? SubmitterEmail { get; set; }
public TicketStatus Status { get; set; } = TicketStatus.Open;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;

/// <summary>Path to the original .docx file on disk.</summary>
public string OriginalFilePath { get; set; } = string.Empty;
public string OriginalFileName { get; set; } = string.Empty;

/// <summary>Path to the modified .docx file on disk.</summary>
public string ModifiedFilePath { get; set; } = string.Empty;
public string ModifiedFileName { get; set; } = string.Empty;

/// <summary>Path to the redline .docx produced by Docxodus (generated on submission).</summary>
public string? RedlineFilePath { get; set; }

/// <summary>Comparison log warnings/errors, if any.</summary>
public string? ComparisonLog { get; set; }

/// <summary>Number of revisions detected in the redline.</summary>
public int? RevisionCount { get; set; }
}

public enum TicketStatus
{
Open,
InProgress,
Resolved,
WontFix,
Duplicate
}
30 changes: 30 additions & 0 deletions web/DocxodusWeb/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

# Copy solution and project files for restore
COPY Docxodus/Docxodus.csproj Docxodus/
COPY web/DocxodusWeb/DocxodusWeb.csproj web/DocxodusWeb/
RUN dotnet restore web/DocxodusWeb/DocxodusWeb.csproj

# Copy everything and build
COPY Docxodus/ Docxodus/
COPY web/DocxodusWeb/ web/DocxodusWeb/
RUN dotnet publish web/DocxodusWeb/DocxodusWeb.csproj -c Release -o /app/publish

# Runtime image
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app

# Install native dependencies for SkiaSharp
RUN apt-get update && apt-get install -y --no-install-recommends \
libfontconfig1 \
&& rm -rf /var/lib/apt/lists/*

COPY --from=build /app/publish .

# Cloud Run uses PORT env var
ENV ASPNETCORE_URLS=http://+:8080
ENV DATA_DIR=/data
EXPOSE 8080

ENTRYPOINT ["dotnet", "DocxodusWeb.dll"]
21 changes: 21 additions & 0 deletions web/DocxodusWeb/DocxodusWeb.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<RootNamespace>DocxodusWeb</RootNamespace>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../Docxodus/Docxodus.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Loading
Loading