difflicious 0.13.0__tar.gz → 0.14.0__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.
Files changed (205) hide show
  1. {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/check-version-bump.yml +3 -4
  2. {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/ci.yml +2 -2
  3. {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/docker-publish.yml +9 -0
  4. {difflicious-0.13.0 → difflicious-0.14.0}/.gitignore +8 -0
  5. {difflicious-0.13.0 → difflicious-0.14.0}/CHANGELOG.md +59 -2
  6. {difflicious-0.13.0 → difflicious-0.14.0}/CLAUDE.md +43 -74
  7. {difflicious-0.13.0 → difflicious-0.14.0}/INSTALLATION.md +5 -5
  8. {difflicious-0.13.0 → difflicious-0.14.0}/PKG-INFO +59 -26
  9. {difflicious-0.13.0 → difflicious-0.14.0}/PLAN.md +1 -1
  10. difflicious-0.14.0/README.md +107 -0
  11. difflicious-0.14.0/docs/THEMING.md +187 -0
  12. {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2025-07-29-1015-expandable-context-feature.md +4 -0
  13. {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2025-11-04-2318-gitpython-migration-plan.md +4 -0
  14. {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/2025-11-18-alpine-component-architecture.md +4 -0
  15. {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2025-11-22-1.0-release-execution-plan.md +4 -0
  16. difflicious-0.14.0/docs/internal/archive/2026-04-03-design-proposal-warm-precision.md +530 -0
  17. {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2026-04-12-presentation-layer-separation.md +5 -1
  18. difflicious-0.14.0/docs/internal/archive/README.md +34 -0
  19. {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/javascript-modularization-plan.md +6 -2
  20. {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/presentation-layer-separation.md +4 -0
  21. {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/tailwind-design-system.md +4 -0
  22. difflicious-0.14.0/docs/screenshots/dark.png +0 -0
  23. difflicious-0.14.0/docs/screenshots/light.png +0 -0
  24. difflicious-0.14.0/docs/screenshots/themes/ledger-dark.png +0 -0
  25. difflicious-0.14.0/docs/screenshots/themes/ledger-light.png +0 -0
  26. difflicious-0.14.0/docs/screenshots/themes/slate-dark.png +0 -0
  27. difflicious-0.14.0/docs/screenshots/themes/slate-light.png +0 -0
  28. difflicious-0.14.0/docs/screenshots/themes/sorbet-dark.png +0 -0
  29. difflicious-0.14.0/docs/screenshots/themes/sorbet-light.png +0 -0
  30. {difflicious-0.13.0 → difflicious-0.14.0}/docs/site/_config.yml +1 -1
  31. {difflicious-0.13.0 → difflicious-0.14.0}/package.json +10 -2
  32. {difflicious-0.13.0 → difflicious-0.14.0}/pyproject.toml +2 -1
  33. {difflicious-0.13.0 → difflicious-0.14.0}/scripts/screenshot.py +83 -53
  34. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/__init__.py +1 -1
  35. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/app.py +8 -2
  36. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/auto_reload_routes.py +7 -2
  37. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/cli.py +48 -0
  38. difflicious-0.14.0/src/difflicious/config.py +188 -0
  39. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/syntax_service.py +61 -25
  40. difflicious-0.14.0/src/difflicious/static/css/styles.css +1329 -0
  41. difflicious-0.14.0/src/difflicious/static/css/tailwind.css +1 -0
  42. difflicious-0.14.0/src/difflicious/static/css/themes/_contract.css +309 -0
  43. difflicious-0.14.0/src/difflicious/static/css/themes/ledger.css +262 -0
  44. difflicious-0.14.0/src/difflicious/static/css/themes/slate.css +241 -0
  45. difflicious-0.14.0/src/difflicious/static/css/themes/sorbet.css +286 -0
  46. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/alpine-init.js +12 -12
  47. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/main.js +1 -1
  48. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/auto-reload.js +15 -9
  49. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/base.html +19 -6
  50. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/diff_file.html +14 -13
  51. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/diff_hunk.html +24 -16
  52. difflicious-0.14.0/src/difflicious/templates/partials/empty_state.html +27 -0
  53. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/partials/global_controls.html +1 -1
  54. difflicious-0.14.0/src/difflicious/templates/partials/loading_state.html +7 -0
  55. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/partials/toolbar.html +29 -37
  56. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_syntax_service.py +29 -14
  57. {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_app.py +103 -0
  58. {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_auto_reload_routes.py +37 -0
  59. {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_cli.py +53 -0
  60. {difflicious-0.13.0 → difflicious-0.14.0}/uv.lock +206 -21
  61. difflicious-0.13.0/README.md +0 -74
  62. difflicious-0.13.0/docs/CSS-STYLE-GUIDE.md +0 -596
  63. difflicious-0.13.0/docs/reference/app.js.reference +0 -982
  64. difflicious-0.13.0/docs/reference/diff-interactions.js.reference +0 -1676
  65. difflicious-0.13.0/docs/screenshots/dark.png +0 -0
  66. difflicious-0.13.0/docs/screenshots/light.png +0 -0
  67. difflicious-0.13.0/package-lock.json +0 -9183
  68. difflicious-0.13.0/src/difflicious/config.py +0 -71
  69. difflicious-0.13.0/src/difflicious/static/css/styles.css +0 -1611
  70. difflicious-0.13.0/src/difflicious/static/css/tailwind.css +0 -1
  71. difflicious-0.13.0/src/difflicious/templates/partials/empty_state.html +0 -29
  72. difflicious-0.13.0/src/difflicious/templates/partials/loading_state.html +0 -7
  73. {difflicious-0.13.0 → difflicious-0.14.0}/.dockerignore +0 -0
  74. {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/auto-release.yml +0 -0
  75. {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/pages.yml +0 -0
  76. {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/pypi-publish.yml +0 -0
  77. {difflicious-0.13.0 → difflicious-0.14.0}/AGENTS.md +0 -0
  78. {difflicious-0.13.0 → difflicious-0.14.0}/CONTRIBUTING.md +0 -0
  79. {difflicious-0.13.0 → difflicious-0.14.0}/DEVELOPING.md +0 -0
  80. {difflicious-0.13.0 → difflicious-0.14.0}/Dockerfile +0 -0
  81. {difflicious-0.13.0 → difflicious-0.14.0}/LICENSE +0 -0
  82. {difflicious-0.13.0 → difflicious-0.14.0}/cilicious.sh +0 -0
  83. {difflicious-0.13.0 → difflicious-0.14.0}/docs/TROUBLESHOOTING.md +0 -0
  84. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-08-03-1009-claude-fixing-uncommon-off-by-one-error.md +0 -0
  85. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-08-19-1925-expandable-context.md +0 -0
  86. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-08-19-1925-troubleshooting-context-expansion-2025-07-29.md +0 -0
  87. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-11-18-alpine-js-migration-progress.md +0 -0
  88. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-11-18-alpine-js-migration-status.md +0 -0
  89. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/prompts/2025-08-19-1934-phase-1-css-foundation-dark-theme.md +0 -0
  90. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-29-1916-code-structure-refactoring-recommendations.md +0 -0
  91. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-29-1917-extract-context-expansion-module.md +0 -0
  92. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-29-1918-extract-business-logic-service-layer.md +0 -0
  93. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-30-1701-jinja2-server-side-diff-rendering.md +0 -0
  94. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-30-1730-virtual-scrolling-lazy-rendering.md +0 -0
  95. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-03-2106-typescript-migration-plan.md +0 -0
  96. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-04-2130-simplify-diff-logic-and-ui.md +0 -0
  97. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-18-1954-font-configuration-proposal.md +0 -0
  98. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-18-1954-font-implementation-plan.md +0 -0
  99. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-18-1954-font-implementation-summary.md +0 -0
  100. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-19-1430-dark-light-mode-implementation.md +0 -0
  101. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-11-18-0130-alpine-js-dom-manipulation.md +0 -0
  102. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-07-29-2100-context-expansion-extraction-report.md +0 -0
  103. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-07-30-1647-diff-rendering-performance-analysis.md +0 -0
  104. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-07-30-1655-backend-migration-performance-analysis.md +0 -0
  105. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-08-18-1200-dead-code-analysis-report.md +0 -0
  106. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-09-22-1857-production-readiness-analysis.md +0 -0
  107. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-09-22-1949-ui-css-cleanup-analysis.md +0 -0
  108. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-30-2201-production-readiness-update.md +0 -0
  109. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-31-1253-test-coverage-analysis.md +0 -0
  110. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-31-1718-test-coverage-improvement-summary.md +0 -0
  111. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-31-1720-0.9-release-plan.md +0 -0
  112. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-05-1857-css-rationalization-analysis.md +0 -0
  113. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-05-2019-color-audit.md +0 -0
  114. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-05-2019-phase2-implementation-plan.md +0 -0
  115. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-17-1730-codebase-improvements-analysis.md +0 -0
  116. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2026-02-05-v1.0-release-readiness-audit.md +0 -0
  117. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-27-1256-project-setup-and-modern-python-packaging.md +0 -0
  118. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-27-1415-git-integration-and-security-implementation.md +0 -0
  119. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-27-1820-diff-parser-and-side-by-side-ui.md +0 -0
  120. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-28-0953-syntax-highlighting-implementation.md +0 -0
  121. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-28-1500-commit-comparison-and-ui-enhancements.md +0 -0
  122. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-28-1805-untracked-files-implementation-and-bugfix.md +0 -0
  123. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-31-1730-pygments-syntax-highlighting.compacted.md +0 -0
  124. {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-11-18-0130-alpine-js-migration-implementation.md +0 -0
  125. {difflicious-0.13.0 → difflicious-0.14.0}/docs/screenshots/.gitkeep +0 -0
  126. {difflicious-0.13.0 → difflicious-0.14.0}/docs/site/assets/logo.png +0 -0
  127. {difflicious-0.13.0 → difflicious-0.14.0}/docs/site/index.md +0 -0
  128. {difflicious-0.13.0 → difflicious-0.14.0}/pnpm-lock.yaml +0 -0
  129. {difflicious-0.13.0 → difflicious-0.14.0}/postcss.config.cjs +0 -0
  130. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/__init__.py +0 -0
  131. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/context_routes.py +0 -0
  132. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/diff_routes.py +0 -0
  133. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/git_routes.py +0 -0
  134. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/helpers.py +0 -0
  135. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/views.py +0 -0
  136. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/diff_parser.py +0 -0
  137. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/dummy_data.json +0 -0
  138. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/git_operations.py +0 -0
  139. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/__init__.py +0 -0
  140. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/base_service.py +0 -0
  141. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/diff_service.py +0 -0
  142. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/dtos.py +0 -0
  143. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/exceptions.py +0 -0
  144. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/file_watcher.py +0 -0
  145. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/git_service.py +0 -0
  146. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/template_service.py +0 -0
  147. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/css/tailwind.input.css +0 -0
  148. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/data/language_map.json +0 -0
  149. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/fileComponent.js +0 -0
  150. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/groupComponent.js +0 -0
  151. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/hunkComponent.js +0 -0
  152. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/searchComponent.js +0 -0
  153. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/context-expansion-ui.js +0 -0
  154. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/context-expansion.js +0 -0
  155. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/design-system.js +0 -0
  156. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/dom-utils.js +0 -0
  157. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/full-diff.js +0 -0
  158. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/hunk-operations.js +0 -0
  159. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/navigation.js +0 -0
  160. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/search.js +0 -0
  161. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/theme.js +0 -0
  162. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/toolbar.js +0 -0
  163. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/stores/diffStore.js +0 -0
  164. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/stores/searchStore.js +0 -0
  165. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/stores/themeStore.js +0 -0
  166. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/diff_groups.html +0 -0
  167. {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/index.html +0 -0
  168. {difflicious-0.13.0 → difflicious-0.14.0}/tailwind.config.cjs +0 -0
  169. {difflicious-0.13.0 → difflicious-0.14.0}/tests/__init__.py +0 -0
  170. {difflicious-0.13.0 → difflicious-0.14.0}/tests/conftest.py +0 -0
  171. {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/conftest.py +0 -0
  172. {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/test_api.py +0 -0
  173. {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/test_api_detailed.py +0 -0
  174. {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/test_frontend.py +0 -0
  175. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/auto-reload.test.js +0 -0
  176. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/components/fileComponent.test.js +0 -0
  177. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/components/groupComponent.test.js +0 -0
  178. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/components/hunkComponent.test.js +0 -0
  179. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/context-expansion-ui.test.js +0 -0
  180. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/context-expansion.test.js +0 -0
  181. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/design-system.test.js +0 -0
  182. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/diff-state-persistence.test.js.old +0 -0
  183. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/diffStore-actions.test.js +0 -0
  184. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/dom-utils.test.js +0 -0
  185. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/full-diff.test.js +0 -0
  186. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/navigation.test.js +0 -0
  187. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/search.test.js +0 -0
  188. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/setup.js +0 -0
  189. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/stores/diffStore.test.js +0 -0
  190. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/stores/searchStore.test.js +0 -0
  191. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/stores/themeStore.test.js +0 -0
  192. {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/toolbar.test.js +0 -0
  193. {difflicious-0.13.0 → difflicious-0.14.0}/tests/sample_01.diff +0 -0
  194. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/__init__.py +0 -0
  195. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_base_service.py +0 -0
  196. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_diff_service.py +0 -0
  197. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_exceptions.py +0 -0
  198. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_file_watcher.py +0 -0
  199. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_git_service.py +0 -0
  200. {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_template_service.py +0 -0
  201. {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_git_operations.py +0 -0
  202. {difflicious-0.13.0 → difflicious-0.14.0}/tests/unit/test_diff_parser_line_count.py +0 -0
  203. {difflicious-0.13.0 → difflicious-0.14.0}/tests/unit/test_diff_parser_side_by_side.py +0 -0
  204. {difflicious-0.13.0 → difflicious-0.14.0}/tests/unit/test_diff_rendering.py +0 -0
  205. {difflicious-0.13.0 → difflicious-0.14.0}/tests/unit/test_parser.py +0 -0
@@ -1,14 +1,13 @@
1
1
  name: Check Version Bump
2
2
 
3
+ # `pull_request` only. Registering `pull_request_target` as well ran the job a
4
+ # second time with the base checked out as the head, so it compared main against
5
+ # main and reported "Version was not bumped" on every genuine version bump.
3
6
  on:
4
7
  pull_request:
5
8
  paths:
6
9
  - 'src/difflicious/__init__.py'
7
10
  - 'CHANGELOG.md'
8
- pull_request_target:
9
- paths:
10
- - 'src/difflicious/__init__.py'
11
- - 'CHANGELOG.md'
12
11
 
13
12
  permissions:
14
13
  pull-requests: write
@@ -59,12 +59,12 @@ jobs:
59
59
  - name: Install pnpm
60
60
  uses: pnpm/action-setup@v4
61
61
  with:
62
- version: 9
62
+ version: 11
63
63
 
64
64
  - name: Set up Node.js
65
65
  uses: actions/setup-node@v4
66
66
  with:
67
- node-version: '18'
67
+ node-version: '22'
68
68
  cache: 'pnpm'
69
69
 
70
70
  - name: Install JavaScript dependencies
@@ -78,3 +78,12 @@ jobs:
78
78
  labels: ${{ steps.meta.outputs.labels }}
79
79
  cache-from: type=gha
80
80
  cache-to: type=gha,mode=max
81
+
82
+ - name: Update Docker Hub description
83
+ if: github.event_name != 'pull_request'
84
+ uses: peter-evans/dockerhub-description@v4
85
+ with:
86
+ username: ${{ secrets.DOCKER_USERNAME }}
87
+ password: ${{ secrets.DOCKER_HUB_TOKEN }}
88
+ repository: ${{ github.repository }}
89
+ readme-filepath: ./README.md
@@ -116,3 +116,11 @@ vendor/
116
116
  .coverage
117
117
  coverage.xml
118
118
  vendor/
119
+
120
+ # Git worktrees live inside the repo so they are easy to find; git tracks them
121
+ # via .git/worktrees, so the checkouts themselves must never be added.
122
+ .worktrees/
123
+
124
+ # Working notes. The rule is shared so everyone gets the same convention and
125
+ # their own private file; the contents are never committed.
126
+ .notes/
@@ -5,6 +5,57 @@ All notable changes to difflicious will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.14.0] - 2026-08-23
9
+
10
+ ### Themes & Interface
11
+
12
+ The interface is rebuilt on a theme layer. Every design decision — colour,
13
+ spacing, radius, border width, typography, shadow, motion, density — now lives in
14
+ `static/css/themes/`, and a theme can be swapped without touching anything else.
15
+ See [`docs/THEMING.md`](docs/THEMING.md).
16
+
17
+ ### Added
18
+ - **Three themes** — `ledger` (default, warm paper and ochre), `slate` (cool
19
+ greys and indigo), `sorbet` (bright, rounded, turquoise). Each ships light and
20
+ dark variants as peers, not as a filter over one another
21
+ - **Theme selection** — `--theme` or `DIFFLICIOUS_THEME`, listed with
22
+ `--list-themes`. A value that looks like a URL is loaded as a custom
23
+ stylesheet, named after its file
24
+ - **Per-theme typefaces** — a theme declares its own display and UI faces; only
25
+ the selected theme's fonts are fetched
26
+ - **Theme gallery** — thumbnails of every theme in both schemes in the theming
27
+ docs, and `scripts/screenshot.py --all-themes` to regenerate them
28
+
29
+ ### Fixed
30
+ - **Dark-mode syntax highlighting** — Pygments ran with `noclasses=True`, baking
31
+ one theme's colours inline server-side where no stylesheet could override
32
+ them, while the theme is switched in the browser. Dark mode had been showing
33
+ light-theme code colours. The formatter is now class-based
34
+ - **Syntax CSS was never injected** — a formatter had split `{{ syntax_css }}`
35
+ into `{ { … } }`, so the block rendered as literal text
36
+ - **Dark-mode overrides fighting the theme** — around 250 lines of `!important`
37
+ rules with hardcoded colours, most of them matching classes the templates no
38
+ longer emit, prevented a theme change taking full effect
39
+ - **Sticky file headers** — restored; they had been disabled by an `overflow`
40
+ rule on the file card
41
+ - **Empty bar above every file header** — a masking strip had become the only
42
+ separation between cards, which were otherwise flush. Cards now have a real gap
43
+ - **Whole expansion strip is clickable** — expanding context no longer requires
44
+ hitting a 28px pill, and the row is keyboard-operable
45
+ - **JavaScript linting** — `lint:js` never checked two source files, because npm
46
+ runs scripts through a shell where `**` is not recursive
47
+ - **Lockfile** — `playwright` was declared in `pyproject.toml` but missing from
48
+ `uv.lock`, so every `uv run` re-resolved and rewrote it
49
+
50
+ ### Changed
51
+ - **pnpm 11** in CI, matching local development
52
+ - **Git worktrees** may live in `.worktrees/` inside the repo; the file watcher
53
+ and test runners ignore them
54
+ - **Docs** — completed plans and superseded specs archived under
55
+ `docs/internal/archive/`; the CSS style guide is retired in favour of
56
+ `docs/THEMING.md`
57
+ - Removed the stray `package-lock.json`; the project is pnpm throughout
58
+
8
59
  ## [0.13.0] - 2026-04-14
9
60
 
10
61
  ### Release Automation & Infrastructure
@@ -31,7 +82,7 @@ Automated version management and release processes to streamline development wor
31
82
 
32
83
  ### Presentation Layer Separation
33
84
 
34
- Enforced explicit contracts between the data, service, template, CSS, and JS layers. Full design rationale in [`docs/presentation-layer-separation.md`](docs/presentation-layer-separation.md).
85
+ Enforced explicit contracts between the data, service, template, CSS, and JS layers. Full design rationale in [`docs/internal/archive/presentation-layer-separation.md`](docs/internal/archive/presentation-layer-separation.md).
35
86
 
36
87
  ### Changed
37
88
  - **Removed dual state** — deleted `state.js` and `file-operations.js`; `diffStore` is now the single source of truth for expansion state
@@ -45,7 +96,13 @@ Enforced explicit contracts between the data, service, template, CSS, and JS lay
45
96
  - **File content animation** — removed vertical scale transform; transition is now a plain opacity fade
46
97
  - **Ctrl+C shutdown** — SIGINT now triggers `os._exit(0)` matching the existing SIGTERM handler, so a single keypress exits cleanly regardless of open SSE connections
47
98
 
48
- ## [1.0.0] - 2026-02-06
99
+ ## [1.0.0] - 2026-02-06 — never released
100
+
101
+ > **This release does not exist.** It was published in error and withdrawn: there
102
+ > is no `v1.0.0` tag, and no 1.0.0 on PyPI. Development continued from 0.11.0.
103
+ > The entry is kept so the mistake is on the record rather than an unexplained
104
+ > gap, but nothing below shipped under this version number — the changes went out
105
+ > in 0.11.0 and later.
49
106
 
50
107
  ### Stable Release
51
108
 
@@ -147,10 +147,11 @@ Difflicious supports the following environment variables for configuration:
147
147
  | `DIFFLICIOUS_PORT` | `5000` | Port to run the web server on |
148
148
  | `DIFFLICIOUS_HOST` | `127.0.0.1` | Host to bind the web server to |
149
149
  | `DIFFLICIOUS_FONT` | `jetbrains-mono` | Programming font (see `--list-fonts`) |
150
+ | `DIFFLICIOUS_THEME` | `ledger` | Colour theme (see `--list-themes`) |
150
151
  | `DIFFLICIOUS_DISABLE_GOOGLE_FONTS` | `false` | Disable Google Fonts CDN |
151
152
  | `DIFFLICIOUS_AUTO_RELOAD` | `true` | Enable auto-reload on file changes |
152
153
  | `DIFFLICIOUS_WATCH_DEBOUNCE` | `1.0` | Debounce time (seconds) for file watcher |
153
- | `DIFFLICIOUS_WATCH_IGNORE` | `.git` | Patterns to ignore for file watching |
154
+ | `DIFFLICIOUS_WATCH_IGNORE` | `.git,.worktrees` | Patterns to ignore for file watching |
154
155
  | `DIFFLICIOUS_DEBUG` | `false` | Enable verbose debug logging in browser console |
155
156
 
156
157
  **Example usage:**
@@ -216,8 +217,8 @@ DIFFLICIOUS_AUTO_RELOAD=false difflicious
216
217
  - ✅ **Docker Support**: Production-ready containerization with Alpine Linux
217
218
  - ✅ **Real-time Updates**: Server-Sent Events implementation for live status monitoring
218
219
  - ✅ **Modular Frontend**: ES6 module architecture for maintainable JavaScript
219
- - 🚧 **Word-level Diffs**: Advanced word-diff parsing (future enhancement)
220
- - 🚧 **Keyboard Shortcuts**: Accessibility and power-user features (planned)
220
+ - **Theming**: Three built-in themes, selectable at startup, with light and dark variants
221
+ - **Sticky File Headers**: File headers pin to the top while scrolling a diff
221
222
 
222
223
  ## Security Requirements (IMPLEMENTED)
223
224
 
@@ -301,7 +302,7 @@ All API endpoints return JSON responses with consistent error handling via the b
301
302
  **Modifying Styles:**
302
303
  1. Add Tailwind utilities in templates for layout/spacing
303
304
  2. Add custom styles in `static/css/styles.css` for components
304
- 3. Use CSS variables for all colors (see CSS Style Guide)
305
+ 3. Use tokens for all colours (see `docs/THEMING.md`)
305
306
  4. Rebuild Tailwind: `pnpm run tailwind:build`
306
307
  5. Test both light and dark themes
307
308
 
@@ -314,93 +315,54 @@ All API endpoints return JSON responses with consistent error handling via the b
314
315
  - **Security**: All git command execution must use proper subprocess sanitization
315
316
  - **Type Hints**: All new Python code should include type hints (enforced by mypy via cilicious.sh)
316
317
  - **Docstrings**: All public functions/classes should have docstrings
317
- - **CSS Guidelines**: Follow the CSS Style Guide for all styling changes (see below)
318
+ - **CSS Guidelines**: Follow `docs/THEMING.md` for all styling changes (see below)
318
319
  - **Testing**: All tests must pass via cilicious.sh (both Python pytest and JavaScript Jest)
319
320
  - **Linting**: Code must pass all linters via cilicious.sh (ruff, black, eslint)
320
321
 
321
- ## CSS Architecture & Guidelines
322
+ ## CSS Architecture & Theming
322
323
 
323
- **IMPORTANT:** Difflicious uses a semantic CSS variable system. Always follow these guidelines:
324
+ **IMPORTANT:** Every design decision colour, spacing, radius, border width,
325
+ typography, shadow, motion, density — lives in `src/difflicious/static/css/themes/`.
326
+ Read `docs/THEMING.md` before making any styling change.
324
327
 
325
- ### Core Principles
328
+ ### The rule
326
329
 
327
- 1. **CSS Variables for Colors** - ALWAYS use CSS variables, NEVER hardcode hex values
328
- 2. **Tailwind for Utilities Only** - Layout, spacing, typography (NOT colors)
329
- 3. **Semantic Class Names** - Describe purpose, not appearance
330
- 4. **Both Themes** - Always test light AND dark themes
331
-
332
- ### Quick Reference
333
-
334
- **✅ DO:**
335
- ```css
336
- .component {
337
- background: var(--surface-secondary);
338
- color: var(--text-primary);
339
- border: 1px solid var(--border-default);
340
- }
341
- ```
342
-
343
- ```html
344
- <span class="status-badge status-badge-added">added</span>
345
- ```
346
-
347
- **❌ DON'T:**
348
- ```css
349
- .component {
350
- background: #f8fafc; /* Hardcoded! */
351
- color: green; /* Won't respect theme! */
352
- }
353
330
  ```
354
-
355
- ```html
356
- <span class="bg-green-100 text-green-800"> <!-- Don't use Tailwind colors! -->
331
+ themes/_contract.css → theme-independent scales, density knobs, aliases
332
+ themes/<name>.css → palette + semantic roles for one theme
333
+ styles.css → structure and layout only; consumes tokens
334
+ templates → semantic classes only; never Tailwind colour utilities
357
335
  ```
358
336
 
359
- ### Common Color Variables
337
+ `styles.css` contains no literal colours, radii or shadows. If a value needs to
338
+ be tunable, add a token to the contract and reference it — do not inline it.
360
339
 
361
- - `--surface-primary` - Page background
362
- - `--surface-secondary` - Cards, panels
363
- - `--text-primary` - Main text
364
- - `--text-secondary` - Secondary text
365
- - `--border-default` - Standard borders
366
- - `--semantic-success-bg-subtle` - Success badges/states
367
- - `--semantic-danger-bg-subtle` - Error badges/states
340
+ ### Never reference another theme's palette
368
341
 
369
- ### Component Classes Available
342
+ Tokens prefixed `--theme-<name>-*` are private to the theme that declares them.
343
+ The contract, `styles.css` and templates may only use semantic roles
344
+ (`--surface-*`, `--text-*`, `--border-*`, `--accent-*`, `--diff-*`), which every
345
+ theme declares. Pointing at `--theme-paper-500` resolves to nothing under any
346
+ theme but Ledger.
370
347
 
371
- - `.status-badge .status-badge-{added|deleted|renamed|modified}` - Status indicators
372
- - `.file-stat .file-stat-{addition|deletion}` - File change counts
348
+ ### Themes
373
349
 
374
- ### Tailwind Usage
350
+ `ledger` (default), `slate`, `sorbet`. Select with `--theme` or
351
+ `DIFFLICIOUS_THEME`; `--list-themes` shows them. A value that looks like a URL is
352
+ loaded as a custom stylesheet named after its file.
375
353
 
376
- **Use Tailwind for:**
377
- - Layout: `flex`, `grid`, `space-x-4`
378
- - Spacing: `p-4`, `m-2`, `px-3`
379
- - Typography: `text-sm`, `font-mono`
380
- - Display: `block`, `hidden`
354
+ ### Both themes, every time
381
355
 
382
- **DON'T use Tailwind for:**
383
- - Colors (use CSS variables)
384
- - Dark mode (use `[data-theme="dark"]`)
385
- - Complex components (use semantic classes)
356
+ Light and dark are peers. Every semantic token is declared in both blocks of a
357
+ theme file, and every UI change must be checked in both.
386
358
 
387
- ### CSS File Rebuilding
359
+ ### Rebuilding Tailwind
388
360
 
389
- When modifying Tailwind config or input CSS:
390
361
  ```bash
391
362
  pnpm run tailwind:build
392
363
  ```
393
364
 
394
- ### Complete Documentation
395
-
396
- For comprehensive CSS guidelines, see: `docs/CSS-STYLE-GUIDE.md`
397
-
398
- This includes:
399
- - Complete list of CSS variables by category
400
- - How to create new component classes
401
- - Dark mode implementation details
402
- - Common patterns and examples
403
- - Best practices and migration guide
365
+ Tailwind is for layout, spacing and typography only — never colours or dark mode.
404
366
 
405
367
  ## Project Structure
406
368
 
@@ -484,9 +446,12 @@ difflicious/
484
446
  │ └── js/ # JavaScript tests
485
447
 
486
448
  ├── docs/ # Documentation
487
- │ ├── CSS-STYLE-GUIDE.md # CSS conventions
449
+ │ ├── THEMING.md # Themes and design tokens
488
450
  │ ├── TROUBLESHOOTING.md # Common issues
489
- └── javascript-modularization-plan.md
451
+ ├── internal/ # Working notes, reports, session logs
452
+ │ │ └── archive/ # Completed plans and superseded specs
453
+ │ ├── screenshots/ # README screenshots
454
+ │ └── site/ # GitHub Pages content
490
455
 
491
456
  ├── pyproject.toml # Python project configuration
492
457
  ├── uv.lock # uv lockfile
@@ -541,9 +506,13 @@ The application is designed for multiple distribution channels:
541
506
  - `INSTALLATION.md` - Installation and usage guide (PyPI, Docker, configuration)
542
507
 
543
508
  **Technical Guides:**
544
- - `docs/CSS-STYLE-GUIDE.md` - Comprehensive CSS architecture and conventions
509
+ - `docs/THEMING.md` - Themes, design tokens, and how to add a theme
545
510
  - `docs/TROUBLESHOOTING.md` - Common issues and solutions
546
- - `docs/javascript-modularization-plan.md` - Frontend architecture decisions
511
+
512
+ **Archive:**
513
+ - `docs/internal/archive/` - Completed plans and superseded specs, kept for
514
+ context only. Do not treat anything there as a description of current
515
+ behaviour; see `docs/internal/archive/README.md` for the index.
547
516
 
548
517
  **Keep these files synchronized when making architectural changes!**
549
518
 
@@ -13,7 +13,7 @@ This guide covers installing and running difflicious locally for developers.
13
13
  ## Quick Start
14
14
 
15
15
  For the fastest path to running difflicious, follow the quick-start steps in
16
- the [README](../README.md#installation--quick-start). This guide focuses on
16
+ the [README](README.md#installation--quick-start). This guide focuses on
17
17
  detailed configuration, Docker workflows, and troubleshooting.
18
18
 
19
19
  ## PyPI Installation
@@ -287,10 +287,10 @@ docker logs <container-id>
287
287
  docker images insipid/difflicious
288
288
  ```
289
289
 
290
- For more troubleshooting help, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md).
290
+ For more troubleshooting help, see [TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md).
291
291
 
292
292
  ## Next Steps
293
293
 
294
- - Check [troubleshooting](TROUBLESHOOTING.md) for common issues
295
- - Read the main [README](../README.md) for features
296
- - Explore [DEVELOPING.md](../DEVELOPING.md) for development setup and workflow
294
+ - Check [troubleshooting](docs/TROUBLESHOOTING.md) for common issues
295
+ - Read the main [README](README.md) for features
296
+ - Explore [DEVELOPING.md](DEVELOPING.md) for development setup and workflow
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: difflicious
3
- Version: 0.13.0
4
- Summary: A sleek web-based git diff visualization tool for developers
3
+ Version: 0.14.0
4
+ Summary: A local web diff viewer for git diffs of a working directory
5
5
  Project-URL: Homepage, https://github.com/insipid/difflicious
6
6
  Project-URL: Repository, https://github.com/insipid/difflicious
7
7
  Project-URL: Issues, https://github.com/insipid/difflicious/issues
@@ -38,34 +38,62 @@ Description-Content-Type: text/markdown
38
38
 
39
39
  # Difflicious
40
40
 
41
- [![PyPI version](https://img.shields.io/pypi/v/difflicious.svg)](https://pypi.org/project/difflicious/)
42
- [![Python versions](https://img.shields.io/pypi/pyversions/difflicious.svg)](https://pypi.org/project/difflicious/)
43
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
41
+ <div align="center">
42
+ <img src="docs/site/assets/logo.png" width="160" alt="Difflicious">
43
+ <p><em>A local diff viewer for comparing your working directory to any branch, not just HEAD.<br>
44
+ No forge, no push — just run it in your repo.</em></p>
45
+ </div>
44
46
 
45
- A local web application for reviewing git diffs. Run it in your working directory and view your changes in a browser with side-by-side visualization, syntax highlighting, and context expansion.
47
+ ---
46
48
 
47
49
  ## Screenshots
48
50
 
49
- | Light mode | Dark mode |
50
- |------------|-----------|
51
- | ![Light mode](docs/screenshots/light.png) | ![Dark mode](docs/screenshots/dark.png) |
51
+ <p align="center">
52
+ <img src="docs/screenshots/light.png" width="49%" alt="Light mode">
53
+ <img src="docs/screenshots/dark.png" width="49%" alt="Dark mode">
54
+ </p>
55
+
56
+ ## Usage
57
+
58
+ The quickest way — no install required:
59
+
60
+ ```bash
61
+ uvx difflicious
62
+ ```
63
+
64
+ Or with Docker:
65
+
66
+ ```bash
67
+ docker run -it --rm -v "$PWD:/workspace" -p 5000:5000 insipid/difflicious
68
+ ```
52
69
 
53
- > To regenerate: `uv run python scripts/screenshot.py`
54
- > Prerequisites: `uv add --dev playwright && uv run playwright install chromium`
70
+ Then open `http://localhost:5000` in your browser.
55
71
 
56
72
  ## Installation
57
73
 
74
+ For regular use, install from PyPI:
75
+
58
76
  ```bash
59
77
  pip install difflicious
60
78
  difflicious
61
79
  ```
62
80
 
63
- Open `http://localhost:5000` in your browser.
64
-
65
81
  See [INSTALLATION.md](INSTALLATION.md) for Docker, source installation, and full configuration options.
66
82
 
83
+ If you prefer not to install globally, add one of these to your shell profile:
84
+
85
+ ```bash
86
+ # via uvx
87
+ difflicious() { uvx difflicious "$@"; }
88
+
89
+ # via Docker (uses DIFFLICIOUS_PORT if set, otherwise 5000)
90
+ difflicious() { docker run -it --rm -v "$PWD:/workspace" -p "${DIFFLICIOUS_PORT:-5000}:${DIFFLICIOUS_PORT:-5000}" insipid/difflicious "$@"; }
91
+ ```
92
+
67
93
  ## Features
68
94
 
95
+ Like your favourite forge, and then some:
96
+
69
97
  - Side-by-side diff view with line numbering
70
98
  - Syntax highlighting for 100+ languages (via Pygments)
71
99
  - Context expansion to see more surrounding code
@@ -73,19 +101,23 @@ See [INSTALLATION.md](INSTALLATION.md) for Docker, source installation, and full
73
101
  - Light and dark themes
74
102
  - Live auto-reload on file changes (SSE)
75
103
  - Font customization via `DIFFLICIOUS_FONT` environment variable
104
+ - Compare against any branch — defaults to remote HEAD, configurable per session
105
+ - Toggle staged and unstaged changes independently
106
+ - UI state is persistent — collapsed files, hidden files, and view settings are remembered in the browser across sessions
76
107
 
77
108
  ## Configuration
78
109
 
79
- Set environment variables to configure behavior:
110
+ All options can be set via environment variable or CLI flag:
80
111
 
81
- | Variable | Default | Description |
82
- |----------|---------|-------------|
83
- | `DIFFLICIOUS_PORT` | `5000` | Port to listen on |
84
- | `DIFFLICIOUS_HOST` | `127.0.0.1` | Host to bind to |
85
- | `DIFFLICIOUS_FONT` | `jetbrains-mono` | Code font (see `--list-fonts`) |
86
- | `DIFFLICIOUS_DISABLE_GOOGLE_FONTS` | `false` | Use system fonts only |
87
- | `DIFFLICIOUS_AUTO_RELOAD` | `true` | Auto-reload on file changes |
88
- | `DIFFLICIOUS_DEBUG` | `false` | Verbose debug logging |
112
+ | Environment variable | CLI flag | Default | Description |
113
+ |----------------------|----------|---------|-------------|
114
+ | `DIFFLICIOUS_PORT` | `--port`, `-p` | `5000` | Port to listen on |
115
+ | `DIFFLICIOUS_HOST` | `--host`, `-h` | `127.0.0.1` | Host to bind to |
116
+ | `DIFFLICIOUS_FONT` | — | `jetbrains-mono` | Code font (`--list-fonts` to browse) |
117
+ | `DIFFLICIOUS_DISABLE_GOOGLE_FONTS` | — | `false` | Use system fonts only |
118
+ | `DIFFLICIOUS_AUTO_RELOAD` | `--auto-reload` / `--no-auto-reload` | `true` | Auto-reload on file changes |
119
+ | `DIFFLICIOUS_WATCH_DEBOUNCE` | `--watch-debounce` | `1.0` | File watcher debounce delay (seconds) |
120
+ | `DIFFLICIOUS_DEBUG` | `--debug` | `false` | Verbose debug logging |
89
121
 
90
122
  See [INSTALLATION.md](INSTALLATION.md) for full configuration details.
91
123
 
@@ -100,13 +132,14 @@ See [INSTALLATION.md](INSTALLATION.md) for full configuration details.
100
132
  - [INSTALLATION.md](INSTALLATION.md) — installation options, configuration, environment variables
101
133
  - [DEVELOPING.md](DEVELOPING.md) — development setup, testing, code conventions
102
134
  - [CHANGELOG.md](CHANGELOG.md) — version history
103
- - [docs/CSS-STYLE-GUIDE.md](docs/CSS-STYLE-GUIDE.md) — CSS conventions and design tokens
104
135
  - [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) — common issues
105
136
 
106
137
  ## Contributing
107
138
 
108
139
  See [CONTRIBUTING.md](CONTRIBUTING.md).
109
140
 
110
- ## License
141
+ ---
111
142
 
112
- MIT License — see [LICENSE](LICENSE) file for details.
143
+ [![PyPI version](https://img.shields.io/pypi/v/difflicious.svg)](https://pypi.org/project/difflicious/)
144
+ [![Python versions](https://img.shields.io/pypi/pyversions/difflicious.svg)](https://pypi.org/project/difflicious/)
145
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -64,7 +64,7 @@ A lightweight local web application for developers to visualize git diffs with a
64
64
  - Implement advanced display options (more git data)
65
65
  - Add keyboard shortcuts and accessibility
66
66
  - Polish UI/UX with responsive design
67
- - **Sticky file headers** - File headers that stick to top during scroll (attempted but needs further investigation with CSS positioning in Alpine.js/Tailwind context)
67
+ - ~~Sticky file headers~~ - implemented; headers pin while scrolling a diff
68
68
 
69
69
  ## Current Status (as of Version 0.10.0)
70
70
  - ✅ Phase 1: Project Setup & Core Backend - COMPLETE
@@ -0,0 +1,107 @@
1
+ # Difflicious
2
+
3
+ <div align="center">
4
+ <img src="docs/site/assets/logo.png" width="160" alt="Difflicious">
5
+ <p><em>A local diff viewer for comparing your working directory to any branch, not just HEAD.<br>
6
+ No forge, no push — just run it in your repo.</em></p>
7
+ </div>
8
+
9
+ ---
10
+
11
+ ## Screenshots
12
+
13
+ <p align="center">
14
+ <img src="docs/screenshots/light.png" width="49%" alt="Light mode">
15
+ <img src="docs/screenshots/dark.png" width="49%" alt="Dark mode">
16
+ </p>
17
+
18
+ ## Usage
19
+
20
+ The quickest way — no install required:
21
+
22
+ ```bash
23
+ uvx difflicious
24
+ ```
25
+
26
+ Or with Docker:
27
+
28
+ ```bash
29
+ docker run -it --rm -v "$PWD:/workspace" -p 5000:5000 insipid/difflicious
30
+ ```
31
+
32
+ Then open `http://localhost:5000` in your browser.
33
+
34
+ ## Installation
35
+
36
+ For regular use, install from PyPI:
37
+
38
+ ```bash
39
+ pip install difflicious
40
+ difflicious
41
+ ```
42
+
43
+ See [INSTALLATION.md](INSTALLATION.md) for Docker, source installation, and full configuration options.
44
+
45
+ If you prefer not to install globally, add one of these to your shell profile:
46
+
47
+ ```bash
48
+ # via uvx
49
+ difflicious() { uvx difflicious "$@"; }
50
+
51
+ # via Docker (uses DIFFLICIOUS_PORT if set, otherwise 5000)
52
+ difflicious() { docker run -it --rm -v "$PWD:/workspace" -p "${DIFFLICIOUS_PORT:-5000}:${DIFFLICIOUS_PORT:-5000}" insipid/difflicious "$@"; }
53
+ ```
54
+
55
+ ## Features
56
+
57
+ Like your favourite forge, and then some:
58
+
59
+ - Side-by-side diff view with line numbering
60
+ - Syntax highlighting for 100+ languages (via Pygments)
61
+ - Context expansion to see more surrounding code
62
+ - Search and filter across files
63
+ - Light and dark themes
64
+ - Live auto-reload on file changes (SSE)
65
+ - Font customization via `DIFFLICIOUS_FONT` environment variable
66
+ - Compare against any branch — defaults to remote HEAD, configurable per session
67
+ - Toggle staged and unstaged changes independently
68
+ - UI state is persistent — collapsed files, hidden files, and view settings are remembered in the browser across sessions
69
+
70
+ ## Configuration
71
+
72
+ All options can be set via environment variable or CLI flag:
73
+
74
+ | Environment variable | CLI flag | Default | Description |
75
+ |----------------------|----------|---------|-------------|
76
+ | `DIFFLICIOUS_PORT` | `--port`, `-p` | `5000` | Port to listen on |
77
+ | `DIFFLICIOUS_HOST` | `--host`, `-h` | `127.0.0.1` | Host to bind to |
78
+ | `DIFFLICIOUS_FONT` | — | `jetbrains-mono` | Code font (`--list-fonts` to browse) |
79
+ | `DIFFLICIOUS_DISABLE_GOOGLE_FONTS` | — | `false` | Use system fonts only |
80
+ | `DIFFLICIOUS_AUTO_RELOAD` | `--auto-reload` / `--no-auto-reload` | `true` | Auto-reload on file changes |
81
+ | `DIFFLICIOUS_WATCH_DEBOUNCE` | `--watch-debounce` | `1.0` | File watcher debounce delay (seconds) |
82
+ | `DIFFLICIOUS_DEBUG` | `--debug` | `false` | Verbose debug logging |
83
+
84
+ See [INSTALLATION.md](INSTALLATION.md) for full configuration details.
85
+
86
+ ## Technology
87
+
88
+ - **Backend**: Flask, GitPython, Pygments, unidiff
89
+ - **Frontend**: Alpine.js, Tailwind CSS
90
+ - **Real-time**: Server-Sent Events
91
+
92
+ ## Documentation
93
+
94
+ - [INSTALLATION.md](INSTALLATION.md) — installation options, configuration, environment variables
95
+ - [DEVELOPING.md](DEVELOPING.md) — development setup, testing, code conventions
96
+ - [CHANGELOG.md](CHANGELOG.md) — version history
97
+ - [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) — common issues
98
+
99
+ ## Contributing
100
+
101
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
102
+
103
+ ---
104
+
105
+ [![PyPI version](https://img.shields.io/pypi/v/difflicious.svg)](https://pypi.org/project/difflicious/)
106
+ [![Python versions](https://img.shields.io/pypi/pyversions/difflicious.svg)](https://pypi.org/project/difflicious/)
107
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)