@lad-sapienza/scms-core 0.1.0-alpha.6 → 0.1.0-alpha.7
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/README.md
CHANGED
|
@@ -51,6 +51,7 @@ import { DataTb, Map, Gallery } from '@lad-sapienza/scms-core';
|
|
|
51
51
|
| `MapComponent` (`Map`) | Interactive map with MapLibre GL JS |
|
|
52
52
|
| `Gallery` | Responsive image gallery with lightbox |
|
|
53
53
|
| `TableOfContents` | Auto-generated TOC from headings |
|
|
54
|
+
| `RedirectPage` | Static client-side redirect stub (meta-refresh + JS fallback) for static hosts |
|
|
54
55
|
| `ZoteroGeoViewer` | Zotero library visualised on a map |
|
|
55
56
|
| `RecordProvider`, `Field`, `Image`, `RecordFetcher`, `useRecordFetcher` | Build single-record detail pages against Directus |
|
|
56
57
|
| `SearchUI`, `SearchUISimple`, `SearchUIAdvanced` | Field/operator/value search UI (used by `Map`'s `searchInFields`) |
|
|
@@ -63,7 +64,7 @@ import BSNavbar from '@lad-sapienza/scms-core/components/BSNavbar';
|
|
|
63
64
|
import { directusLoader } from '@lad-sapienza/scms-core/integrations/directusLoader';
|
|
64
65
|
```
|
|
65
66
|
|
|
66
|
-
See each component folder's own `README.md` (`components/DataTb`, `components/Gallery`, `components/ZoteroGeoViewer`, `components/`) for detailed API docs and examples.
|
|
67
|
+
See each component folder's own `README.md` (`components/DataTb`, `components/Gallery`, `components/RedirectPage`, `components/ZoteroGeoViewer`, `components/`) for detailed API docs and examples.
|
|
67
68
|
|
|
68
69
|
## Creating a new site
|
|
69
70
|
|
|
@@ -31,35 +31,11 @@ if (explicitImages && explicitImages.length > 0) {
|
|
|
31
31
|
}
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
-
{finalImages.length > 0
|
|
34
|
+
{finalImages.length > 0 && (
|
|
35
35
|
<GalleryClient
|
|
36
36
|
images={finalImages}
|
|
37
37
|
columns={columns}
|
|
38
38
|
className={className}
|
|
39
39
|
client:idle
|
|
40
40
|
/>
|
|
41
|
-
) : (
|
|
42
|
-
<p class="gallery-empty">
|
|
43
|
-
No images found{name && <> for gallery "<code>{name}</code>"</>}.
|
|
44
|
-
{!name && !explicitImages && (
|
|
45
|
-
<> Add images to a <code>gallery/</code> folder next to this page.</>
|
|
46
|
-
)}
|
|
47
|
-
</p>
|
|
48
41
|
)}
|
|
49
|
-
|
|
50
|
-
<style>
|
|
51
|
-
.gallery-empty {
|
|
52
|
-
padding: 2rem;
|
|
53
|
-
background: #f5f5f5;
|
|
54
|
-
border-radius: 8px;
|
|
55
|
-
text-align: center;
|
|
56
|
-
color: #666;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.gallery-empty code {
|
|
60
|
-
background: #e0e0e0;
|
|
61
|
-
padding: 2px 6px;
|
|
62
|
-
border-radius: 3px;
|
|
63
|
-
font-family: monospace;
|
|
64
|
-
}
|
|
65
|
-
</style>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# RedirectPage Component
|
|
2
|
+
|
|
3
|
+
A static, client-side redirect stub for static hosts (GitHub Pages, S3, any
|
|
4
|
+
CDN without server-side redirect support). Renders a page that redirects via
|
|
5
|
+
`<meta http-equiv="refresh">`, a `<link rel="canonical">` for search engines,
|
|
6
|
+
and a `window.location.replace()` fallback for browsers that ignore
|
|
7
|
+
meta-refresh.
|
|
8
|
+
|
|
9
|
+
## When to use this vs. Astro's native `redirects`
|
|
10
|
+
|
|
11
|
+
Astro's [`redirects`](https://docs.astro.build/en/reference/configuration-reference/#redirects)
|
|
12
|
+
config option generates the same kind of stub automatically for `output:
|
|
13
|
+
'static'` sites, and should be preferred whenever it applies — it's zero
|
|
14
|
+
extra code. Reach for `RedirectPage` only when `redirects` can't express the
|
|
15
|
+
mapping.
|
|
16
|
+
|
|
17
|
+
**Works fine with native `redirects`:** a static source path redirecting to
|
|
18
|
+
a destination produced by a dynamic route, as long as the destination is
|
|
19
|
+
given as a concrete, already-resolved path (not a bracketed route pattern).
|
|
20
|
+
Astro only validates dynamic-parameter propagation when the *source* path
|
|
21
|
+
itself has dynamic segments — a static source skips that check entirely.
|
|
22
|
+
Confirmed empirically against Astro 7.2.4 (`output: 'static'`): a source
|
|
23
|
+
route with no params, e.g. `/chi-siamo`, redirecting to `/it/chi-siamo`
|
|
24
|
+
(itself generated by a `src/pages/[locale]/chi-siamo.astro` with
|
|
25
|
+
`getStaticPaths`), builds and emits the expected redirect stub with no
|
|
26
|
+
errors.
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
// astro.config.mjs
|
|
30
|
+
export default defineConfig({
|
|
31
|
+
redirects: {
|
|
32
|
+
'/chi-siamo': '/it/chi-siamo',
|
|
33
|
+
'/notizie': '/it/notizie',
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Needs `RedirectPage` instead:** the source path itself is dynamic — e.g.
|
|
39
|
+
one redirect per old article slug, `/notizie/<slug>` → `/it/notizie/<slug>`
|
|
40
|
+
— *and* the destination route has a dynamic parameter the source doesn't
|
|
41
|
+
carry (typically a locale prefix). Astro requires the destination's dynamic
|
|
42
|
+
parameters to already be present in the source; `[locale]` isn't, since the
|
|
43
|
+
old flat URL had no locale segment. Trying to force it fails at build time:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
redirects: {
|
|
47
|
+
'/notizie/[...slug]': '/it/notizie/[...slug]', // does NOT match the
|
|
48
|
+
// registered `/[locale]/notizie/[...slug]` route — this throws
|
|
49
|
+
// InvalidRedirectDestination: "The destination ... does not match any
|
|
50
|
+
// existing route in your project."
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
There's no config-level way to say "always substitute `it` for `[locale]`
|
|
55
|
+
here" — the list of old slugs to redirect, and the mapping to each new URL,
|
|
56
|
+
has to come from actual code that knows about the content collection. That's
|
|
57
|
+
what the recipe below does.
|
|
58
|
+
|
|
59
|
+
## Basic usage — single static redirect
|
|
60
|
+
|
|
61
|
+
For a handful of one-off redirects where you'd rather not touch
|
|
62
|
+
`astro.config.mjs` (or where the source **is** dynamic but happens not to
|
|
63
|
+
need a config-level `redirects` entry), drop a page using `RedirectPage`
|
|
64
|
+
directly:
|
|
65
|
+
|
|
66
|
+
```astro
|
|
67
|
+
---
|
|
68
|
+
// src/pages/chi-siamo.astro
|
|
69
|
+
import { RedirectPage } from '@lad-sapienza/scms-core';
|
|
70
|
+
export const prerender = true;
|
|
71
|
+
---
|
|
72
|
+
<RedirectPage target="/it/chi-siamo" />
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Recipe — redirecting every entry of a content collection
|
|
76
|
+
|
|
77
|
+
The common case: a collection is moving from a flat URL (`/notizie/<slug>/`)
|
|
78
|
+
to a locale-prefixed one (`/it/notizie/<slug>/`), and every existing entry
|
|
79
|
+
needs its own redirect stub. Generate one page per old slug with
|
|
80
|
+
`getStaticPaths`, reading the slug list straight from the collection so the
|
|
81
|
+
redirect list can never drift out of sync with the content itself:
|
|
82
|
+
|
|
83
|
+
```astro
|
|
84
|
+
---
|
|
85
|
+
// src/pages/notizie/[...slug].astro
|
|
86
|
+
import { RedirectPage } from '@lad-sapienza/scms-core';
|
|
87
|
+
import { getCollection } from 'astro:content';
|
|
88
|
+
|
|
89
|
+
export const prerender = true;
|
|
90
|
+
|
|
91
|
+
export async function getStaticPaths() {
|
|
92
|
+
const articles = await getCollection('notizie');
|
|
93
|
+
// Adapt this to however your entry IDs encode locale/slug — e.g. if
|
|
94
|
+
// content lives under src/content/notizie/it/<slug>/, split the id
|
|
95
|
+
// yourself and keep only the default-locale entries (each locale has the
|
|
96
|
+
// same slug, so the redirect only needs to be generated once).
|
|
97
|
+
return articles
|
|
98
|
+
.filter((a) => a.id.startsWith('it/'))
|
|
99
|
+
.map((a) => ({ params: { slug: a.id.slice('it/'.length) } }));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { slug } = Astro.params;
|
|
103
|
+
---
|
|
104
|
+
<RedirectPage target={`/it/notizie/${slug}/`} />
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Repeat one such `[...slug].astro` per collection that needs migrating
|
|
108
|
+
(`blog`, `ricerca`, `didattica`, ...) — the body only changes in the
|
|
109
|
+
collection name and the target prefix. A collection's own `index.astro`
|
|
110
|
+
(the old flat listing page) is a single static redirect and can either use
|
|
111
|
+
this same component directly or, per the section above, a plain
|
|
112
|
+
`redirects` config entry.
|
|
113
|
+
|
|
114
|
+
## Props
|
|
115
|
+
|
|
116
|
+
| Prop | Type | Default | Description |
|
|
117
|
+
|---|---|---|---|
|
|
118
|
+
| `target` | `string` | — | Destination URL to redirect to (required) |
|
|
119
|
+
| `title` | `string` | `"Redirecting…"` | Page `<title>`, shown briefly before the redirect fires |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Static client-side redirect stub (meta-refresh + JS), for static hosts
|
|
4
|
+
* where server-side redirects aren't available (e.g. GitHub Pages). Render
|
|
5
|
+
* one of these at each old URL to send visitors/search engines/citations to
|
|
6
|
+
* a new location — typically after a URL scheme change (e.g. adding an
|
|
7
|
+
* i18n locale prefix) that Astro's own config-level `redirects` can't
|
|
8
|
+
* express. See `components/RedirectPage/README.md` for when to reach for
|
|
9
|
+
* this instead of `redirects`, and for the `getStaticPaths` recipe that
|
|
10
|
+
* generates one of these per entry of a content collection.
|
|
11
|
+
*/
|
|
12
|
+
interface Props {
|
|
13
|
+
/** Destination URL to redirect to */
|
|
14
|
+
target: string
|
|
15
|
+
/** Page title shown briefly before the redirect fires */
|
|
16
|
+
title?: string
|
|
17
|
+
}
|
|
18
|
+
const { target, title = "Redirecting…" } = Astro.props
|
|
19
|
+
---
|
|
20
|
+
<!doctype html>
|
|
21
|
+
<html lang="en">
|
|
22
|
+
<head>
|
|
23
|
+
<meta charset="UTF-8" />
|
|
24
|
+
<meta http-equiv="refresh" content={`0; url=${target}`} />
|
|
25
|
+
<link rel="canonical" href={target} />
|
|
26
|
+
<title>{title}</title>
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
<p>Redirecting to <a href={target}>{target}</a>…</p>
|
|
30
|
+
<script is:inline define:vars={{ target }}>
|
|
31
|
+
window.location.replace(target);
|
|
32
|
+
</script>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
package/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Core package exports
|
|
2
2
|
export { Gallery } from './components/Gallery';
|
|
3
3
|
export { default as TableOfContents } from './components/TableOfContents/TableOfContents.astro';
|
|
4
|
+
export { default as RedirectPage } from './components/RedirectPage/RedirectPage.astro';
|
|
4
5
|
export { default as ThemeToggle } from './components/ThemeToggle';
|
|
5
6
|
|
|
6
7
|
// DataTb (recommended table component)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lad-sapienza/scms-core",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"description": "Framework components and Astro integrations for s:CMS — DataTb, Gallery, Map, ZoteroGeoViewer, Record.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BSD-0-Clause",
|