ffs-triumph 0.1.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.
- ffs_triumph-0.1.0/.github/workflows/ci.yml +25 -0
- ffs_triumph-0.1.0/.github/workflows/publish.yml +39 -0
- ffs_triumph-0.1.0/.gitignore +26 -0
- ffs_triumph-0.1.0/.python-version +1 -0
- ffs_triumph-0.1.0/LICENSE +21 -0
- ffs_triumph-0.1.0/PKG-INFO +137 -0
- ffs_triumph-0.1.0/README.md +106 -0
- ffs_triumph-0.1.0/fit_for_print.js +13 -0
- ffs_triumph-0.1.0/pyproject.toml +52 -0
- ffs_triumph-0.1.0/src/ffs_triumph/__init__.py +13 -0
- ffs_triumph-0.1.0/src/ffs_triumph/__main__.py +6 -0
- ffs_triumph-0.1.0/src/ffs_triumph/cli.py +388 -0
- ffs_triumph-0.1.0/src/ffs_triumph/client.py +203 -0
- ffs_triumph-0.1.0/src/ffs_triumph/config.py +120 -0
- ffs_triumph-0.1.0/src/ffs_triumph/document.py +146 -0
- ffs_triumph-0.1.0/src/ffs_triumph/pdf.py +61 -0
- ffs_triumph-0.1.0/src/ffs_triumph/render.py +243 -0
- ffs_triumph-0.1.0/tests/test_render.py +108 -0
- ffs_triumph-0.1.0/uv.lock +587 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- name: Install
|
|
21
|
+
run: pip install -e ".[dev]"
|
|
22
|
+
- name: Lint
|
|
23
|
+
run: ruff check .
|
|
24
|
+
- name: Test
|
|
25
|
+
run: pytest -q
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Publishes on a version tag (e.g. v0.1.0) using PyPI Trusted Publishing (OIDC).
|
|
4
|
+
# One-time setup: on PyPI, add this repo + workflow ("publish.yml") and the
|
|
5
|
+
# "pypi" environment as a Trusted Publisher for the `ffs-triumph` project.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
- name: Build sdist + wheel
|
|
20
|
+
run: |
|
|
21
|
+
pip install build
|
|
22
|
+
python -m build
|
|
23
|
+
- uses: actions/upload-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
needs: build
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
environment: pypi
|
|
32
|
+
permissions:
|
|
33
|
+
id-token: write # required for trusted publishing
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/download-artifact@v4
|
|
36
|
+
with:
|
|
37
|
+
name: dist
|
|
38
|
+
path: dist/
|
|
39
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Secrets
|
|
2
|
+
.env
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
.venv/
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.pyc
|
|
8
|
+
|
|
9
|
+
# Build artifacts
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
*.egg-info/
|
|
13
|
+
|
|
14
|
+
# Local user config (may contain email)
|
|
15
|
+
ffs.toml
|
|
16
|
+
|
|
17
|
+
# Tool output & caches
|
|
18
|
+
.cache/
|
|
19
|
+
out/
|
|
20
|
+
output/
|
|
21
|
+
output_full/
|
|
22
|
+
*.pdf
|
|
23
|
+
manual.html
|
|
24
|
+
sample.html
|
|
25
|
+
.vscode
|
|
26
|
+
.claude
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jesse Erlbaum
|
|
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.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ffs-triumph
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: FFS — Full-manual Fetcher & Stitcher: turn a Triumph service manual into an offline PDF
|
|
5
|
+
Project-URL: Homepage, https://github.com/jerlbaum/ffs-triumph
|
|
6
|
+
Project-URL: Repository, https://github.com/jerlbaum/ffs-triumph
|
|
7
|
+
Project-URL: Issues, https://github.com/jerlbaum/ffs-triumph/issues
|
|
8
|
+
Author-email: Jesse Erlbaum <jesse@erlbaum.net>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: motorcycle,offline,pdf,scraper,service-manual,triumph
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
24
|
+
Requires-Dist: lxml>=5.0
|
|
25
|
+
Requires-Dist: playwright>=1.49
|
|
26
|
+
Requires-Dist: requests>=2.31
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# FFS — Full-manual Fetcher & Stitcher
|
|
33
|
+
|
|
34
|
+
*For F***'s Sake, just let me print my own service manual.*
|
|
35
|
+
|
|
36
|
+
`ffs-triumph` turns a [Triumph Technical Information](https://triumphtechnicalinformation.com)
|
|
37
|
+
service manual — delivered as a JavaScript single-page app you can't download or
|
|
38
|
+
print — into a single, self-contained, **paginated PDF** for offline use.
|
|
39
|
+
|
|
40
|
+
It logs in with your account, finds your motorcycle from your subscription,
|
|
41
|
+
crawls the whole manual, converts the site's structured content into HTML,
|
|
42
|
+
inlines the diagrams, and renders a clean PDF with a title page, table of
|
|
43
|
+
contents, page numbers, and proper page breaks.
|
|
44
|
+
|
|
45
|
+
> **Disclaimer.** This tool is for owners with **legitimate, licensed access**
|
|
46
|
+
> archiving **their own** manual for **personal, offline** use. You need a valid
|
|
47
|
+
> Triumph Technical Information subscription; it only ever fetches content your
|
|
48
|
+
> account is already entitled to. It is **not affiliated with or endorsed by
|
|
49
|
+
> Triumph**, and you are responsible for complying with the site's terms of use.
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install ffs-triumph
|
|
55
|
+
ffs install-browser # one-time: downloads the Chromium build for PDF rendering
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
(`install-browser` runs `python -m playwright install chromium`. You can skip it
|
|
59
|
+
if you only use `--html-only`.)
|
|
60
|
+
|
|
61
|
+
## Quick start
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Provide credentials (or you'll be prompted):
|
|
65
|
+
export TTI_EMAIL="you@example.com"
|
|
66
|
+
export TTI_PASSWORD="..."
|
|
67
|
+
|
|
68
|
+
ffs build out/
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That's it. With one motorcycle on your account and one service manual in your
|
|
72
|
+
language, **no other input is needed** — `ffs` auto-detects your VIN from your
|
|
73
|
+
subscription, picks the Service Manual, and writes the PDF to `out/`.
|
|
74
|
+
|
|
75
|
+
Not sure what's available? Inspect your account first:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
ffs discover # lists your VIN(s), product context, and documents
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## How it figures things out
|
|
82
|
+
|
|
83
|
+
From just your **email + password**:
|
|
84
|
+
|
|
85
|
+
1. **Your bike** — read from your subscription's VIN(s). One → used automatically;
|
|
86
|
+
several → you pick from a menu showing year/model. (Override with `--vin`.)
|
|
87
|
+
2. **Product context** — model code/year, serial, engine number and market are
|
|
88
|
+
looked up from the VIN automatically.
|
|
89
|
+
3. **The manual** — the single `Service Manual` document for your language is
|
|
90
|
+
selected automatically. Use `--doc-type "Owner Handbook"` for a different type,
|
|
91
|
+
`--all-types` to browse everything, or `--root-id <id>` to pick exactly.
|
|
92
|
+
|
|
93
|
+
After a successful run it offers to remember your email + bike + manual in
|
|
94
|
+
`~/.config/ffs-triumph/config.toml` (your password is **never** saved), so the
|
|
95
|
+
next run is just `ffs build out/`.
|
|
96
|
+
|
|
97
|
+
## Commands
|
|
98
|
+
|
|
99
|
+
| Command | Purpose |
|
|
100
|
+
|---------|---------|
|
|
101
|
+
| `ffs build OUTPUT` | Fetch the manual and render `OUTPUT/manual.html` + the PDF |
|
|
102
|
+
| `ffs discover` | List your VIN(s), product context, and available documents |
|
|
103
|
+
| `ffs list` | Print the manual's table of contents with topic IDs |
|
|
104
|
+
| `ffs audit` | Verify every topic fetches with non-empty content |
|
|
105
|
+
| `ffs install-browser` | Download the Chromium build needed for PDF rendering |
|
|
106
|
+
|
|
107
|
+
### Useful `build` options
|
|
108
|
+
|
|
109
|
+
| Flag | Purpose |
|
|
110
|
+
|------|---------|
|
|
111
|
+
| `--html-only` | Assemble HTML but skip PDF rendering (no Chromium needed) |
|
|
112
|
+
| `--topic ID` | Only that topic's subtree — fast for previewing |
|
|
113
|
+
| `--limit N` | Render at most N topics |
|
|
114
|
+
| `--inline-images` | Embed images as base64 in one large portable HTML file (default: write to `OUTPUT/images/`; the PDF is self-contained either way) |
|
|
115
|
+
| `--cache-dir DIR` | Where fetched topics/images are cached (default `.cache`) |
|
|
116
|
+
| `--no-cache` | Ignore the cache (still writes it) |
|
|
117
|
+
| `-v` | Verbose progress |
|
|
118
|
+
|
|
119
|
+
Credentials come from `--email`/`--password`, the `TTI_EMAIL`/`TTI_PASSWORD`
|
|
120
|
+
environment variables, a local `.env`, the saved config, or interactive prompts —
|
|
121
|
+
in that order. Every prompt has a corresponding flag, so the tool is fully
|
|
122
|
+
scriptable / CI-friendly.
|
|
123
|
+
|
|
124
|
+
## Use as a library
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from ffs_triumph import TriumphClient, ManualConfig
|
|
128
|
+
|
|
129
|
+
client = TriumphClient("you@example.com", "password")
|
|
130
|
+
vin = client.subscribed_vins()[0]
|
|
131
|
+
client.config = ManualConfig.from_product(client.product_search(vin), root_id="<doc id>")
|
|
132
|
+
root = client.get_root() # the manual's table-of-contents tree
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# FFS — Full-manual Fetcher & Stitcher
|
|
2
|
+
|
|
3
|
+
*For F***'s Sake, just let me print my own service manual.*
|
|
4
|
+
|
|
5
|
+
`ffs-triumph` turns a [Triumph Technical Information](https://triumphtechnicalinformation.com)
|
|
6
|
+
service manual — delivered as a JavaScript single-page app you can't download or
|
|
7
|
+
print — into a single, self-contained, **paginated PDF** for offline use.
|
|
8
|
+
|
|
9
|
+
It logs in with your account, finds your motorcycle from your subscription,
|
|
10
|
+
crawls the whole manual, converts the site's structured content into HTML,
|
|
11
|
+
inlines the diagrams, and renders a clean PDF with a title page, table of
|
|
12
|
+
contents, page numbers, and proper page breaks.
|
|
13
|
+
|
|
14
|
+
> **Disclaimer.** This tool is for owners with **legitimate, licensed access**
|
|
15
|
+
> archiving **their own** manual for **personal, offline** use. You need a valid
|
|
16
|
+
> Triumph Technical Information subscription; it only ever fetches content your
|
|
17
|
+
> account is already entitled to. It is **not affiliated with or endorsed by
|
|
18
|
+
> Triumph**, and you are responsible for complying with the site's terms of use.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install ffs-triumph
|
|
24
|
+
ffs install-browser # one-time: downloads the Chromium build for PDF rendering
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
(`install-browser` runs `python -m playwright install chromium`. You can skip it
|
|
28
|
+
if you only use `--html-only`.)
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Provide credentials (or you'll be prompted):
|
|
34
|
+
export TTI_EMAIL="you@example.com"
|
|
35
|
+
export TTI_PASSWORD="..."
|
|
36
|
+
|
|
37
|
+
ffs build out/
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
That's it. With one motorcycle on your account and one service manual in your
|
|
41
|
+
language, **no other input is needed** — `ffs` auto-detects your VIN from your
|
|
42
|
+
subscription, picks the Service Manual, and writes the PDF to `out/`.
|
|
43
|
+
|
|
44
|
+
Not sure what's available? Inspect your account first:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
ffs discover # lists your VIN(s), product context, and documents
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## How it figures things out
|
|
51
|
+
|
|
52
|
+
From just your **email + password**:
|
|
53
|
+
|
|
54
|
+
1. **Your bike** — read from your subscription's VIN(s). One → used automatically;
|
|
55
|
+
several → you pick from a menu showing year/model. (Override with `--vin`.)
|
|
56
|
+
2. **Product context** — model code/year, serial, engine number and market are
|
|
57
|
+
looked up from the VIN automatically.
|
|
58
|
+
3. **The manual** — the single `Service Manual` document for your language is
|
|
59
|
+
selected automatically. Use `--doc-type "Owner Handbook"` for a different type,
|
|
60
|
+
`--all-types` to browse everything, or `--root-id <id>` to pick exactly.
|
|
61
|
+
|
|
62
|
+
After a successful run it offers to remember your email + bike + manual in
|
|
63
|
+
`~/.config/ffs-triumph/config.toml` (your password is **never** saved), so the
|
|
64
|
+
next run is just `ffs build out/`.
|
|
65
|
+
|
|
66
|
+
## Commands
|
|
67
|
+
|
|
68
|
+
| Command | Purpose |
|
|
69
|
+
|---------|---------|
|
|
70
|
+
| `ffs build OUTPUT` | Fetch the manual and render `OUTPUT/manual.html` + the PDF |
|
|
71
|
+
| `ffs discover` | List your VIN(s), product context, and available documents |
|
|
72
|
+
| `ffs list` | Print the manual's table of contents with topic IDs |
|
|
73
|
+
| `ffs audit` | Verify every topic fetches with non-empty content |
|
|
74
|
+
| `ffs install-browser` | Download the Chromium build needed for PDF rendering |
|
|
75
|
+
|
|
76
|
+
### Useful `build` options
|
|
77
|
+
|
|
78
|
+
| Flag | Purpose |
|
|
79
|
+
|------|---------|
|
|
80
|
+
| `--html-only` | Assemble HTML but skip PDF rendering (no Chromium needed) |
|
|
81
|
+
| `--topic ID` | Only that topic's subtree — fast for previewing |
|
|
82
|
+
| `--limit N` | Render at most N topics |
|
|
83
|
+
| `--inline-images` | Embed images as base64 in one large portable HTML file (default: write to `OUTPUT/images/`; the PDF is self-contained either way) |
|
|
84
|
+
| `--cache-dir DIR` | Where fetched topics/images are cached (default `.cache`) |
|
|
85
|
+
| `--no-cache` | Ignore the cache (still writes it) |
|
|
86
|
+
| `-v` | Verbose progress |
|
|
87
|
+
|
|
88
|
+
Credentials come from `--email`/`--password`, the `TTI_EMAIL`/`TTI_PASSWORD`
|
|
89
|
+
environment variables, a local `.env`, the saved config, or interactive prompts —
|
|
90
|
+
in that order. Every prompt has a corresponding flag, so the tool is fully
|
|
91
|
+
scriptable / CI-friendly.
|
|
92
|
+
|
|
93
|
+
## Use as a library
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from ffs_triumph import TriumphClient, ManualConfig
|
|
97
|
+
|
|
98
|
+
client = TriumphClient("you@example.com", "password")
|
|
99
|
+
vin = client.subscribed_vins()[0]
|
|
100
|
+
client.config = ManualConfig.from_product(client.product_search(vin), root_id="<doc id>")
|
|
101
|
+
root = client.get_root() # the manual's table-of-contents tree
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
|
|
3
|
+
Modify the DOM so that we can print it.
|
|
4
|
+
|
|
5
|
+
https://triumphtechnicalinformation.com/document/690d9a07cf4323000922e147?topics=5908801803,5814189963&active=1
|
|
6
|
+
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
var jq = document.createElement('script');
|
|
10
|
+
jq.src = "https://code.jquery.com/jquery-3.7.1.min.js"; // Use a specific, recent version
|
|
11
|
+
document.getElementsByTagName('head')[0].appendChild(jq);
|
|
12
|
+
|
|
13
|
+
// Remove watermark div
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ffs-triumph"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "FFS — Full-manual Fetcher & Stitcher: turn a Triumph service manual into an offline PDF"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Jesse Erlbaum", email = "jesse@erlbaum.net" }]
|
|
13
|
+
keywords = ["triumph", "motorcycle", "service-manual", "pdf", "offline", "scraper"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: End Users/Desktop",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Topic :: Utilities",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"beautifulsoup4>=4.12",
|
|
28
|
+
"lxml>=5.0",
|
|
29
|
+
"playwright>=1.49",
|
|
30
|
+
"requests>=2.31",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
dev = ["pytest>=8.0", "ruff>=0.6"]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/jerlbaum/ffs-triumph"
|
|
38
|
+
Repository = "https://github.com/jerlbaum/ffs-triumph"
|
|
39
|
+
Issues = "https://github.com/jerlbaum/ffs-triumph/issues"
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
ffs = "ffs_triumph.cli:main"
|
|
43
|
+
|
|
44
|
+
[tool.hatch.version]
|
|
45
|
+
path = "src/ffs_triumph/__init__.py"
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.wheel]
|
|
48
|
+
packages = ["src/ffs_triumph"]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 100
|
|
52
|
+
target-version = "py310"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""FFS — Full-manual Fetcher & Stitcher.
|
|
2
|
+
|
|
3
|
+
Turn a Triumph Technical Information service manual (a JavaScript SPA) into a
|
|
4
|
+
single, self-contained, paginated PDF for offline viewing and printing.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__version__ = "0.1.0"
|
|
8
|
+
|
|
9
|
+
from .client import LoginError, TriumphClient
|
|
10
|
+
from .config import ManualConfig
|
|
11
|
+
from .render import HtmlRenderer
|
|
12
|
+
|
|
13
|
+
__all__ = ["TriumphClient", "LoginError", "ManualConfig", "HtmlRenderer", "__version__"]
|