[@layout]: ../docs.layout.md

# Assets and scripts

Keep images, downloadable files, CSS, and JavaScript beneath `paths/`.

Relative
references resolve beside the Source that authors them. Root-relative paths
start at the Source root and respect the publication mount when rendered.

---

## Link files

```md
![Workshop diagram](./assets/diagram.png)

[Download the worksheet](./assets/worksheet.pdf)
```

Use ordinary HTML when you want the browser to download a file:

```html
<a href="./assets/worksheet.pdf" download>Download the worksheet</a>
```

Images use the [Image Plugin](./images.reference.md), including responsive
variants where supported. Authored assets follow their Source access boundary;
private attachments require an authorized reader. An anonymous static export
cannot expose private files by linking to them.

---

## Attach a script

Create `paths/scripts/print.js`:

```js
document.addEventListener("click", (event) => {
  if (event.target instanceof Element && event.target.closest("[data-print]")) {
    window.print()
  }
})
```

Create `paths/print.page.md` with the script reference and a button:

```md
[@script]: ./scripts/print.js

# Print your worksheet

<button class="pmx-button" type="button" data-print>Print this page</button>
```

Run `bun run dev`, open `/print.page`, and choose **Print this page**. The browser
opens its print dialog; cancel to return to the same page.

The script runs as a browser module. `[@script.global]` includes it across the
site. Local imports are bundled, and published assets are included in static
exports. These directives accept local `.js` files; server code and credentials
belong in trusted Plugins, not browser scripts.

For behavior tied to one component, prefer a
[component's client lifecycle](./components.reference.md#browser-lifecycle)
so mounting, live updates, and cleanup stay together.

---

## Attach styles

Use `[@styles]: ./styles.css` for the current Source and pages using it as a
layout. The [stylesheet reference](../site/styles.reference.md#stylesheet-scope)
owns global, theme-layer, and print/screen variants.

Create `paths/print.css`:

```css
.worksheet-note {
  border-inline-start: .25rem solid var(--pmx-color-accent);
  padding-inline-start: 1rem;
}
```

Add this declaration and content to `paths/print.page.md`:

```md
[@styles]: ./print.css

<p class="worksheet-note">Bring your observations to the workshop.</p>
```

The note now has an accent rule and left padding. Change the padding and save
to see the authored stylesheet update.

---

## Load a script across the site

To use the same print behavior on multiple pages, move its declaration to the
root `paths/index.md` and qualify it as global:

```md
[@script.global]: ./scripts/print.js
```

Remove the local `@script` declaration from `print.page.md`. Add the same
`data-print` button to another page or the shared layout. Both buttons open the
browser print dialog; the one delegated listener handles buttons introduced by
live updates. Keep this site-wide script in the root declaration rather than
repeating it on each consumer.

---

## Generate assets in a Plugin

Plugins can add assets through compile and page contexts. Generated variants
use the [Source-owned asset API](../extend/core.reference.md#source-owned-derived-assets),
which keeps generated content associated with its owning Source.
