@ranx729/ducktape-assets 0.0.0 → 1.0.0
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.
- package/AGENTS.md +52 -0
- package/README.md +42 -2
- package/bin/ducktape-assets.mjs +34 -0
- package/catalog.json +6617 -0
- package/index.json +51 -0
- package/package.json +51 -1
- package/schemas/index.schema.json +38 -0
- package/sets/illuminated-acanthus.json +8046 -0
- package/sets/medieval-cutouts.json +8492 -0
- package/sets/walters-w102.json +759 -0
- package/src/copy.mjs +131 -0
- package/src/generate.mjs +190 -0
- package/src/node.mjs +9 -0
- package/src/resolver.mjs +235 -0
- package/src/rungs.mjs +34 -0
- package/src/thumbhash.mjs +163 -0
- package/src/urls.mjs +34 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Ducktape Assets for agents
|
|
2
|
+
|
|
3
|
+
Generated. Use these rules; do not edit this file by hand.
|
|
4
|
+
|
|
5
|
+
## Finding an asset
|
|
6
|
+
|
|
7
|
+
- Search `catalog.json` (one grep finds an asset and its URL). Ids are `<set>/<asset>`.
|
|
8
|
+
- Read `sets/<set>.json` only for what the catalog leaves out (hashes, bytes, components, parts).
|
|
9
|
+
|
|
10
|
+
## Using an asset
|
|
11
|
+
|
|
12
|
+
1. **Paste a URL.** Any HTML, CSS or Markdown references one file on jsDelivr, for example `https://cdn.jsdelivr.net/npm/@ranx729/ducktape-assets-walters-w102@1.2.0/webp/rabbit-church-bells-512.webp`. Only that file is transferred. `catalog.json` lists the exact URL of every width and format, so nothing has to be guessed.
|
|
13
|
+
2. **Pick and copy.** Keep a small `ducktape.json` listing the asset ids you want, with optional widths, formats and `masters: true`. `npx @ranx729/ducktape-assets copy` fetches exactly those files into the project (default `src/assets/ducktape/`), verifies every SHA-256 against the manifest, and writes `ducktape.manifest.json` beside them with dimensions, thumbhash, licence and attribution per asset. Re-running is idempotent.
|
|
14
|
+
3. **Resolve in code.** `npm i @ranx729/ducktape-assets` installs metadata and a resolver, zero images. `assets.image(id, { width })` returns `src`, `srcset`, `sizes`, width, height, thumbhash and licence. Bytes come from the CDN at request time, or from flow 2 when `base` points at the copied directory.
|
|
15
|
+
|
|
16
|
+
Prefer flow 2 for anything that must survive unattended: copied files do not depend on any host.
|
|
17
|
+
|
|
18
|
+
`ducktape.json`:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"pin": "@ranx729/ducktape-assets@3.4.0",
|
|
23
|
+
"out": "src/assets/ducktape",
|
|
24
|
+
"assets": [
|
|
25
|
+
"walters-w102/rabbit-church-bells",
|
|
26
|
+
{ "id": "numbered-plate/stepped-ribbon", "formats": ["avif", "webp"], "max": 1024 },
|
|
27
|
+
{ "id": "illuminated-acanthus/divider-center", "masters": true }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## URLs
|
|
33
|
+
|
|
34
|
+
`https://cdn.jsdelivr.net/npm/@ranx729/ducktape-assets-<set>@<version>/<format>/<asset>-<w>.<ext>`
|
|
35
|
+
|
|
36
|
+
Exact-version URLs are immutable and cached for a year. Large sets are split into volume packages (`…-<set>-part2`); the catalog, the resolver and the copy command emit the right URL, so a consumer never notices the split.
|
|
37
|
+
|
|
38
|
+
## Rules
|
|
39
|
+
|
|
40
|
+
- Honour the licence block: show the `attribution` line when the asset's licence requires it.
|
|
41
|
+
- Never use `@latest` or range URLs; always an exact version from `index.json` or `catalog.json`.
|
|
42
|
+
- Never put a master on a page. Masters are for re-encoding in a build.
|
|
43
|
+
- Images are decorative by default (`alt=""`); use `description` when the image carries meaning.
|
|
44
|
+
- Always set the `width` and `height` attributes; the resolver returns them.
|
|
45
|
+
|
|
46
|
+
## Sets
|
|
47
|
+
|
|
48
|
+
| Set | Title | Summary | Assets | Licence | Repo |
|
|
49
|
+
| --- | --- | --- | --- | --- | --- |
|
|
50
|
+
| `illuminated-acanthus` | Illuminated acanthus | Red, blue and gold acanthus corners, dividers, frames, margin rods, sprigs and a muse figure in the style of a 15th-century Flemish illuminated border, AI-generated by adrian729 from style references for the Polyhymnia app. | 36 | CC-BY-4.0 | [repo](https://github.com/adrian729/ducktape-assets-illuminated-acanthus) |
|
|
51
|
+
| `medieval-cutouts` | Medieval cutouts | A legacy collection of 41 painted cut-outs in a medieval manuscript style (animal and human musicians, drolleries, readers and single animals) whose origin was never recorded. | 41 | CC-BY-4.0 | [repo](https://github.com/adrian729/ducktape-assets-medieval-cutouts) |
|
|
52
|
+
| `walters-w102` | Walters W.102 marginalia | Marginal creatures and scenes from Walters Art Museum W.102, a Flemish book of hours of around 1300 whose margins are filled with animal musicians, hybrids and small architectural vignettes. | 4 | CC0-1.0 | [repo](https://github.com/adrian729/ducktape-assets-walters-w102) |
|
package/README.md
CHANGED
|
@@ -1,3 +1,43 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ducktape Assets
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Find an asset here, use it in under a minute. This package is metadata and a build-time resolver: it never contains an image. It is generated; do not edit it by hand.
|
|
4
|
+
|
|
5
|
+
## Three ways to use an asset
|
|
6
|
+
|
|
7
|
+
1. **Paste a URL.** Any HTML, CSS or Markdown references one file on jsDelivr, for example `https://cdn.jsdelivr.net/npm/@ranx729/ducktape-assets-walters-w102@1.2.0/webp/rabbit-church-bells-512.webp`. Only that file is transferred. `catalog.json` lists the exact URL of every width and format, so nothing has to be guessed.
|
|
8
|
+
2. **Pick and copy.** Keep a small `ducktape.json` listing the asset ids you want, with optional widths, formats and `masters: true`. `npx @ranx729/ducktape-assets copy` fetches exactly those files into the project (default `src/assets/ducktape/`), verifies every SHA-256 against the manifest, and writes `ducktape.manifest.json` beside them with dimensions, thumbhash, licence and attribution per asset. Re-running is idempotent.
|
|
9
|
+
3. **Resolve in code.** `npm i @ranx729/ducktape-assets` installs metadata and a resolver, zero images. `assets.image(id, { width })` returns `src`, `srcset`, `sizes`, width, height, thumbhash and licence. Bytes come from the CDN at request time, or from flow 2 when `base` points at the copied directory.
|
|
10
|
+
|
|
11
|
+
`ducktape.json`:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"pin": "@ranx729/ducktape-assets@3.4.0",
|
|
16
|
+
"out": "src/assets/ducktape",
|
|
17
|
+
"assets": [
|
|
18
|
+
"walters-w102/rabbit-church-bells",
|
|
19
|
+
{ "id": "numbered-plate/stepped-ribbon", "formats": ["avif", "webp"], "max": 1024 },
|
|
20
|
+
{ "id": "illuminated-acanthus/divider-center", "masters": true }
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## URLs
|
|
26
|
+
|
|
27
|
+
`https://cdn.jsdelivr.net/npm/@ranx729/ducktape-assets-<set>@<version>/<format>/<asset>-<w>.<ext>`
|
|
28
|
+
|
|
29
|
+
Exact-version URLs are immutable and cached for a year. Large sets are split into volume packages (`…-<set>-part2`); the catalog, the resolver and the copy command emit the right URL, so a consumer never notices the split.
|
|
30
|
+
|
|
31
|
+
## Files
|
|
32
|
+
|
|
33
|
+
- `catalog.json`: every asset with id, title, description, type, categories, subjects, colours, size, render capabilities, thumbhash, licence, attribution and the exact URL of each width and format.
|
|
34
|
+
- `sets/<set>.json`: the published manifest of each set (hashes, bytes, components, volume packages).
|
|
35
|
+
- `index.json`: the pinned version, packages and CDN base of each set.
|
|
36
|
+
|
|
37
|
+
## Sets
|
|
38
|
+
|
|
39
|
+
| Set | Title | Summary | Assets | Licence | Repo |
|
|
40
|
+
| --- | --- | --- | --- | --- | --- |
|
|
41
|
+
| `illuminated-acanthus` | Illuminated acanthus | Red, blue and gold acanthus corners, dividers, frames, margin rods, sprigs and a muse figure in the style of a 15th-century Flemish illuminated border, AI-generated by adrian729 from style references for the Polyhymnia app. | 36 | CC-BY-4.0 | [repo](https://github.com/adrian729/ducktape-assets-illuminated-acanthus) |
|
|
42
|
+
| `medieval-cutouts` | Medieval cutouts | A legacy collection of 41 painted cut-outs in a medieval manuscript style (animal and human musicians, drolleries, readers and single animals) whose origin was never recorded. | 41 | CC-BY-4.0 | [repo](https://github.com/adrian729/ducktape-assets-medieval-cutouts) |
|
|
43
|
+
| `walters-w102` | Walters W.102 marginalia | Marginal creatures and scenes from Walters Art Museum W.102, a Flemish book of hours of around 1300 whose margins are filled with animal musicians, hybrids and small architectural vignettes. | 4 | CC0-1.0 | [repo](https://github.com/adrian729/ducktape-assets-walters-w102) |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { copy } from '../src/copy.mjs';
|
|
5
|
+
|
|
6
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
7
|
+
|
|
8
|
+
const HELP = `usage: ducktape-assets copy [--config ducktape.json] [--out dir]
|
|
9
|
+
|
|
10
|
+
--config project config (default ducktape.json): { pin, out, assets: [ "set/id" | { id, formats?, max?, widths?, masters? } ] }
|
|
11
|
+
--out destination (default: config "out", else src/assets/ducktape)
|
|
12
|
+
--index local path or URL of index.json (default: the pin's package on jsDelivr)
|
|
13
|
+
--base directory or URL laid out as <base>/<set>/<path> to read files from instead of the CDN`;
|
|
14
|
+
|
|
15
|
+
if (!command || command === '--help' || command === '-h') {
|
|
16
|
+
console.log(HELP);
|
|
17
|
+
} else if (command === 'copy') {
|
|
18
|
+
try {
|
|
19
|
+
const { values } = parseArgs({
|
|
20
|
+
args: rest,
|
|
21
|
+
options: { config: { type: 'string', default: 'ducktape.json' }, out: { type: 'string' }, index: { type: 'string' }, base: { type: 'string' } },
|
|
22
|
+
});
|
|
23
|
+
const config = JSON.parse(await readFile(values.config, 'utf8'));
|
|
24
|
+
const out = values.out ?? config.out ?? 'src/assets/ducktape';
|
|
25
|
+
const r = await copy({ config, out, index: values.index, base: values.base, log: (m) => console.log(m) });
|
|
26
|
+
console.log(`${r.copied} copied, ${r.skipped} up to date, manifest at ${out}/ducktape.manifest.json`);
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.error(`ducktape-assets: ${e.message}`);
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
console.error(`unknown command "${command}"; run with --help`);
|
|
33
|
+
process.exitCode = 2;
|
|
34
|
+
}
|