Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/pages-site.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ Which examples are surfaced is curated for a single hosted page (the rationale i

- `basic` and `inline-data` render fully standalone.
- `csv` (a single standalone track — one row, no group) and `json` (a live UniProt API track next to the BYO file) are bring-your-own-file. The examples reference `data: ./hotspots.*`, which the loader resolves against the *page*, not the config's directory (see the path-resolution caveat in `examples/README.md`). So `presets.ts` repoints them at the site-absolute `/protvista/sample-data/hotspots.*`, served from `docs/public/sample-data/` (copies of `examples/csv|json/hotspots.*`). That is what makes the file-backed presets render on the playground page.
- `extend-default` is omitted: it `extends: /src/default-config.yaml`, which the built `site/` bundle does not serve, so it can only load under the dev server. `tsv` (same shape as `csv`) and `bed` (niche) are omitted for brevity — add them to `PRESETS` if wanted.
- `extend-uniprot` (from `starter-kit/recipes/`) is surfaced: it layers a custom track on the full default viewer via `extends:`, pinned to the jsDelivr `dist/default-config.yaml` URL, which the element fetches over the network at render time — so it works on the hosted page. `presets.spec.ts` loads it offline by substituting `src/default-config.yaml` (the `starter-kit.spec.ts` pattern). Its `./data/` sample path is repointed at the served `hotspots.csv`.
- `extend-default` is omitted: it `extends: /src/default-config.yaml`, which the built `site/` bundle does not serve, so it can only load under the dev server (`extend-uniprot` is the hosted-page-friendly variant). `tsv` (same shape as `csv`) and `bed` (niche) are omitted for brevity — add them to `PRESETS` if wanted.

## Q2 "Documentation and training" deliverables (done)

Expand Down
14 changes: 7 additions & 7 deletions docs/src/content/docs/blog/protvista-5.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ nothing to install. Type an accession, edit the configuration, watch the
visualisation change. Every view has its own web address, so you can send a
colleague exactly what you are looking at.

When you want to keep it, the
When you want to keep a view you've built, the
[Starter Kit](https://github.com/ebi-webcomponents/protvista-starter-kit) is a
page and a configuration already wired together: select **Use this template**,
put your data file in the `data` folder, edit `config.yaml`, and switch on
GitHub Pages. That
gives you a web page you can share, with nothing installed. Your configuration
is checked each time you save a change, so a mistyped field is flagged there and
then rather than leaving you with an empty track and no explanation.
page and a configuration already wired together. Select **Use this template**,
drop your data file into the `data` folder, edit `config.yaml`, and switch on
GitHub Pages — that gives you a shareable web page with nothing installed. Each
time you save a change, an automatic check validates `config.yaml` against
ProtVista's schema, so a mistyped or unknown field is caught and named for you
rather than slipping through unnoticed.

## Getting it

Expand Down
7 changes: 4 additions & 3 deletions docs/src/content/docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,10 @@ merge rules and the full caveat.

:::tip[Try it live]
Open the [full default viewer](/protvista/playground/#preset=uniprot-default) to
see the base you're extending. To see it combined with your track, switch
`extends:` to the CDN URL above — that form resolves from any page, once 5.0.0
ships.
see the base you're extending, then open the
[extended viewer](/protvista/playground/#preset=extend-uniprot) to see your own
track layered on top of it — that preset uses the CDN `extends:` URL above, so it
resolves right on the hosted page.
:::

![The full default UniProt viewer for P05067 with an additional group labelled My lab at the bottom, containing the lab's own Hotspots track.](../../assets/screenshots/tutorial-extended.png)
Expand Down
31 changes: 29 additions & 2 deletions src/playground/__spec__/presets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
* broken seed can never reach the playground UI.
*/
import { describe, it, expect } from 'vitest';
import { readFile } from 'node:fs/promises';
import { resolve, dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { loadConfig } from '../../schema/load.js';
import { createRegistry } from '../../schema/registry.js';
import {
Expand All @@ -13,6 +16,27 @@ import {
isDevPreset,
} from '../presets.js';

// This spec lives at src/playground/__spec__/ → three levels up is the repo root.
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');

/**
* The `extend-uniprot` preset's `extends:` is a version-pinned jsDelivr URL
* whose release is not published in CI. Mirror `starter-kit.spec.ts`:
* substitute this repo's `src/default-config.yaml` (which the build copies
* verbatim to the `dist/` file jsDelivr serves) so the seed loads offline.
* Presets without an `extends:` never invoke this fetcher.
*/
const extendsFetcher = async (ref: string): Promise<string> => {
if (/^https?:\/\//i.test(ref)) {
expect(
ref.endsWith('/dist/default-config.yaml'),
`unexpected remote extends target: ${ref}`
).toBe(true);
return readFile(join(REPO_ROOT, 'src/default-config.yaml'), 'utf8');
}
throw new Error(`unexpected local extends target: ${ref}`);
};

describe('presets', () => {
it('exposes the default preset', () => {
expect(getPreset(DEFAULT_PRESET_ID)).toBeDefined();
Expand All @@ -31,18 +55,21 @@ describe('presets', () => {
loadConfig(preset.config, {
accession: preset.accession,
registry: createRegistry(),
extendsFetcher,
})
).resolves.toBeDefined();
}
);

it('file-backed presets point at the served sample data, not a bare page-relative file', () => {
for (const id of ['csv', 'json']) {
for (const id of ['csv', 'json', 'extend-uniprot']) {
const preset = getPreset(id);
expect(preset).toBeDefined();
// Repointed to the served /protvista/sample-data/ path so it loads.
expect(preset!.config).toContain('/protvista/sample-data/hotspots.');
expect(preset!.config).not.toMatch(/data:\s*\.\/hotspots\./);
// No bare relative `data:` path survives (covers both `./hotspots.*`
// and extend-uniprot's `./data/hotspots-extends.csv`).
expect(preset!.config).not.toMatch(/data:\s*\.\//);
}
});
});
36 changes: 32 additions & 4 deletions src/playground/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
* Those files are served from `docs/public/sample-data/` (copies of the
* canonical `examples/csv|json/hotspots.*`). That is the only edit from
* verbatim, and it makes the presets render on the native Astro page.
* - `extend-uniprot` (from `starter-kit/recipes/`) layers a custom track
* on the full default viewer via `extends:`. It pins the jsDelivr
* `dist/default-config.yaml` URL — fetched over the network at render
* time — so it resolves on the hosted page, unlike `examples/extend-default`
* whose `extends: /src/default-config.yaml` only loads under the dev
* server (the built `site/` bundle does not serve `/src/`). Its `./data/`
* sample is repointed at the served `hotspots.csv` like the presets above.
* - `extend-default` / `tsv` / `bed` are intentionally omitted:
* `extend-default` extends `/src/default-config.yaml`, which the
* built `site/` bundle does not serve (see the note in that example
* and examples/README.md); `tsv` duplicates `csv`'s shape and `bed`
* is niche.
* `extend-default` is the dev-only `/src/`-extends variant just described;
* `tsv` duplicates `csv`'s shape and `bed` is niche.
*
* `__spec__/presets.spec.ts` loads every preset through `loadConfig`, so
* a broken seed can never ship.
Expand All @@ -35,6 +40,11 @@ import basicConfig from '../../examples/basic/config.yaml?raw';
import inlineDataConfig from '../../examples/inline-data/config.yaml?raw';
import csvConfig from '../../examples/csv/config.yaml?raw';
import jsonConfig from '../../examples/json/config.yaml?raw';
// The CDN-`extends:` recipe from the Starter Kit. Its base config is a
// version-pinned jsDelivr URL, so — unlike examples/extend-default, which
// extends the dev-only `/src/` path — it resolves on the hosted playground
// (the element fetches it over the network at render time).
import extendUniprotConfig from '../../starter-kit/recipes/extend-uniprot.yaml?raw';
import { DEFAULT_ACCESSION } from './url-state.js';

// Repoint a file-backed example's page-relative data path at the sample data
Expand All @@ -47,6 +57,15 @@ const withServedData = (config: string): string =>
'data: /protvista/sample-data/$1'
);

// The extend-uniprot recipe ships its sample under `./data/`; repoint it at the
// same served hotspots.csv the csv/json presets use so it renders on the page.
// (Its `extends:` jsDelivr URL is fetched over the network at render time.)
const withServedExtendsData = (config: string): string =>
config.replace(
'data: ./data/hotspots-extends.csv',
'data: /protvista/sample-data/hotspots.csv'
);

export interface Preset {
/** Stable id used in shareable links (`#preset=<id>`). */
id: string;
Expand Down Expand Up @@ -97,6 +116,15 @@ export const PRESETS: readonly Preset[] = [
config: withServedData(jsonConfig),
accession: DEFAULT_ACCESSION,
},
{
id: 'extend-uniprot',
label: 'Extend UniProt (your track + the full default viewer)',
description:
'Your own track layered on the entire default UniProt viewer via ' +
'extends: — fetches the version-pinned base config over the network.',
config: withServedExtendsData(extendUniprotConfig),
accession: DEFAULT_ACCESSION,
},
];

/**
Expand Down
Loading