jotline 0.9.6__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.
- jotline-0.9.6/.github/ISSUE_TEMPLATE/bug.yml +32 -0
- jotline-0.9.6/.github/ISSUE_TEMPLATE/config.yml +5 -0
- jotline-0.9.6/.github/ISSUE_TEMPLATE/feature.yml +20 -0
- jotline-0.9.6/.github/pull_request_template.md +11 -0
- jotline-0.9.6/.github/workflows/release.yml +92 -0
- jotline-0.9.6/.github/workflows/test.yml +69 -0
- jotline-0.9.6/.gitignore +15 -0
- jotline-0.9.6/CHANGELOG.md +262 -0
- jotline-0.9.6/CONTRIBUTING.md +71 -0
- jotline-0.9.6/LICENSE +21 -0
- jotline-0.9.6/PKG-INFO +734 -0
- jotline-0.9.6/README.md +697 -0
- jotline-0.9.6/ROADMAP.md +51 -0
- jotline-0.9.6/SECURITY.md +19 -0
- jotline-0.9.6/docs/actions.md +52 -0
- jotline-0.9.6/docs/drafts-feature-review.md +75 -0
- jotline-0.9.6/docs/find.svg +204 -0
- jotline-0.9.6/docs/hardening-2026-09-12/context.md +14 -0
- jotline-0.9.6/docs/hardening-2026-09-12/hardening.json +35 -0
- jotline-0.9.6/docs/hardening-2026-09-12/hardening.md +63 -0
- jotline-0.9.6/docs/import-recovery.md +68 -0
- jotline-0.9.6/docs/install.md +132 -0
- jotline-0.9.6/docs/macos-fix.md +28 -0
- jotline-0.9.6/docs/make_screenshot.py +37 -0
- jotline-0.9.6/docs/navigation.md +13 -0
- jotline-0.9.6/docs/platforms.md +41 -0
- jotline-0.9.6/docs/quick-capture.md +98 -0
- jotline-0.9.6/docs/redteam-2026-09-12.md +146 -0
- jotline-0.9.6/docs/redteam-review.md +112 -0
- jotline-0.9.6/docs/release-notes.md +28 -0
- jotline-0.9.6/docs/release-verification.md +103 -0
- jotline-0.9.6/docs/screenshot.svg +189 -0
- jotline-0.9.6/docs/settings.svg +203 -0
- jotline-0.9.6/docs/terminal-testing.md +67 -0
- jotline-0.9.6/docs/theme-research.md +40 -0
- jotline-0.9.6/examples/actions/README.md +5 -0
- jotline-0.9.6/examples/actions/starter-recipes.json +40 -0
- jotline-0.9.6/pyproject.toml +57 -0
- jotline-0.9.6/scripts/install.ps1 +20 -0
- jotline-0.9.6/scripts/install.py +226 -0
- jotline-0.9.6/scripts/release_metadata.py +46 -0
- jotline-0.9.6/scripts/smoke_install.py +177 -0
- jotline-0.9.6/scripts/smoke_pty.py +85 -0
- jotline-0.9.6/src/jotline/__init__.py +2 -0
- jotline-0.9.6/src/jotline/__main__.py +2 -0
- jotline-0.9.6/src/jotline/_windows_fs.py +214 -0
- jotline-0.9.6/src/jotline/action_history.py +118 -0
- jotline-0.9.6/src/jotline/action_recipes.py +56 -0
- jotline-0.9.6/src/jotline/action_ui.py +367 -0
- jotline-0.9.6/src/jotline/actions.py +140 -0
- jotline-0.9.6/src/jotline/app.py +1028 -0
- jotline-0.9.6/src/jotline/capture_ui.py +66 -0
- jotline-0.9.6/src/jotline/cli.py +717 -0
- jotline-0.9.6/src/jotline/cli_doctor.py +252 -0
- jotline-0.9.6/src/jotline/cli_io.py +109 -0
- jotline-0.9.6/src/jotline/commands.py +17 -0
- jotline-0.9.6/src/jotline/completion.py +396 -0
- jotline-0.9.6/src/jotline/connect_ui.py +232 -0
- jotline-0.9.6/src/jotline/crypto.py +166 -0
- jotline-0.9.6/src/jotline/desktop.py +472 -0
- jotline-0.9.6/src/jotline/desktop_data/__init__.py +1 -0
- jotline-0.9.6/src/jotline/desktop_data/gnome.txt +12 -0
- jotline-0.9.6/src/jotline/desktop_data/hyprland.conf +12 -0
- jotline-0.9.6/src/jotline/desktop_data/kde.txt +10 -0
- jotline-0.9.6/src/jotline/desktop_data/omarchy.lua +6 -0
- jotline-0.9.6/src/jotline/desktop_data/org.jotline.capture.desktop +13 -0
- jotline-0.9.6/src/jotline/desktop_data/pipe.txt +9 -0
- jotline-0.9.6/src/jotline/encryption_ui.py +140 -0
- jotline-0.9.6/src/jotline/export.py +342 -0
- jotline-0.9.6/src/jotline/filesystem.py +255 -0
- jotline-0.9.6/src/jotline/history.py +492 -0
- jotline-0.9.6/src/jotline/import_ui.py +116 -0
- jotline-0.9.6/src/jotline/importing.py +259 -0
- jotline-0.9.6/src/jotline/limits.py +13 -0
- jotline-0.9.6/src/jotline/links.py +248 -0
- jotline-0.9.6/src/jotline/markdown_editor.py +850 -0
- jotline-0.9.6/src/jotline/modal.py +131 -0
- jotline-0.9.6/src/jotline/navigation.py +247 -0
- jotline-0.9.6/src/jotline/note_menu.py +89 -0
- jotline-0.9.6/src/jotline/omarchy.py +104 -0
- jotline-0.9.6/src/jotline/preferences.py +154 -0
- jotline-0.9.6/src/jotline/recovery_ui.py +46 -0
- jotline-0.9.6/src/jotline/review_ui.py +190 -0
- jotline-0.9.6/src/jotline/screens.py +229 -0
- jotline-0.9.6/src/jotline/search.py +65 -0
- jotline-0.9.6/src/jotline/settings.py +367 -0
- jotline-0.9.6/src/jotline/store.py +794 -0
- jotline-0.9.6/src/jotline/tasks.py +157 -0
- jotline-0.9.6/src/jotline/templates.py +242 -0
- jotline-0.9.6/src/jotline/workflows.py +347 -0
- jotline-0.9.6/tests/conftest.py +80 -0
- jotline-0.9.6/tests/test_action_experience.py +273 -0
- jotline-0.9.6/tests/test_app.py +181 -0
- jotline-0.9.6/tests/test_cli_append_errors.py +103 -0
- jotline-0.9.6/tests/test_cli_redteam.py +218 -0
- jotline-0.9.6/tests/test_cli_scripting.py +362 -0
- jotline-0.9.6/tests/test_connections.py +229 -0
- jotline-0.9.6/tests/test_desktop.py +370 -0
- jotline-0.9.6/tests/test_drafts_workflows.py +334 -0
- jotline-0.9.6/tests/test_editing_hardening.py +76 -0
- jotline-0.9.6/tests/test_encryption.py +237 -0
- jotline-0.9.6/tests/test_export.py +218 -0
- jotline-0.9.6/tests/test_history.py +472 -0
- jotline-0.9.6/tests/test_hotkeys.py +138 -0
- jotline-0.9.6/tests/test_import_integration_review.py +108 -0
- jotline-0.9.6/tests/test_import_recovery.py +203 -0
- jotline-0.9.6/tests/test_install.py +192 -0
- jotline-0.9.6/tests/test_integration_redteam.py +36 -0
- jotline-0.9.6/tests/test_knowledge_worker.py +168 -0
- jotline-0.9.6/tests/test_markdown.py +113 -0
- jotline-0.9.6/tests/test_markdown_editor.py +443 -0
- jotline-0.9.6/tests/test_markdown_hotkeys.py +84 -0
- jotline-0.9.6/tests/test_markdown_toolbar.py +106 -0
- jotline-0.9.6/tests/test_navigation.py +109 -0
- jotline-0.9.6/tests/test_newcomer_flow.py +73 -0
- jotline-0.9.6/tests/test_note_menu.py +181 -0
- jotline-0.9.6/tests/test_omarchy.py +131 -0
- jotline-0.9.6/tests/test_packaging.py +101 -0
- jotline-0.9.6/tests/test_platforms.py +181 -0
- jotline-0.9.6/tests/test_quick_capture.py +73 -0
- jotline-0.9.6/tests/test_redteam_2026_09_12.py +592 -0
- jotline-0.9.6/tests/test_settings.py +94 -0
- jotline-0.9.6/tests/test_shutdown.py +28 -0
- jotline-0.9.6/tests/test_storage_cache.py +165 -0
- jotline-0.9.6/tests/test_storage_redteam.py +422 -0
- jotline-0.9.6/tests/test_store.py +184 -0
- jotline-0.9.6/tests/test_tasks.py +122 -0
- jotline-0.9.6/tests/test_templates.py +145 -0
- jotline-0.9.6/tests/test_ui_redteam.py +228 -0
- jotline-0.9.6/tests/test_usability_integration.py +248 -0
- jotline-0.9.6/tests/test_windows_console.py +46 -0
- jotline-0.9.6/tests/test_workflow_additions.py +116 -0
- jotline-0.9.6/tests/test_workspaces_tags.py +142 -0
- jotline-0.9.6/uv.lock +360 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report unexpected behavior with reproducible steps.
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: Please use synthetic notes. For security vulnerabilities, follow SECURITY.md instead of posting publicly.
|
|
8
|
+
- type: textarea
|
|
9
|
+
id: environment
|
|
10
|
+
attributes:
|
|
11
|
+
label: Environment
|
|
12
|
+
description: Jotline version, Python version, OS, terminal and terminal version.
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: reproduce
|
|
17
|
+
attributes:
|
|
18
|
+
label: Steps to reproduce
|
|
19
|
+
description: Include the smallest example that shows the problem.
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: textarea
|
|
23
|
+
id: behavior
|
|
24
|
+
attributes:
|
|
25
|
+
label: Expected and actual behavior
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: diagnostics
|
|
30
|
+
attributes:
|
|
31
|
+
label: Diagnostics or screenshots
|
|
32
|
+
description: Optional jotline doctor --json output. Review local paths before sharing; remove personal information.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: Workflow improvement
|
|
2
|
+
description: Explain a task Jotline could make easier.
|
|
3
|
+
body:
|
|
4
|
+
- type: textarea
|
|
5
|
+
id: task
|
|
6
|
+
attributes:
|
|
7
|
+
label: What are you trying to do?
|
|
8
|
+
description: Describe the writing or review task and where you get stuck.
|
|
9
|
+
validations:
|
|
10
|
+
required: true
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: suggestion
|
|
13
|
+
attributes:
|
|
14
|
+
label: Suggested behavior
|
|
15
|
+
description: Include an example and any workaround you use today.
|
|
16
|
+
- type: textarea
|
|
17
|
+
id: fit
|
|
18
|
+
attributes:
|
|
19
|
+
label: Terminal and offline considerations
|
|
20
|
+
description: Optional keyboard, platform, accessibility or external-service requirements.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Describe the problem and the resulting user behavior.
|
|
2
|
+
|
|
3
|
+
## Validation
|
|
4
|
+
|
|
5
|
+
Include relevant test results and any manual terminal checks. For UI changes,
|
|
6
|
+
show the affected workflow with synthetic notes. State platforms not tested.
|
|
7
|
+
|
|
8
|
+
## Compatibility
|
|
9
|
+
|
|
10
|
+
Mention changes to note files, settings, shortcuts, imports, or install behavior,
|
|
11
|
+
and update user-facing documentation where needed.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags: ['v*']
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
jobs:
|
|
8
|
+
verify:
|
|
9
|
+
uses: ./.github/workflows/test.yml
|
|
10
|
+
package:
|
|
11
|
+
needs: verify
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
timeout-minutes: 15
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
16
|
+
with:
|
|
17
|
+
persist-credentials: false
|
|
18
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.12'
|
|
21
|
+
- name: Check release identity
|
|
22
|
+
env:
|
|
23
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
24
|
+
run: python scripts/release_metadata.py
|
|
25
|
+
- name: Build and checksum packages
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install uv==0.12.10
|
|
28
|
+
uv build --clear
|
|
29
|
+
python scripts/release_metadata.py --checksums
|
|
30
|
+
uvx twine==7.0.0 check dist/*.whl dist/*.tar.gz
|
|
31
|
+
- name: Smoke-test the exact release wheel through the public installer
|
|
32
|
+
run: |
|
|
33
|
+
uv venv /tmp/jotline-release-smoke
|
|
34
|
+
python scripts/install.py --from-dir dist --python /tmp/jotline-release-smoke/bin/python --installer pip
|
|
35
|
+
/tmp/jotline-release-smoke/bin/python -I scripts/smoke_install.py
|
|
36
|
+
/tmp/jotline-release-smoke/bin/python -I scripts/smoke_pty.py
|
|
37
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
38
|
+
with:
|
|
39
|
+
name: release-dist
|
|
40
|
+
path: |
|
|
41
|
+
dist/*.whl
|
|
42
|
+
dist/*.tar.gz
|
|
43
|
+
dist/SHA256SUMS
|
|
44
|
+
dist/install.py
|
|
45
|
+
dist/install.ps1
|
|
46
|
+
if-no-files-found: error
|
|
47
|
+
github-release:
|
|
48
|
+
needs: package
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
timeout-minutes: 10
|
|
51
|
+
permissions:
|
|
52
|
+
contents: write
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
55
|
+
with:
|
|
56
|
+
persist-credentials: false
|
|
57
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
58
|
+
with:
|
|
59
|
+
name: release-dist
|
|
60
|
+
path: dist
|
|
61
|
+
- name: Publish GitHub Release assets
|
|
62
|
+
env:
|
|
63
|
+
GH_TOKEN: ${{ github.token }}
|
|
64
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
65
|
+
run: |
|
|
66
|
+
assets=(dist/*.whl dist/*.tar.gz dist/SHA256SUMS dist/install.py dist/install.ps1)
|
|
67
|
+
if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
|
|
68
|
+
gh release upload "$RELEASE_TAG" "${assets[@]}" --clobber
|
|
69
|
+
else
|
|
70
|
+
gh release create "$RELEASE_TAG" "${assets[@]}" --verify-tag --title "Jotline $RELEASE_TAG" --notes-file docs/release-notes.md
|
|
71
|
+
fi
|
|
72
|
+
pypi:
|
|
73
|
+
needs: package
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
timeout-minutes: 10
|
|
76
|
+
environment:
|
|
77
|
+
name: pypi
|
|
78
|
+
url: https://pypi.org/project/jotline/
|
|
79
|
+
permissions:
|
|
80
|
+
id-token: write
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
83
|
+
with:
|
|
84
|
+
name: release-dist
|
|
85
|
+
path: dist
|
|
86
|
+
- name: Stage PyPI packages only
|
|
87
|
+
run: |
|
|
88
|
+
mkdir pypi-dist
|
|
89
|
+
cp dist/*.whl dist/*.tar.gz pypi-dist/
|
|
90
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
91
|
+
with:
|
|
92
|
+
packages-dir: pypi-dist
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: ['**']
|
|
5
|
+
pull_request:
|
|
6
|
+
workflow_call:
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
timeout-minutes: 15
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
17
|
+
python: ['3.11', '3.12', '3.13']
|
|
18
|
+
defaults:
|
|
19
|
+
run:
|
|
20
|
+
shell: bash
|
|
21
|
+
env:
|
|
22
|
+
PYTHONUTF8: '1'
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
with:
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python }}
|
|
30
|
+
- name: Install uv
|
|
31
|
+
timeout-minutes: 2
|
|
32
|
+
run: python -m pip install uv==0.12.10
|
|
33
|
+
- name: Check locked project resolve
|
|
34
|
+
timeout-minutes: 2
|
|
35
|
+
run: uv lock --check --python '${{ matrix.python }}'
|
|
36
|
+
- name: Check latest dependency resolve
|
|
37
|
+
if: matrix.python == '3.13'
|
|
38
|
+
timeout-minutes: 4
|
|
39
|
+
run: uv lock --upgrade --dry-run --python '${{ matrix.python }}'
|
|
40
|
+
- name: Check direct lower bounds
|
|
41
|
+
if: matrix.python == '3.11' && matrix.os == 'ubuntu-latest'
|
|
42
|
+
timeout-minutes: 5
|
|
43
|
+
run: |
|
|
44
|
+
uv venv /tmp/jotline-lower-bound --python '${{ matrix.python }}'
|
|
45
|
+
uv pip install --python /tmp/jotline-lower-bound/bin/python --strict -e . 'textual==8.2.8' 'pytest==8.2.0' 'pytest-asyncio==0.24.0'
|
|
46
|
+
/tmp/jotline-lower-bound/bin/python -m pytest -q tests/test_cli_redteam.py tests/test_packaging.py
|
|
47
|
+
- name: Sync locked test environment
|
|
48
|
+
timeout-minutes: 4
|
|
49
|
+
run: uv sync --locked --extra dev --extra encryption --python '${{ matrix.python }}'
|
|
50
|
+
- name: Run tests
|
|
51
|
+
timeout-minutes: 8
|
|
52
|
+
run: uv run --locked pytest -q -o faulthandler_timeout=60
|
|
53
|
+
- name: Build distributions
|
|
54
|
+
timeout-minutes: 3
|
|
55
|
+
run: uv build --clear
|
|
56
|
+
- name: Checksum packages and copy installers
|
|
57
|
+
timeout-minutes: 2
|
|
58
|
+
run: python scripts/release_metadata.py --checksums
|
|
59
|
+
- name: Install and exercise the built wheel through the public installer
|
|
60
|
+
timeout-minutes: 4
|
|
61
|
+
run: |
|
|
62
|
+
uv venv .smoke-venv --python '${{ matrix.python }}'
|
|
63
|
+
if [ "$RUNNER_OS" = "Windows" ]; then
|
|
64
|
+
smoke_python=.smoke-venv/Scripts/python.exe
|
|
65
|
+
else
|
|
66
|
+
smoke_python=.smoke-venv/bin/python
|
|
67
|
+
fi
|
|
68
|
+
python scripts/install.py --from-dir dist --python "$smoke_python" --installer pip
|
|
69
|
+
"$smoke_python" -I scripts/smoke_install.py
|
jotline-0.9.6/.gitignore
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.9.6 — 2026-09-15
|
|
6
|
+
|
|
7
|
+
- The `v0.9.5` tag never uploaded GitHub Release assets or PyPI files.
|
|
8
|
+
Hatchling now emits Metadata-Version 2.5; the release job still ran
|
|
9
|
+
`twine==6.1.0`, which rejects that version. The check now uses Twine 7.
|
|
10
|
+
The rest of 0.9.5 is unchanged.
|
|
11
|
+
|
|
12
|
+
## 0.9.5 — 2026-09-15
|
|
13
|
+
|
|
14
|
+
- Daily logs can move through days: Previous daily log, Next daily log, and Open
|
|
15
|
+
daily log by date (`YYYY-MM-DD`, `today`, or `yesterday`) in the command
|
|
16
|
+
palette. Missing days use the daily template, as today already did. Optional
|
|
17
|
+
shortcuts start unassigned. `jotline daily` opens today's log in the app;
|
|
18
|
+
`jotline daily --date yesterday` opens another day. `jotline capture --daily --date`
|
|
19
|
+
appends to that log.
|
|
20
|
+
- **Extract selection to new note** saves the selection as an inbox note and
|
|
21
|
+
replaces it with a `[[id|title]]` link, as one undo step.
|
|
22
|
+
- **Process next inbox note** opens the oldest inbox capture (daily logs are
|
|
23
|
+
skipped). Filing that note with Move to collection opens the next. The status
|
|
24
|
+
line shows how many captures remain. `jotline stats` (and `--json`) prints
|
|
25
|
+
workspace counts without note bodies.
|
|
26
|
+
- Connections are a first-class loop: Alt+K (or Ctrl+P → Show connections)
|
|
27
|
+
lists incoming and outgoing notes with the line that contains each link.
|
|
28
|
+
Follow opens the `[[link]]` under the cursor; a missing target can create a
|
|
29
|
+
note and rewrite the typed `[[title]]` to a stable `[[id|title]]`. Click a
|
|
30
|
+
link in preview, or Ctrl+click one in the editor. Compact terminals keep
|
|
31
|
+
`←N →N` on the status line when the connections bar is hidden.
|
|
32
|
+
`jotline backlinks NOTE [--json]` prints the same graph. Wiki links inside
|
|
33
|
+
fenced code or inline code spans no longer count as connections. Typing `[[`
|
|
34
|
+
to complete a note link no longer offers the note you are already in.
|
|
35
|
+
- Linux desktop capture is a shipped feature: `jotline desktop install` writes
|
|
36
|
+
an XDG `jotline capture` desktop entry, `jotline desktop launch` opens the
|
|
37
|
+
capture editor in a terminal, and `jotline desktop recipe` prints Omarchy,
|
|
38
|
+
Hyprland, GNOME, KDE, and clipboard-pipe snippets with this install's
|
|
39
|
+
`jotline` path. No dictation, share sheet, or cloud. Windows and macOS keep
|
|
40
|
+
`jotline capture` and pipe-in.
|
|
41
|
+
- Install no longer requires hunting a wheel filename. A tagged GitHub Release
|
|
42
|
+
attaches the wheel, source archive, `SHA256SUMS`, `install.py`, and
|
|
43
|
+
`install.ps1`. Linux and macOS use
|
|
44
|
+
`curl …/install.py | python3`; Windows PowerShell uses
|
|
45
|
+
`irm …/install.ps1 | iex`. The installer verifies SHA-256 before installing
|
|
46
|
+
with uv, pipx, or pip.
|
|
47
|
+
- `uv tool install jotline` / `pipx install jotline` are the PyPI commands. The
|
|
48
|
+
tag workflow publishes to PyPI with Trusted Publishing after the GitHub
|
|
49
|
+
assets exist. Linux, macOS, and Windows remain the supported-OS contract;
|
|
50
|
+
Windows is not dropped to make a tag publishable.
|
|
51
|
+
- CI installs the built wheel through `scripts/install.py` on Linux, macOS, and
|
|
52
|
+
Windows before a tag can publish.
|
|
53
|
+
|
|
54
|
+
## 0.9.4 — 2026-09-15
|
|
55
|
+
|
|
56
|
+
- GitHub Release assets for the `v0.9.3` tag were never uploaded: Windows
|
|
57
|
+
Python 3.11 failed `test_builder_keyboard_only_preview_close_save` on a 60×20
|
|
58
|
+
terminal because Preview sat one row below the screen. The action builder now
|
|
59
|
+
pins Preview, Save, and Cancel below the form, matching Settings.
|
|
60
|
+
- The test job allows eight minutes for pytest. A slow PDF converter on
|
|
61
|
+
Ubuntu/Python 3.12 previously finished the suite in 299s and still failed the
|
|
62
|
+
five-minute step timeout.
|
|
63
|
+
- Settings opens with Ctrl+, so it works on Mac keyboards that do not send
|
|
64
|
+
F-keys without Fn. F1 still opens Settings where function keys work.
|
|
65
|
+
- On macOS, import and recipe files under `/tmp` or `$TMPDIR` (`/var/folders`)
|
|
66
|
+
work. Those prefixes are OS compatibility links to `/private`; user-created
|
|
67
|
+
aliases later in the path are still refused.
|
|
68
|
+
- Optional Omarchy desktop theme synchronization, including live palette,
|
|
69
|
+
cursor and selection updates in the editor and quick-capture window.
|
|
70
|
+
|
|
71
|
+
- Markdown has an editor toolbar for bold, italic, headings, lists, tasks, links,
|
|
72
|
+
inline code, all other formats, and preview. Mouse selections retain their
|
|
73
|
+
Markdown colours on a theme-tinted background, and the cursor uses the theme
|
|
74
|
+
accent. Theme changes update both immediately.
|
|
75
|
+
- PDF export no longer hangs or crashes on common setups. Every installed
|
|
76
|
+
Chromium-based browser is tried in turn, each with its own profile. On Ubuntu
|
|
77
|
+
23.10 and later, where Chromium's sandbox cannot start, a browser is retried
|
|
78
|
+
without it (the page loads nothing and its CSP blocks scripts). Chrome on
|
|
79
|
+
macOS no longer waits on the keychain or on helper processes after printing,
|
|
80
|
+
Windows' `chrome.exe` launcher no longer counts as finished before the PDF is
|
|
81
|
+
written, and a stuck browser gives up after 30 seconds instead of 180.
|
|
82
|
+
- On Windows, a command run with input from `NUL` (a scheduled task or script)
|
|
83
|
+
is no longer mistaken for a terminal: a missing passphrase fails with the
|
|
84
|
+
`JOTLINE_PASSPHRASE` hint instead of waiting forever, and `capture` reads the
|
|
85
|
+
empty input instead of opening the editor.
|
|
86
|
+
- Markdown editing fixes from a code review. Format link keeps a multi-line
|
|
87
|
+
selection on one line in CRLF notes and accepts a selected `<autolink>`.
|
|
88
|
+
Insert or tidy table no longer pulls a paragraph above the table containing
|
|
89
|
+
a pipe into the table, and dash-only body rows no longer truncate the table. Toggling a code block off works when the selection ends at the start
|
|
90
|
+
of the closing fence. Numbered lists keep task checkboxes. Jump to heading
|
|
91
|
+
keeps a `#` that is part of a title (such as `C#`), lists setext headings,
|
|
92
|
+
and is one command again. Enter after a `- - -` rule no longer starts a
|
|
93
|
+
list. A horizontal rule gets exactly one blank line on each side. The
|
|
94
|
+
side-by-side preview follows the cursor as well as edits, waits for its
|
|
95
|
+
content before scrolling, and stops rendering while the terminal is too
|
|
96
|
+
small to show it. It can be switched off while compact, responds to terminal
|
|
97
|
+
resizes immediately, and picks up externally renamed link titles on refresh. Highlighting rescans only the edited rows, so typing in
|
|
98
|
+
large notes no longer lags. Exports, tasks and highlighting share one rule
|
|
99
|
+
for fenced code, and `[[links]]` inside code spans are left alone.
|
|
100
|
+
- Storage fixes from the same review. A revision removed by another process
|
|
101
|
+
between listing and stat no longer makes a note's history read as empty;
|
|
102
|
+
permission and I/O errors still surface. Concurrent backup pruning no longer
|
|
103
|
+
reports a failed daily backup when an archive disappears before stat.
|
|
104
|
+
Exporting a note snapshots its text first, so typing during a slow PDF
|
|
105
|
+
export cannot change what is written. A folder import skips an unreadable
|
|
106
|
+
entry instead of abandoning the rest of that folder.
|
|
107
|
+
- Tags are highlighted with the rule the vault uses to index them, so `#123`
|
|
108
|
+
now counts. Tags inside URL destinations and fragments are not highlighted.
|
|
109
|
+
- Moving a note now reports `Moved to X`, prefixes failures with `Note was not
|
|
110
|
+
moved:`, refreshes connections, and shows any backup warning.
|
|
111
|
+
- Workspace mismatch errors now consistently name the `--workspace NAME` option.
|
|
112
|
+
CLI export uses the same terminal-control refusal message as other commands.
|
|
113
|
+
- Applying an empty note selection now shows `Select at least one note first`.
|
|
114
|
+
- Internal cleanup with no behaviour change: the CLI dispatches commands
|
|
115
|
+
through one handler per command, repeated messages and limits are named
|
|
116
|
+
constants, temporary-file removal and modal cancel share one helper each,
|
|
117
|
+
and dead code was removed.
|
|
118
|
+
- Full Markdown editing in the app. The editor highlights Markdown syntax in the
|
|
119
|
+
current theme's colours, with no new dependency. Enter continues bullet,
|
|
120
|
+
numbered, task and quote lines, and Enter on an empty item ends the list.
|
|
121
|
+
Formatting commands now toggle off. New commands: strikethrough, heading
|
|
122
|
+
levels 1–6, numbered and task lists, code blocks, links, images, horizontal
|
|
123
|
+
rules, indent and outdent, and insert or tidy table. Ctrl+P → Toggle
|
|
124
|
+
side-by-side Markdown preview renders while you type, and Jump to heading
|
|
125
|
+
lists a note's headings. Previews show checkboxes and note-link titles as
|
|
126
|
+
exports do. Every new command can take an optional shortcut, and F1 → Editor
|
|
127
|
+
turns highlighting or list continuation off.
|
|
128
|
+
- Commands that take a note (`append`, `prepend`, `open`, `run`, `export`,
|
|
129
|
+
`tag`) accept a unique ID prefix of four or more characters, an exact title
|
|
130
|
+
(any letter case), or `last`. Ambiguous references are refused with the
|
|
131
|
+
matching IDs. The missing-note error now reads "No note with ID or title …".
|
|
132
|
+
- `capture`, `append`, `prepend` and `import` accept `--encoding NAME` and
|
|
133
|
+
`--replace-invalid`. Decoding errors suggest both, and folder imports report
|
|
134
|
+
a bad file in plain language instead of a codec error. Undecodable bytes in
|
|
135
|
+
command-line text are reported the same way.
|
|
136
|
+
- `tags`, `workspaces` and `actions` accept `--json`, joining `list` and `doctor`.
|
|
137
|
+
- `jotline completion bash|zsh|fish` prints a completion script for commands,
|
|
138
|
+
options, note IDs, tags, workspaces and actions.
|
|
139
|
+
- `jotline tasks` lists open `- [ ]` tasks across the workspace, with optional
|
|
140
|
+
due dates (`due:2026-09-20` or `📅 2026-09-20`), a search filter, `--due`,
|
|
141
|
+
`--done` and `--json`. `jotline done NOTE:LINE` checks one off (`--undo`
|
|
142
|
+
reopens it). In the app, Ctrl+P → Open tasks across notes jumps to a task.
|
|
143
|
+
- `jotline capture` with no text in a terminal opens a small capture editor
|
|
144
|
+
(Ctrl+S saves, Esc cancels). [docs/quick-capture.md](docs/quick-capture.md)
|
|
145
|
+
binds it to a global key on Omarchy/Hyprland, GNOME and KDE.
|
|
146
|
+
- `jotline export` saves HTML, Word (`.docx`) and PDF with `--format` or an
|
|
147
|
+
`--output` file extension; `--force` replaces an existing file. HTML is built
|
|
148
|
+
in; Word uses pandoc or LibreOffice and PDF a Chromium-based browser,
|
|
149
|
+
LibreOffice or pandoc. Ctrl+P → Export note as… does the same in the app.
|
|
150
|
+
- Opt-in encryption for sensitive notes: `jotline encryption setup`, then
|
|
151
|
+
`jotline encrypt NOTE` or Ctrl+P → Encrypt this note. Note text is sealed with
|
|
152
|
+
AES-256-GCM under a passphrase-wrapped key; unencrypted saved versions of the
|
|
153
|
+
note are removed, and locked notes show as "Encrypted note (locked)". Needs
|
|
154
|
+
the `cryptography` package (`jotline[encryption]`). There is no passphrase
|
|
155
|
+
recovery. Versions before this release show encrypted notes as unreadable text.
|
|
156
|
+
|
|
157
|
+
## 0.9.3 — 2026-09-12
|
|
158
|
+
|
|
159
|
+
- `jotline append` and `prepend` put the text on its own line. They add one
|
|
160
|
+
line break in the note's newline style when the text would otherwise run into
|
|
161
|
+
the note, which merged words and created false tags such as `#ideaappended`.
|
|
162
|
+
Pass `--no-newline` for the previous exact join. Actions are unchanged.
|
|
163
|
+
- CLI errors are plain language: a missing note reads "No note with ID …", a
|
|
164
|
+
missing file no longer shows `[Errno 2]`, and non-UTF-8 input names its source
|
|
165
|
+
instead of printing a Python codec error.
|
|
166
|
+
- Tagged as `v0.9.3`; the release workflow did not publish wheels. Install 0.9.4.
|
|
167
|
+
|
|
168
|
+
## 0.9.2 — 2026-09-12
|
|
169
|
+
|
|
170
|
+
Fixes from the 2026-09-12 multi-agent red team (storage, CLI, parsing, UI).
|
|
171
|
+
See [docs/redteam-2026-09-12.md](docs/redteam-2026-09-12.md).
|
|
172
|
+
|
|
173
|
+
- Saves fall back to rename on filesystems that refuse hard links (FAT/exFAT
|
|
174
|
+
media, SMB shares, shared folders). A failed publish now puts the original
|
|
175
|
+
note straight back under its own name, and any warning that names a retained
|
|
176
|
+
file survives sidebar refreshes.
|
|
177
|
+
- A daily backup that cannot be written (full disk, unsafe backup folder) no
|
|
178
|
+
longer blocks note saves or recovery copies; it becomes a warning. The daily
|
|
179
|
+
archive is validated once per session instead of on every save, and stale
|
|
180
|
+
temporary files from interrupted writes are removed after an hour and listed
|
|
181
|
+
by `jotline doctor`.
|
|
182
|
+
- One invalid settings value no longer resets every other preference: valid
|
|
183
|
+
fields are kept, the bad field is named, and the next save preserves actions,
|
|
184
|
+
views, hotkeys and unknown keys. Unreadable settings files are set aside as
|
|
185
|
+
`.jotline-settings.json.invalid-*.json` rather than overwritten.
|
|
186
|
+
- Opening a note never rewrites it: notes with Unicode line separators, form
|
|
187
|
+
feeds, lone CR or mixed newlines stay clean until you actually edit them, and
|
|
188
|
+
no longer trigger false external-change dialogs.
|
|
189
|
+
- Task toggle, heading/list/quote formatting, find context and arrange now use
|
|
190
|
+
the editor's own line model, fixing a crash on lone-CR notes and inserted
|
|
191
|
+
blank lines on CRLF notes.
|
|
192
|
+
- Modal dialogs ignore a second dismissal (key repeat, Enter then Escape, or a
|
|
193
|
+
mouse double-click), which previously ended the app or silently closed the
|
|
194
|
+
action builder.
|
|
195
|
+
- Ctrl+Q, Ctrl+N, Ctrl+S, opening a note and switching workspace re-show the
|
|
196
|
+
external-change dialog after it was dismissed; re-selecting the open note
|
|
197
|
+
keeps its undo history.
|
|
198
|
+
- A byte-order mark added by an external editor no longer strips a note's
|
|
199
|
+
collection, star, workspace and created date; folder imports of Jotline's own
|
|
200
|
+
note files keep that metadata too.
|
|
201
|
+
- Markdown preview refuses notes with more than 600 content lines or very wide
|
|
202
|
+
tables, which stalled the interface for ten seconds or more.
|
|
203
|
+
- Jump to heading used a quadratic regular expression; a 20 KB heading line
|
|
204
|
+
took seconds and a long one minutes.
|
|
205
|
+
- Text search no longer matches one or two characters against random digits of
|
|
206
|
+
every note ID; ID matching needs an 8-character prefix. Links and `title:`
|
|
207
|
+
filters match the full first line, not only its first 100 characters.
|
|
208
|
+
- Terminal-safety checks accept ordinary text such as CRLF, joined emoji,
|
|
209
|
+
soft hyphens and byte-order marks; `jotline run` checks exported output
|
|
210
|
+
before any step applies and accepts `--raw`. Closed stdin and a closed pipe
|
|
211
|
+
reader are handled quietly; `--vault ""` is rejected and a relative
|
|
212
|
+
`XDG_DATA_HOME` is ignored. Shell commands wait up to ten seconds for the
|
|
213
|
+
vault lock instead of one.
|
|
214
|
+
- Revision history orders versions by write time, so a clock step backwards
|
|
215
|
+
cannot offer stale content or prune the newest version.
|
|
216
|
+
- A corrupt action-history file is set aside and logging resumes. One stray
|
|
217
|
+
entry in the templates folder no longer hides every template. Symlinked
|
|
218
|
+
ancestors are reported as such instead of "Not a directory".
|
|
219
|
+
- Read-only commands fail with "Vault does not exist" instead of creating an
|
|
220
|
+
empty vault at a mistyped path; the preview labels unrendered HTML blocks.
|
|
221
|
+
|
|
222
|
+
## 0.9.1 — 2026-09-12
|
|
223
|
+
|
|
224
|
+
- Bound cached search results to one second before the next scan rereads them.
|
|
225
|
+
External edits that preserve all tracked timestamps no longer remain cached
|
|
226
|
+
indefinitely. Refresh vault still forces an immediate reread.
|
|
227
|
+
- Add deterministic coverage for timestamp collisions and cache expiry.
|
|
228
|
+
|
|
229
|
+
## 0.9.0 — 2026-09-12
|
|
230
|
+
|
|
231
|
+
- Added an action builder, starter recipes, result previews, action editing and
|
|
232
|
+
duplication, recipe sharing, and bounded action run history.
|
|
233
|
+
- Added visible navigation controls, contextual empty states, and an optional
|
|
234
|
+
quick-start guide that preserves the current note.
|
|
235
|
+
- Added saved-view editing, renaming, duplication and updates, filter controls,
|
|
236
|
+
and an active-view indicator.
|
|
237
|
+
- Added recovery comparison with explicit preservation of the full local draft
|
|
238
|
+
before reviewing an external version.
|
|
239
|
+
- Added folder and Drafts JSON export import with preview, metadata mapping,
|
|
240
|
+
duplicate handling and partial-result summaries.
|
|
241
|
+
- Added versioned release packages with checksums and a cross-platform test gate,
|
|
242
|
+
installation/update/uninstall instructions, and contributor templates.
|
|
243
|
+
- Added private vulnerability reporting, a security policy, a public roadmap,
|
|
244
|
+
and a terminal/accessibility testing checklist.
|
|
245
|
+
- Corrected replacement failure feedback, backward selection search navigation,
|
|
246
|
+
and canonical date-filter validation.
|
|
247
|
+
- Restored Tab/Shift+Tab navigation inside modals and removed a redundant
|
|
248
|
+
Markdown preview render.
|
|
249
|
+
|
|
250
|
+
Existing notes and settings remain readable. Imports create new notes and do not
|
|
251
|
+
overwrite existing notes. Compact date filters must use `YYYY-MM-DD`. Local
|
|
252
|
+
action history is stored separately from note revision history.
|
|
253
|
+
Older releases do not recognize the new `quote` and `restore` recipe steps;
|
|
254
|
+
back up settings before downgrading, or remove those recipes using 0.9.0 first.
|
|
255
|
+
|
|
256
|
+
## 0.8.1 and earlier
|
|
257
|
+
|
|
258
|
+
The pre-release source history introduced Markdown capture, collections,
|
|
259
|
+
workspaces, tags, templates, history/backups, saved views, local JSON actions,
|
|
260
|
+
native Windows/macOS support and sidebar context menus. See the Git history and
|
|
261
|
+
[earlier review](docs/redteam-review.md) for the historical fixes. Version 0.9.0
|
|
262
|
+
is the first packaged GitHub release.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Jotline values fast capture, readable files, and a small keyboard-first interface.
|
|
4
|
+
|
|
5
|
+
Start with [ROADMAP.md](ROADMAP.md) for priorities and scoped starter tasks.
|
|
6
|
+
Use the workflow-improvement issue template to describe user needs before a
|
|
7
|
+
large change. Recipes and terminal compatibility reports are useful contributions
|
|
8
|
+
alongside code. Security issues should follow [SECURITY.md](SECURITY.md).
|
|
9
|
+
|
|
10
|
+
Install with `uv sync --extra dev`. Before opening a pull request, run the locked
|
|
11
|
+
suite with `uv run --locked pytest -q`. CI also checks an unlocked latest resolve
|
|
12
|
+
with `uv lock --upgrade --dry-run`, a direct lower-bound environment, and a clean
|
|
13
|
+
installed-wheel smoke run. For local release checks, build with `uv build --clear`
|
|
14
|
+
and run `python scripts/install.py --from-dir dist --installer pip` into a fresh
|
|
15
|
+
venv, then `python -I scripts/smoke_install.py` from that environment.
|
|
16
|
+
|
|
17
|
+
CI runs the complete suite and installed-wheel CLI/TUI smoke checks on Linux,
|
|
18
|
+
macOS, and Windows with Python 3.11–3.13. POSIX-only filesystem cases are marked
|
|
19
|
+
explicitly; Windows has separate native handle, junction, and locking coverage.
|
|
20
|
+
Storage code uses `jotline.filesystem.fs`: native `os` on Unix and a pinned-handle
|
|
21
|
+
backend on Windows. Keep file I/O UTF-8 with explicit newlines; do not substitute
|
|
22
|
+
unprotected path operations for descriptor-relative storage calls.
|
|
23
|
+
|
|
24
|
+
Storage changes should cover round trips, external edits, failed saves, and doctor
|
|
25
|
+
diagnostics. UI changes should exercise the relevant keyboard workflow with Textual's
|
|
26
|
+
Pilot. Use temporary vaults for testing; never include personal notes in commits or
|
|
27
|
+
screenshots.
|
|
28
|
+
|
|
29
|
+
Follow [the terminal and accessibility checklist](docs/terminal-testing.md) for
|
|
30
|
+
native UI verification. Headless tests cannot certify clipboard, screen-reader,
|
|
31
|
+
or input-method compatibility. On POSIX, the fresh wheel environment can also
|
|
32
|
+
run `python -I scripts/smoke_pty.py` to exercise actual terminal input and saves.
|
|
33
|
+
|
|
34
|
+
The package version is single-sourced in `src/jotline/__init__.py`; `pyproject.toml`
|
|
35
|
+
reads it dynamically. Release pull requests should update that value and any
|
|
36
|
+
user-facing status text together.
|
|
37
|
+
|
|
38
|
+
For bugs, include the Jotline/Python version, terminal, steps to reproduce, and the
|
|
39
|
+
error message. `jotline doctor --json` reports counts, paths, versions, limits,
|
|
40
|
+
and local state without note bodies. Review local paths before attaching it. Do not
|
|
41
|
+
include secrets or private notes. New integrations should be explicitly
|
|
42
|
+
user-triggered and preserve the offline core.
|
|
43
|
+
|
|
44
|
+
## Releases
|
|
45
|
+
|
|
46
|
+
Update the package version, main README, [CHANGELOG.md](CHANGELOG.md), and
|
|
47
|
+
`docs/release-notes.md` together. Build and exercise the installed wheel locally.
|
|
48
|
+
`python scripts/release_metadata.py --checksums` checks package names and writes
|
|
49
|
+
SHA-256 checksums after `uv build --clear`.
|
|
50
|
+
|
|
51
|
+
Push an annotated matching `vX.Y.Z` tag to start the release workflow. It runs
|
|
52
|
+
the complete Linux/macOS/Windows test and installer-smoke matrix, then publishes
|
|
53
|
+
the wheel, source archive, checksums, and `install.py` / `install.ps1` to GitHub
|
|
54
|
+
Releases. A later job uploads the wheel and sdist to PyPI with Trusted
|
|
55
|
+
Publishing. The tag must match the single-sourced package version. A failed
|
|
56
|
+
verification job prevents publication. Never move an already-published tag; fix
|
|
57
|
+
the issue and release a new patch version. Do not drop Windows from the matrix
|
|
58
|
+
to make a tag publishable.
|
|
59
|
+
|
|
60
|
+
Before the first PyPI upload, add a pending publisher at
|
|
61
|
+
https://pypi.org/manage/account/publishing/ :
|
|
62
|
+
|
|
63
|
+
- PyPI project name: `jotline`
|
|
64
|
+
- Owner: `CaulShiver`
|
|
65
|
+
- Repository: `jotline`
|
|
66
|
+
- Workflow name: `release.yml`
|
|
67
|
+
- Environment name: `pypi`
|
|
68
|
+
|
|
69
|
+
The GitHub Release with assets is the install path that does not wait on that
|
|
70
|
+
one-time PyPI click. After it succeeds, `uv tool install jotline` works on
|
|
71
|
+
Linux, macOS, and Windows.
|
jotline-0.9.6/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CaulShiver
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|