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.
- {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/check-version-bump.yml +3 -4
- {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/ci.yml +2 -2
- {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/docker-publish.yml +9 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/.gitignore +8 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/CHANGELOG.md +59 -2
- {difflicious-0.13.0 → difflicious-0.14.0}/CLAUDE.md +43 -74
- {difflicious-0.13.0 → difflicious-0.14.0}/INSTALLATION.md +5 -5
- {difflicious-0.13.0 → difflicious-0.14.0}/PKG-INFO +59 -26
- {difflicious-0.13.0 → difflicious-0.14.0}/PLAN.md +1 -1
- difflicious-0.14.0/README.md +107 -0
- difflicious-0.14.0/docs/THEMING.md +187 -0
- {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2025-07-29-1015-expandable-context-feature.md +4 -0
- {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2025-11-04-2318-gitpython-migration-plan.md +4 -0
- {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/2025-11-18-alpine-component-architecture.md +4 -0
- {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2025-11-22-1.0-release-execution-plan.md +4 -0
- difflicious-0.14.0/docs/internal/archive/2026-04-03-design-proposal-warm-precision.md +530 -0
- {difflicious-0.13.0/docs/plans → difflicious-0.14.0/docs/internal/archive}/2026-04-12-presentation-layer-separation.md +5 -1
- difflicious-0.14.0/docs/internal/archive/README.md +34 -0
- {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/javascript-modularization-plan.md +6 -2
- {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/presentation-layer-separation.md +4 -0
- {difflicious-0.13.0/docs → difflicious-0.14.0/docs/internal/archive}/tailwind-design-system.md +4 -0
- difflicious-0.14.0/docs/screenshots/dark.png +0 -0
- difflicious-0.14.0/docs/screenshots/light.png +0 -0
- difflicious-0.14.0/docs/screenshots/themes/ledger-dark.png +0 -0
- difflicious-0.14.0/docs/screenshots/themes/ledger-light.png +0 -0
- difflicious-0.14.0/docs/screenshots/themes/slate-dark.png +0 -0
- difflicious-0.14.0/docs/screenshots/themes/slate-light.png +0 -0
- difflicious-0.14.0/docs/screenshots/themes/sorbet-dark.png +0 -0
- difflicious-0.14.0/docs/screenshots/themes/sorbet-light.png +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/site/_config.yml +1 -1
- {difflicious-0.13.0 → difflicious-0.14.0}/package.json +10 -2
- {difflicious-0.13.0 → difflicious-0.14.0}/pyproject.toml +2 -1
- {difflicious-0.13.0 → difflicious-0.14.0}/scripts/screenshot.py +83 -53
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/__init__.py +1 -1
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/app.py +8 -2
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/auto_reload_routes.py +7 -2
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/cli.py +48 -0
- difflicious-0.14.0/src/difflicious/config.py +188 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/syntax_service.py +61 -25
- difflicious-0.14.0/src/difflicious/static/css/styles.css +1329 -0
- difflicious-0.14.0/src/difflicious/static/css/tailwind.css +1 -0
- difflicious-0.14.0/src/difflicious/static/css/themes/_contract.css +309 -0
- difflicious-0.14.0/src/difflicious/static/css/themes/ledger.css +262 -0
- difflicious-0.14.0/src/difflicious/static/css/themes/slate.css +241 -0
- difflicious-0.14.0/src/difflicious/static/css/themes/sorbet.css +286 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/alpine-init.js +12 -12
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/main.js +1 -1
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/auto-reload.js +15 -9
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/base.html +19 -6
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/diff_file.html +14 -13
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/diff_hunk.html +24 -16
- difflicious-0.14.0/src/difflicious/templates/partials/empty_state.html +27 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/partials/global_controls.html +1 -1
- difflicious-0.14.0/src/difflicious/templates/partials/loading_state.html +7 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/partials/toolbar.html +29 -37
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_syntax_service.py +29 -14
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_app.py +103 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_auto_reload_routes.py +37 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_cli.py +53 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/uv.lock +206 -21
- difflicious-0.13.0/README.md +0 -74
- difflicious-0.13.0/docs/CSS-STYLE-GUIDE.md +0 -596
- difflicious-0.13.0/docs/reference/app.js.reference +0 -982
- difflicious-0.13.0/docs/reference/diff-interactions.js.reference +0 -1676
- difflicious-0.13.0/docs/screenshots/dark.png +0 -0
- difflicious-0.13.0/docs/screenshots/light.png +0 -0
- difflicious-0.13.0/package-lock.json +0 -9183
- difflicious-0.13.0/src/difflicious/config.py +0 -71
- difflicious-0.13.0/src/difflicious/static/css/styles.css +0 -1611
- difflicious-0.13.0/src/difflicious/static/css/tailwind.css +0 -1
- difflicious-0.13.0/src/difflicious/templates/partials/empty_state.html +0 -29
- difflicious-0.13.0/src/difflicious/templates/partials/loading_state.html +0 -7
- {difflicious-0.13.0 → difflicious-0.14.0}/.dockerignore +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/auto-release.yml +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/pages.yml +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/.github/workflows/pypi-publish.yml +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/AGENTS.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/CONTRIBUTING.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/DEVELOPING.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/Dockerfile +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/LICENSE +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/cilicious.sh +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/TROUBLESHOOTING.md +0 -0
- {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
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-08-19-1925-expandable-context.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-08-19-1925-troubleshooting-context-expansion-2025-07-29.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-11-18-alpine-js-migration-progress.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/notes/2025-11-18-alpine-js-migration-status.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/prompts/2025-08-19-1934-phase-1-css-foundation-dark-theme.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-29-1916-code-structure-refactoring-recommendations.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-29-1917-extract-context-expansion-module.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-29-1918-extract-business-logic-service-layer.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-30-1701-jinja2-server-side-diff-rendering.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-07-30-1730-virtual-scrolling-lazy-rendering.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-03-2106-typescript-migration-plan.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-04-2130-simplify-diff-logic-and-ui.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-18-1954-font-configuration-proposal.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-18-1954-font-implementation-plan.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-18-1954-font-implementation-summary.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-08-19-1430-dark-light-mode-implementation.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/proposals/2025-11-18-0130-alpine-js-dom-manipulation.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-07-29-2100-context-expansion-extraction-report.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-07-30-1647-diff-rendering-performance-analysis.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-07-30-1655-backend-migration-performance-analysis.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-08-18-1200-dead-code-analysis-report.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-09-22-1857-production-readiness-analysis.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-09-22-1949-ui-css-cleanup-analysis.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-30-2201-production-readiness-update.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-31-1253-test-coverage-analysis.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-31-1718-test-coverage-improvement-summary.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-10-31-1720-0.9-release-plan.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-05-1857-css-rationalization-analysis.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-05-2019-color-audit.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-05-2019-phase2-implementation-plan.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2025-11-17-1730-codebase-improvements-analysis.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/reports/2026-02-05-v1.0-release-readiness-audit.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-27-1256-project-setup-and-modern-python-packaging.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-27-1415-git-integration-and-security-implementation.md +0 -0
- {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
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-28-0953-syntax-highlighting-implementation.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-28-1500-commit-comparison-and-ui-enhancements.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-28-1805-untracked-files-implementation-and-bugfix.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-07-31-1730-pygments-syntax-highlighting.compacted.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/internal/sessions/2025-11-18-0130-alpine-js-migration-implementation.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/screenshots/.gitkeep +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/site/assets/logo.png +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/docs/site/index.md +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/pnpm-lock.yaml +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/postcss.config.cjs +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/__init__.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/context_routes.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/diff_routes.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/git_routes.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/helpers.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/blueprints/views.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/diff_parser.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/dummy_data.json +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/git_operations.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/__init__.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/base_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/diff_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/dtos.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/exceptions.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/file_watcher.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/git_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/services/template_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/css/tailwind.input.css +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/data/language_map.json +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/fileComponent.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/groupComponent.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/hunkComponent.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/components/searchComponent.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/context-expansion-ui.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/context-expansion.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/design-system.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/dom-utils.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/full-diff.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/hunk-operations.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/navigation.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/search.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/theme.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/modules/toolbar.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/stores/diffStore.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/stores/searchStore.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/static/js/stores/themeStore.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/diff_groups.html +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/src/difflicious/templates/index.html +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tailwind.config.cjs +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/__init__.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/conftest.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/conftest.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/test_api.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/test_api_detailed.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/integration/test_frontend.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/auto-reload.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/components/fileComponent.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/components/groupComponent.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/components/hunkComponent.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/context-expansion-ui.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/context-expansion.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/design-system.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/diff-state-persistence.test.js.old +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/diffStore-actions.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/dom-utils.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/full-diff.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/navigation.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/search.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/setup.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/stores/diffStore.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/stores/searchStore.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/stores/themeStore.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/js/toolbar.test.js +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/sample_01.diff +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/__init__.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_base_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_diff_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_exceptions.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_file_watcher.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_git_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/services/test_template_service.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/test_git_operations.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/unit/test_diff_parser_line_count.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/unit/test_diff_parser_side_by_side.py +0 -0
- {difflicious-0.13.0 → difflicious-0.14.0}/tests/unit/test_diff_rendering.py +0 -0
- {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:
|
|
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: '
|
|
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
|
-
-
|
|
220
|
-
-
|
|
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
|
|
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
|
|
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 &
|
|
322
|
+
## CSS Architecture & Theming
|
|
322
323
|
|
|
323
|
-
**IMPORTANT:**
|
|
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
|
-
###
|
|
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
|
-
|
|
356
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
372
|
-
- `.file-stat .file-stat-{addition|deletion}` - File change counts
|
|
348
|
+
### Themes
|
|
373
349
|
|
|
374
|
-
|
|
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
|
-
|
|
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
|
-
|
|
383
|
-
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
│ ├──
|
|
449
|
+
│ ├── THEMING.md # Themes and design tokens
|
|
488
450
|
│ ├── TROUBLESHOOTING.md # Common issues
|
|
489
|
-
│
|
|
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/
|
|
509
|
+
- `docs/THEMING.md` - Themes, design tokens, and how to add a theme
|
|
545
510
|
- `docs/TROUBLESHOOTING.md` - Common issues and solutions
|
|
546
|
-
|
|
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](
|
|
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](
|
|
296
|
-
- Explore [DEVELOPING.md](
|
|
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.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: difflicious
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: A
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
47
|
+
---
|
|
46
48
|
|
|
47
49
|
## Screenshots
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|
-
|
|
110
|
+
All options can be set via environment variable or CLI flag:
|
|
80
111
|
|
|
81
|
-
|
|
|
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 (
|
|
86
|
-
| `DIFFLICIOUS_DISABLE_GOOGLE_FONTS` | `false` | Use system fonts only |
|
|
87
|
-
| `DIFFLICIOUS_AUTO_RELOAD` | `true` | Auto-reload on file changes |
|
|
88
|
-
| `
|
|
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
|
-
|
|
141
|
+
---
|
|
111
142
|
|
|
112
|
-
|
|
143
|
+
[](https://pypi.org/project/difflicious/)
|
|
144
|
+
[](https://pypi.org/project/difflicious/)
|
|
145
|
+
[](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
|
-
-
|
|
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
|
+
[](https://pypi.org/project/difflicious/)
|
|
106
|
+
[](https://pypi.org/project/difflicious/)
|
|
107
|
+
[](https://opensource.org/licenses/MIT)
|