Metadata-Version: 2.5
Name: jupyterlab_advanced_paste_content_extension
Version: 1.0.7
Summary: Jupyterlab extension that captures pasted content (text, file, graphics file / screenshot etc) and copies it to the current folder and in the receiving end (txt file, md file, python file or terminal). Extension will use different handlers to dedice how to handle the content
Project-URL: Homepage, https://github.com/stellarshenson/jupyterlab_advanced_paste_content_extension
Project-URL: Bug Tracker, https://github.com/stellarshenson/jupyterlab_advanced_paste_content_extension/issues
Project-URL: Repository, https://github.com/stellarshenson/jupyterlab_advanced_paste_content_extension.git
Author-email: Stellars Henson <konrad.jelen+github@gmail.com>
License-Expression: BSD-3-Clause
License-File: LICENSE
Keywords: jupyter,jupyterlab,jupyterlab-extension
Classifier: Framework :: Jupyter
Classifier: Framework :: Jupyter :: JupyterLab
Classifier: Framework :: Jupyter :: JupyterLab :: 4
Classifier: Framework :: Jupyter :: JupyterLab :: Extensions
Classifier: Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Requires-Dist: jupyter-server<3,>=2.13.0
Provides-Extra: dev
Requires-Dist: jupyter-builder>=1.2.0; extra == 'dev'
Requires-Dist: jupyterlab>=4; extra == 'dev'
Provides-Extra: test
Requires-Dist: coverage; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-asyncio; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'
Requires-Dist: pytest-jupyter[server]>=0.6.0; extra == 'test'
Description-Content-Type: text/markdown

# jupyterlab_advanced_paste_content_extension

[![GitHub Actions](https://github.com/stellarshenson/jupyterlab_advanced_paste_content_extension/actions/workflows/build.yml/badge.svg)](https://github.com/stellarshenson/jupyterlab_advanced_paste_content_extension/actions/workflows/build.yml)
[![npm version](https://img.shields.io/npm/v/jupyterlab_advanced_paste_content_extension.svg)](https://www.npmjs.com/package/jupyterlab_advanced_paste_content_extension)
[![PyPI version](https://img.shields.io/pypi/v/jupyterlab-advanced-paste-content-extension.svg)](https://pypi.org/project/jupyterlab-advanced-paste-content-extension/)
[![Total PyPI downloads](https://static.pepy.tech/badge/jupyterlab-advanced-paste-content-extension)](https://pepy.tech/project/jupyterlab-advanced-paste-content-extension)
[![JupyterLab 4](https://img.shields.io/badge/JupyterLab-4-orange.svg)](https://jupyterlab.readthedocs.io/en/stable/)
[![Brought To You By KOLOMOLO](https://img.shields.io/badge/Brought%20To%20You%20By-KOLOMOLO-00ffff?style=flat)](https://kolomolo.com)
[![Donate PayPal](https://img.shields.io/badge/Donate-PayPal-blue?style=flat)](https://www.paypal.com/donate/?hosted_button_id=B4KPBJDLLXTSA)

Paste a screenshot or a file into JupyterLab and have it land as a real file. The extension
intercepts the paste, writes the payload into the folder you are working in, and gives the surface
that received the paste a reference to that file instead of a blob of inline content. A plain-text
paste is left alone.

A screenshot pasted into a markdown cell becomes a PNG on disk plus an image link. A copied file
becomes a copy in the current folder. Text stays text.

A terminal has no document to give the file a home, so a paste into one becomes a clipping: the file
is written into a clippings folder of its own and the shell receives its absolute path.

## Features

- **Screenshots become files** - a pasted bitmap is written as PNG named `paste-20260920-191530.png`
  in the folder holding the document, instead of a base64 blob inside the notebook
- **Pasted files are copied in** - a file copied from a file manager lands in the current folder
  under its own name; several files at once all arrive
- **The reference suits the surface** - `![](name)` in a markdown file or markdown cell, `"name"` in
  a code cell so it drops into `plt.imread()`, the bare name in a text file
- **Rich HTML becomes markdown** - only on the two surfaces that render it; a text file, a code cell
  and a terminal take the plain-text flavour, which is what a normal paste already gives them
- **A terminal gets a clipping** - a file or image pasted into a terminal is written into the
  clippings folder, `/tmp/paste-clippings` by default, and the terminal receives the
  absolute path to it, escaped for the shell, so it resolves wherever the shell has changed into;
  Claude Code and the other AI assistant terminals included
- **Nothing is written twice** - an identical payload references the file already in the folder, and
  a name clash never overwrites
- **Server-side write** - the file is created through a Jupyter server endpoint, so it lands in the
  server's workspace rather than the browser sandbox, and writes cannot escape the server root

The full behaviour of every content type on every surface is in
[docs/design-content-types.md](docs/design-content-types.md).

## Configuration

The clippings folder is where a paste into a terminal writes. It defaults to
`/tmp/paste-clippings` and is set in `jupyter_server_config.py`:

```python
c.PasteClippingsConfig.clippings_dir = "/srv/clippings"
```

A clipping is treated like clipboard content and is not expected to survive a reboot, which is why
the default sits in the temporary directory. To keep them, put the folder anywhere and point the
default name at it:

```bash
mkdir -p ~/.cache/paste-clippings
ln -s ~/.cache/paste-clippings /tmp/paste-clippings
```

The symlink is followed, so clips land in the folder under your home directory and outlive the
temporary directory being cleared.

When the configured folder cannot be created, or resolves to one this server does not own, the paste
is written into the folder the file browser shows instead. A paste never fails because of the
clippings folder.

## Requirements

- JupyterLab >= 4.0.0

## Install

To install the extension, execute:

```bash
pip install jupyterlab_advanced_paste_content_extension
```

## Uninstall

To remove the extension, execute:

```bash
pip uninstall jupyterlab_advanced_paste_content_extension
```
