Plain is headed towards 1.0! Subscribe for development updates →

plain.vendor

Download those CDN scripts and styles.

What about source maps?

It's fairly common right now to get an error during plain compile that says it can't find the source map for one of your vendored files. Right now, the fix is add the source map itself to your vendored dependencies too. In the future plain vendor might discover those during the vendoring process and download them automatically with the compiled files.

  1from pathlib import Path
  2
  3import click
  4
  5from plain.assets.finders import APP_ASSETS_DIR
  6
  7from .deps import Dependency, get_deps
  8from .exceptions import DependencyError
  9
 10VENDOR_DIR = APP_ASSETS_DIR / "vendor"
 11
 12
 13@click.group()
 14def cli():
 15    pass
 16
 17
 18@cli.command()
 19@click.option("--clear", is_flag=True, help="Clear all existing vendored dependencies")
 20def install(clear):
 21    if clear:
 22        click.secho("Clearing existing vendored dependencies...", bold=True)
 23        if VENDOR_DIR.exists():
 24            for path in VENDOR_DIR.iterdir():
 25                path.unlink()
 26
 27    deps = get_deps()
 28    if not deps:
 29        click.echo(
 30            "No vendored dependencies found in pyproject.toml. Use [tool.plain.vendor.dependencies]"
 31        )
 32        return
 33
 34    errors = []
 35
 36    for dep in deps:
 37        click.secho(f"Installing {dep.name}...", bold=True, nl=False)
 38        try:
 39            vendored_path = dep.install()
 40        except DependencyError as e:
 41            click.secho(f"  {e}", fg="red")
 42            errors.append(e)
 43
 44        vendored_path = vendored_path.relative_to(Path.cwd())
 45
 46        click.secho(f" {dep.installed}", fg="green", nl=False)
 47        click.secho(f" -> {vendored_path}")
 48
 49    if errors:
 50        click.secho("Failed to install some dependencies.", fg="red")
 51        exit(1)
 52
 53
 54@cli.command()
 55def update():
 56    deps = get_deps()
 57    if not deps:
 58        click.echo(
 59            "No vendored dependencies found in pyproject.toml. Use [tool.plain.vendor.dependencies]"
 60        )
 61        return
 62
 63    errors = []
 64
 65    for dep in deps:
 66        click.secho(f"Updating {dep.name} {dep.installed}...", bold=True, nl=False)
 67        try:
 68            vendored_path = dep.update()
 69            vendored_path = vendored_path.relative_to(Path.cwd())
 70
 71            click.secho(f" {dep.installed}", fg="green", nl=False)
 72            click.secho(f" -> {vendored_path}")
 73        except DependencyError as e:
 74            click.secho(f"  {e}", fg="red")
 75            errors.append(e)
 76
 77    if errors:
 78        click.secho("Failed to install some dependencies.", fg="red")
 79        exit(1)
 80
 81
 82@cli.command()
 83@click.argument("url")
 84@click.option("--name", help="Name of the dependency")
 85def add(url, name):
 86    if not name:
 87        name = url.split("/")[-1]
 88
 89    dep = Dependency(name, url=url)
 90
 91    click.secho(f"Installing {dep.name}...", bold=True, nl=False)
 92
 93    try:
 94        vendored_path = dep.update()
 95    except DependencyError as e:
 96        click.secho(f"  {e}", fg="red")
 97        exit(1)
 98
 99    vendored_path = vendored_path.relative_to(Path.cwd())
100
101    click.secho(f" {dep.installed}", fg="green", nl=False)
102    click.secho(f" -> {vendored_path}")