docpull 1.0.1__py3-none-any.whl

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.
@@ -0,0 +1,440 @@
1
+ Metadata-Version: 2.4
2
+ Name: docpull
3
+ Version: 1.0.1
4
+ Summary: Pull documentation from the web and convert to clean markdown
5
+ Author-email: Zachary Roth <support@raintree.technology>
6
+ Maintainer-email: Raintree Technology <support@raintree.technology>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/raintree-technology/docpull
9
+ Project-URL: Documentation, https://github.com/raintree-technology/docpull#readme
10
+ Project-URL: Repository, https://github.com/raintree-technology/docpull
11
+ Project-URL: Source Code, https://github.com/raintree-technology/docpull
12
+ Project-URL: Bug Tracker, https://github.com/raintree-technology/docpull/issues
13
+ Project-URL: Changelog, https://github.com/raintree-technology/docpull/blob/main/CHANGELOG.md
14
+ Keywords: python,markdown,documentation,web-scraping,developer-tools,claude,ai-training-data
15
+ Classifier: Development Status :: 5 - Production/Stable
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Information Technology
18
+ Classifier: Intended Audience :: Science/Research
19
+ Classifier: Intended Audience :: Education
20
+ Classifier: Environment :: Console
21
+ Classifier: Topic :: Documentation
22
+ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
23
+ Classifier: Topic :: Software Development :: Documentation
24
+ Classifier: Topic :: Text Processing :: Markup :: HTML
25
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
26
+ Classifier: Topic :: Utilities
27
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
28
+ Classifier: Natural Language :: English
29
+ Classifier: Operating System :: OS Independent
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Programming Language :: Python :: 3.9
32
+ Classifier: Programming Language :: Python :: 3.10
33
+ Classifier: Programming Language :: Python :: 3.11
34
+ Classifier: Programming Language :: Python :: 3.12
35
+ Classifier: Programming Language :: Python :: 3.13
36
+ Classifier: Programming Language :: Python :: 3 :: Only
37
+ Classifier: Typing :: Typed
38
+ Requires-Python: >=3.9
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: requests>=2.31.0
42
+ Requires-Dist: beautifulsoup4>=4.12.0
43
+ Requires-Dist: html2text>=2020.1.16
44
+ Requires-Dist: defusedxml>=0.7.1
45
+ Requires-Dist: aiohttp>=3.9.0
46
+ Requires-Dist: rich>=13.0.0
47
+ Provides-Extra: yaml
48
+ Requires-Dist: pyyaml>=6.0; extra == "yaml"
49
+ Provides-Extra: js
50
+ Requires-Dist: playwright>=1.40.0; extra == "js"
51
+ Provides-Extra: all
52
+ Requires-Dist: pyyaml>=6.0; extra == "all"
53
+ Requires-Dist: playwright>=1.40.0; extra == "all"
54
+ Provides-Extra: dev
55
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
56
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
57
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
58
+ Requires-Dist: black>=23.0.0; extra == "dev"
59
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
60
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
61
+ Requires-Dist: bandit>=1.7.0; extra == "dev"
62
+ Requires-Dist: pip-audit>=2.0.0; extra == "dev"
63
+ Requires-Dist: types-requests>=2.31.0; extra == "dev"
64
+ Requires-Dist: types-beautifulsoup4>=4.12.0; extra == "dev"
65
+ Requires-Dist: types-aiohttp>=3.9.0; extra == "dev"
66
+ Dynamic: license-file
67
+
68
+ # docpull
69
+
70
+ **Pull documentation from ANY website and convert to clean, AI-ready markdown.**
71
+
72
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
73
+ [![PyPI version](https://badge.fury.io/py/docpull.svg)](https://badge.fury.io/py/docpull)
74
+ [![License: MIT](https://img.shields.io/github/license/raintree-technology/docpull)](https://github.com/raintree-technology/docpull/blob/main/LICENSE)
75
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
76
+ [![Type checked: mypy](https://img.shields.io/badge/type%20checked-mypy-blue.svg)](http://mypy-lang.org/)
77
+ [![Security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
78
+
79
+ ## Why docpull?
80
+
81
+ Unlike wget or httrack that dump messy HTML, **docpull extracts clean markdown** perfect for:
82
+ - Training AI models / RAG systems
83
+ - Building knowledge bases
84
+ - Creating searchable documentation archives
85
+ - Offline documentation reading
86
+
87
+ **Production-ready**: Full type safety (mypy), security scanning (Bandit), zero linting issues (Ruff), comprehensive test coverage, and no known vulnerabilities.
88
+
89
+ ## Features
90
+
91
+ - **Universal**: Scrape ANY documentation site - not limited to predefined sources
92
+ - **Smart extraction**: Auto-detects main content, removes navigation/ads
93
+ - **Blazing fast**: Async/parallel fetching (10x faster than sync)
94
+ - **JavaScript support**: Handles JS-heavy sites with Playwright
95
+ - **Progress bars**: Beautiful real-time progress with Rich
96
+ - **Sitemap support**: Auto-discovers pages via sitemap.xml
97
+ - **Link crawling**: Optionally follows links to discover all pages
98
+ - **Secure**: Rate limiting, content validation, timeout controls
99
+ - **Clean output**: Markdown with YAML frontmatter
100
+ - **Configurable**: Control depth, page limits, concurrency
101
+ - **Resumable**: Skip already-fetched files
102
+
103
+ ## Quick Start
104
+
105
+ ```bash
106
+ # Install
107
+ pip install docpull
108
+
109
+ # Scrape ANY documentation site
110
+ docpull https://aptos.dev
111
+ docpull https://docs.anthropic.com
112
+ docpull https://go.dev/doc
113
+
114
+ # Use optimized profiles for popular sites
115
+ docpull stripe
116
+ docpull nextjs react
117
+
118
+ # Control scraping behavior
119
+ docpull https://newsite.com/docs --max-pages 100 --max-concurrent 20
120
+ ```
121
+
122
+ ## Installation
123
+
124
+ ```bash
125
+ # Basic installation
126
+ pip install docpull
127
+
128
+ # With YAML config support
129
+ pip install docpull[yaml]
130
+
131
+ # With JavaScript rendering (for JS-heavy sites)
132
+ pip install docpull[js]
133
+ python -m playwright install chromium
134
+
135
+ # Everything
136
+ pip install docpull[all]
137
+ python -m playwright install chromium
138
+ ```
139
+
140
+ ## Usage
141
+
142
+ ### Scrape Any URL
143
+
144
+ The primary way to use docpull is by providing any documentation URL:
145
+
146
+ ```bash
147
+ # Single site
148
+ docpull https://aptos.dev
149
+
150
+ # Multiple sites
151
+ docpull https://aptos.dev https://docs.soliditylang.org
152
+
153
+ # Control crawling
154
+ docpull https://docs.example.com \
155
+ --max-pages 200 \
156
+ --max-depth 4 \
157
+ --rate-limit 1.0
158
+ ```
159
+
160
+ ### Use Optimized Profiles
161
+
162
+ For popular documentation sites, use shortcut names for optimized scraping:
163
+
164
+ ```bash
165
+ # Single profile
166
+ docpull stripe
167
+
168
+ # Multiple profiles
169
+ docpull stripe plaid nextjs
170
+
171
+ # Mix profiles and URLs
172
+ docpull stripe https://newsite.com/docs
173
+ ```
174
+
175
+ ### JavaScript Rendering
176
+
177
+ For sites that require JavaScript to render content:
178
+
179
+ ```bash
180
+ # Enable JS rendering with Playwright
181
+ docpull https://js-heavy-site.com --js
182
+
183
+ # Combine with other options
184
+ docpull https://site.com --js --max-pages 50 --max-concurrent 5
185
+ ```
186
+
187
+ **Note:** JS rendering is slower but handles modern SPAs and dynamically-loaded content.
188
+
189
+ ### Available Profiles
190
+
191
+ | Profile | Site | Optimizations |
192
+ |---------|------|---------------|
193
+ | `stripe` | docs.stripe.com | Filters changelog, focused on API docs |
194
+ | `nextjs` | nextjs.org | Excludes blog/showcase, docs only |
195
+ | `react` | react.dev | Learn & reference sections only |
196
+ | `plaid` | plaid.com | API + guides, excludes marketing |
197
+ | `tailwind` | tailwindcss.com | Documentation only |
198
+ | `bun` | bun.sh | Runtime documentation |
199
+ | `d3` | d3js.org | Data visualization docs |
200
+ | `turborepo` | turbo.build | Monorepo tooling docs |
201
+
202
+ ### Python API
203
+
204
+ ```python
205
+ from docpull import GenericAsyncFetcher
206
+
207
+ # Scrape any URL (async/parallel)
208
+ fetcher = GenericAsyncFetcher(
209
+ url_or_profile="https://aptos.dev",
210
+ output_dir="./docs",
211
+ max_pages=100,
212
+ max_concurrent=20,
213
+ use_js=False, # Set to True for JS rendering
214
+ )
215
+ fetcher.fetch()
216
+
217
+ # Or use a profile
218
+ fetcher = GenericAsyncFetcher(
219
+ url_or_profile="stripe",
220
+ output_dir="./docs",
221
+ )
222
+ fetcher.fetch()
223
+ ```
224
+
225
+ ### Advanced Options
226
+
227
+ ```bash
228
+ # Limit pages and depth
229
+ docpull https://docs.example.com --max-pages 50 --max-depth 2
230
+
231
+ # Control concurrent requests (default: 10)
232
+ docpull https://site.com --max-concurrent 20
233
+
234
+ # Enable JavaScript rendering
235
+ docpull https://site.com --js
236
+
237
+ # Custom output directory
238
+ docpull stripe --output-dir ./my-docs
239
+
240
+ # Adjust rate limiting
241
+ docpull https://site.com --rate-limit 2.0
242
+
243
+ # Re-fetch existing files
244
+ docpull stripe --no-skip-existing
245
+
246
+ # Verbose logging
247
+ docpull https://site.com --verbose
248
+
249
+ # Disable progress bars
250
+ docpull https://site.com --no-progress
251
+
252
+ # Dry run (see what would be fetched)
253
+ docpull https://site.com --dry-run
254
+ ```
255
+
256
+ ## Performance
257
+
258
+ **Async/Parallel Fetching** makes docpull **10x faster** than traditional sync scrapers:
259
+
260
+ | Pages | Sync (old) | Async (new) | Speedup |
261
+ |-------|-----------|-------------|---------|
262
+ | 5 | ~5.0s | ~1.8s | 2.8x faster |
263
+ | 50 | ~50s | ~6s | 8.3x faster |
264
+ | 500 | ~500s | ~45s | 11x faster |
265
+
266
+ With `--max-concurrent 20`, even faster for large sites!
267
+
268
+ ## Output Format
269
+
270
+ Each page is saved as markdown with YAML frontmatter:
271
+
272
+ ```markdown
273
+ ---
274
+ url: https://stripe.com/docs/payments
275
+ fetched: 2025-11-13
276
+ ---
277
+
278
+ # Payment Intents
279
+
280
+ Your clean documentation content here...
281
+ ```
282
+
283
+ Files are organized by URL structure:
284
+
285
+ ```
286
+ docs/
287
+ ├── stripe/
288
+ │ ├── api/
289
+ │ │ ├── charges.md
290
+ │ │ └── customers.md
291
+ │ └── payments/
292
+ │ └── payment-intents.md
293
+ └── aptos_dev/
294
+ ├── guides/
295
+ │ └── getting-started.md
296
+ └── reference/
297
+ └── api.md
298
+ ```
299
+
300
+ ## How It Works
301
+
302
+ 1. **Discovery**: Tries sitemap.xml first, falls back to link crawling
303
+ 2. **Filtering**: Applies URL patterns to focus on documentation
304
+ 3. **Extraction**: Removes nav/footer/ads, extracts main content
305
+ 4. **Conversion**: Converts HTML to clean markdown
306
+ 5. **Organization**: Saves with structure that mirrors the site
307
+ 6. **Async Magic**: Fetches multiple pages concurrently with rate limiting
308
+
309
+ ## Configuration File
310
+
311
+ Create `config.yaml` for complex setups:
312
+
313
+ ```yaml
314
+ output_dir: ./docs
315
+ rate_limit: 0.5
316
+ skip_existing: true
317
+ log_level: INFO
318
+
319
+ sources:
320
+ - stripe
321
+ - nextjs
322
+ - react
323
+ ```
324
+
325
+ Run with:
326
+ ```bash
327
+ docpull --config config.yaml
328
+ ```
329
+
330
+ ## Creating Custom Profiles
331
+
332
+ You can create optimized profiles for your frequently-scraped sites:
333
+
334
+ ```python
335
+ from docpull.profiles.base import SiteProfile
336
+
337
+ MY_PROFILE = SiteProfile(
338
+ name="mysite",
339
+ domains={"docs.mysite.com"},
340
+ sitemap_url="https://docs.mysite.com/sitemap.xml",
341
+ base_url="https://docs.mysite.com/",
342
+ include_patterns=["/docs/", "/api/"],
343
+ exclude_patterns=["/blog/"],
344
+ output_subdir="mysite",
345
+ rate_limit=0.5,
346
+ )
347
+ ```
348
+
349
+ ## Security
350
+
351
+ docpull is designed with security in mind:
352
+
353
+ - **HTTPS-only** by default
354
+ - **Private IP blocking** (no localhost, 192.168.x.x, etc.)
355
+ - **Content size limits** (50MB max per page)
356
+ - **Timeout controls** (30s per request)
357
+ - **Rate limiting** (async-safe, prevents DoS)
358
+ - **Concurrent connection limits** (prevents overwhelming servers)
359
+ - **Content-type validation** (only fetches HTML/XML)
360
+ - **Playwright sandboxing** (when using --js)
361
+
362
+ See [SECURITY.md](SECURITY.md) for detailed security information.
363
+
364
+ ## Comparison with Alternatives
365
+
366
+ | Tool | Output | Works on any site? | Clean extraction? | Speed | JS Support |
367
+ |------|--------|-------------------|-------------------|-------|------------|
368
+ | **docpull** | Clean markdown | Yes | Yes | Fast (async) | Optional |
369
+ | wget | Raw HTML | Yes | No | Slow (sync) | No |
370
+ | httrack | Raw HTML | Yes | No | Slow (sync) | No |
371
+ | Site-specific | Varies | No | Varies | Varies | No |
372
+
373
+ ## Troubleshooting
374
+
375
+ ### Site requires JavaScript
376
+
377
+ ```bash
378
+ # Install Playwright support
379
+ pip install docpull[js]
380
+ python -m playwright install chromium
381
+
382
+ # Use --js flag
383
+ docpull https://site.com --js
384
+ ```
385
+
386
+ ### Too slow / rate limited
387
+
388
+ ```bash
389
+ # Reduce concurrent requests
390
+ docpull https://site.com --max-concurrent 5 --rate-limit 2.0
391
+ ```
392
+
393
+ ### Memory issues on large sites
394
+
395
+ ```bash
396
+ # Limit pages fetched
397
+ docpull https://site.com --max-pages 1000
398
+ ```
399
+
400
+ ## Contributing
401
+
402
+ Contributions welcome! To add:
403
+ - **New site profiles**: Create a profile in `docpull/profiles/`
404
+ - **Better extraction**: Improve content detection in `fetchers/base.py`
405
+ - **Performance improvements**: Optimize async fetching
406
+ - **Bug reports**: Use the [issue tracker](https://github.com/raintree-technology/docpull/issues)
407
+
408
+ ### Development Setup
409
+
410
+ ```bash
411
+ # Clone and install
412
+ git clone https://github.com/raintree-technology/docpull
413
+ cd docpull
414
+ pip install -e ".[dev]"
415
+
416
+ # Run all quality checks (as per CI)
417
+ black --check . # Code formatting
418
+ ruff check . # Linting
419
+ mypy docpull # Type checking
420
+ bandit -r docpull # Security scanning
421
+ pip-audit # Dependency vulnerabilities
422
+ pytest --cov=docpull -v # Tests with coverage
423
+ ```
424
+
425
+ All PRs must pass these checks before merging.
426
+
427
+ ## Documentation
428
+
429
+ - [Changelog](CHANGELOG.md)
430
+ - [Security Policy](SECURITY.md)
431
+
432
+ ## License
433
+
434
+ MIT License - see [LICENSE](LICENSE) file for details
435
+
436
+ ## Links
437
+
438
+ - [PyPI](https://pypi.org/project/docpull/)
439
+ - [GitHub](https://github.com/raintree-technology/docpull)
440
+ - [Issues](https://github.com/raintree-technology/docpull/issues)
@@ -0,0 +1,38 @@
1
+ docpull/__init__.py,sha256=GxP9o5rz9t6wxmo6Gu7t4mRrAsUyI-1qHWVTjGROin0,835
2
+ docpull/__main__.py,sha256=4JMK66Wj4uLZTKbF-sT3LAxOsr6buig77PmOkJCRRxw,83
3
+ docpull/cli.py,sha256=WmgN7Vwv7ggmiVzHjFYff-w1ZV09lnkKPSw9dEkZdNQ,12157
4
+ docpull/config.py,sha256=9CzuNFYbDUX1o2SG25_dxcC6Z0JFLPC0KWJxeqE3O6k,6264
5
+ docpull/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ docpull/fetchers/__init__.py,sha256=GU2_3i9Qles7fEKpCd29N471HTvuLjVGReylOY5oHuE,572
7
+ docpull/fetchers/async_fetcher.py,sha256=YxenNx88bP1SwhgfPbm1iNPxZxX-RPYnyOHD9D7iXuc,11213
8
+ docpull/fetchers/base.py,sha256=1cSIvNwVuhqZ_zwCYAXFZ01HEvU8K2gX3iIliR2ELE8,15691
9
+ docpull/fetchers/bun.py,sha256=Wp3HGwnbDoI1OCIEUXuZyavrt2J0-rmUryjIcYD9Bx0,1782
10
+ docpull/fetchers/d3.py,sha256=CGVEL6QyXz22cNhCcLU05dcR-_uvgLZCfJE49ivm8eM,7148
11
+ docpull/fetchers/generic.py,sha256=2MglTVvrdaYJBpHMovFVcoo4mtEhaqBxr-f2Oz2ThPA,9373
12
+ docpull/fetchers/generic_async.py,sha256=xX84RhsnKUon3MUJGKFYc8RNuq-hY-o4sL7Jskx4zZo,11125
13
+ docpull/fetchers/nextjs.py,sha256=3ozWLbAFYUtVwvPSbRcPuar5kQVA9sHgo4Qfn4BqhaI,1729
14
+ docpull/fetchers/parallel_base.py,sha256=Eb1qZvHKub_hL5cIcAbFoGmR17EEZ2mQeo2P6mFgnjE,3090
15
+ docpull/fetchers/plaid.py,sha256=ARoo60g9h0xV_LfSoa2bOSve6dIgRB3y43dSxSmCcfQ,3223
16
+ docpull/fetchers/react.py,sha256=UwUkFzz8oNT9tW3xLLZ1B8dVhHLiJUQoQhBkx26wcNE,1804
17
+ docpull/fetchers/stripe.py,sha256=ezmmL41E4x6GgNYaUy_GSPCm5-jvsyWS4aZfigZxbkA,2080
18
+ docpull/fetchers/tailwind.py,sha256=76Bj-gCFDHw_BNIlx16CsKD1PWBuH3eusa-fNwHnfEI,1882
19
+ docpull/fetchers/turborepo.py,sha256=4hRntjjne5ZrAf2eZavFW7aZ8jGvJkZGsuShSosM5KM,1816
20
+ docpull/profiles/__init__.py,sha256=TCE13-hgoSkqOP8lf1uoafZ_R9E6osgGTnJ29huQdsU,1563
21
+ docpull/profiles/base.py,sha256=6LTgxnddR1vsygPLvTM_Gyqua6mU0gM210vgg0i5b4k,1933
22
+ docpull/profiles/bun.py,sha256=RFvMgmWNrxIhi3Xlhk5wzLPzhBum7_IpHhoUZRE7cVI,315
23
+ docpull/profiles/d3.py,sha256=6UBcRtZ5Y_9XCd1LPKSgxrvqvgzPEN_KMTHpGbglZt0,478
24
+ docpull/profiles/nextjs.py,sha256=y6uPhxD4K16FHCfWoKmANliTnE2XRIMWRNkBS_l_h4s,406
25
+ docpull/profiles/plaid.py,sha256=FfE4cG7Iph_-n6VR5vckD-il55vJZZpOATboN89_9L0,514
26
+ docpull/profiles/react.py,sha256=nQ9YwMa3fiOAFVwOiGWOLwL_L_dMSc7_QMoE7LoJB4E,412
27
+ docpull/profiles/stripe.py,sha256=0ZoAIKltAvPE0oIr6vLNUugmqgqFaHIFaDBnwbEAbMA,413
28
+ docpull/profiles/tailwind.py,sha256=tjdQE_wmVis0tkORYFE1Y_8QNAACRT8_xcAkTLmnvUk,366
29
+ docpull/profiles/turborepo.py,sha256=GS-DKYMC9JqFWy2R_mq5T3wkpdCd5b_48Pij9vtQX4Q,381
30
+ docpull/utils/__init__.py,sha256=KmZIu_MLGAYn9RaZ_p-FRW7JAEktqqHu3vAJnp6x3S4,238
31
+ docpull/utils/file_utils.py,sha256=ofwqmWh5bOdURmZ4D5Jntab-eMJmzbhPpaGYdffnQPs,2657
32
+ docpull/utils/logging_config.py,sha256=0l4U4KsnLYJ8qD7fMDbTOe6_bij-q-gUAMDgymS0cnM,1731
33
+ docpull-1.0.1.dist-info/licenses/LICENSE,sha256=PaRVpLb_4aICC6aK-Mmx_-UWm9hVPmG3GCc8TlVFePI,1076
34
+ docpull-1.0.1.dist-info/METADATA,sha256=eiC0K4JKO9w04E7US_RAK3C-be7kJgE5X7xsouq4UIA,12834
35
+ docpull-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ docpull-1.0.1.dist-info/entry_points.txt,sha256=2XpUlOneuBhB00fqOCfzoywf56nYM1FRyKW6HVCsIC4,45
37
+ docpull-1.0.1.dist-info/top_level.txt,sha256=Ya0YBKQEKxPLBYU5wNsPtsdgdV0WGM_0J3Y_75MI9e4,8
38
+ docpull-1.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ docpull = docpull.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Raintree Technology
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 @@
1
+ docpull