tfrere HF Staff commited on
Commit
ad5fa41
Β·
1 Parent(s): 5580f98

rename figure into image

Browse files
app/.astro/astro/content.d.ts CHANGED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ declare module 'astro:content' {
2
+ interface Render {
3
+ '.mdx': Promise<{
4
+ Content: import('astro').MarkdownInstance<{}>['Content'];
5
+ headings: import('astro').MarkdownHeading[];
6
+ remarkPluginFrontmatter: Record<string, any>;
7
+ components: import('astro').MDXInstance<{}>['components'];
8
+ }>;
9
+ }
10
+ }
11
+
12
+ declare module 'astro:content' {
13
+ interface RenderResult {
14
+ Content: import('astro/runtime/server/index.js').AstroComponentFactory;
15
+ headings: import('astro').MarkdownHeading[];
16
+ remarkPluginFrontmatter: Record<string, any>;
17
+ }
18
+ interface Render {
19
+ '.md': Promise<RenderResult>;
20
+ }
21
+
22
+ export interface RenderedContent {
23
+ html: string;
24
+ metadata?: {
25
+ imagePaths: Array<string>;
26
+ [key: string]: unknown;
27
+ };
28
+ }
29
+ }
30
+
31
+ declare module 'astro:content' {
32
+ type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
33
+
34
+ export type CollectionKey = keyof AnyEntryMap;
35
+ export type CollectionEntry<C extends CollectionKey> = Flatten<AnyEntryMap[C]>;
36
+
37
+ export type ContentCollectionKey = keyof ContentEntryMap;
38
+ export type DataCollectionKey = keyof DataEntryMap;
39
+
40
+ type AllValuesOf<T> = T extends any ? T[keyof T] : never;
41
+ type ValidContentEntrySlug<C extends keyof ContentEntryMap> = AllValuesOf<
42
+ ContentEntryMap[C]
43
+ >['slug'];
44
+
45
+ /** @deprecated Use `getEntry` instead. */
46
+ export function getEntryBySlug<
47
+ C extends keyof ContentEntryMap,
48
+ E extends ValidContentEntrySlug<C> | (string & {}),
49
+ >(
50
+ collection: C,
51
+ // Note that this has to accept a regular string too, for SSR
52
+ entrySlug: E,
53
+ ): E extends ValidContentEntrySlug<C>
54
+ ? Promise<CollectionEntry<C>>
55
+ : Promise<CollectionEntry<C> | undefined>;
56
+
57
+ /** @deprecated Use `getEntry` instead. */
58
+ export function getDataEntryById<C extends keyof DataEntryMap, E extends keyof DataEntryMap[C]>(
59
+ collection: C,
60
+ entryId: E,
61
+ ): Promise<CollectionEntry<C>>;
62
+
63
+ export function getCollection<C extends keyof AnyEntryMap, E extends CollectionEntry<C>>(
64
+ collection: C,
65
+ filter?: (entry: CollectionEntry<C>) => entry is E,
66
+ ): Promise<E[]>;
67
+ export function getCollection<C extends keyof AnyEntryMap>(
68
+ collection: C,
69
+ filter?: (entry: CollectionEntry<C>) => unknown,
70
+ ): Promise<CollectionEntry<C>[]>;
71
+
72
+ export function getEntry<
73
+ C extends keyof ContentEntryMap,
74
+ E extends ValidContentEntrySlug<C> | (string & {}),
75
+ >(entry: {
76
+ collection: C;
77
+ slug: E;
78
+ }): E extends ValidContentEntrySlug<C>
79
+ ? Promise<CollectionEntry<C>>
80
+ : Promise<CollectionEntry<C> | undefined>;
81
+ export function getEntry<
82
+ C extends keyof DataEntryMap,
83
+ E extends keyof DataEntryMap[C] | (string & {}),
84
+ >(entry: {
85
+ collection: C;
86
+ id: E;
87
+ }): E extends keyof DataEntryMap[C]
88
+ ? Promise<DataEntryMap[C][E]>
89
+ : Promise<CollectionEntry<C> | undefined>;
90
+ export function getEntry<
91
+ C extends keyof ContentEntryMap,
92
+ E extends ValidContentEntrySlug<C> | (string & {}),
93
+ >(
94
+ collection: C,
95
+ slug: E,
96
+ ): E extends ValidContentEntrySlug<C>
97
+ ? Promise<CollectionEntry<C>>
98
+ : Promise<CollectionEntry<C> | undefined>;
99
+ export function getEntry<
100
+ C extends keyof DataEntryMap,
101
+ E extends keyof DataEntryMap[C] | (string & {}),
102
+ >(
103
+ collection: C,
104
+ id: E,
105
+ ): E extends keyof DataEntryMap[C]
106
+ ? Promise<DataEntryMap[C][E]>
107
+ : Promise<CollectionEntry<C> | undefined>;
108
+
109
+ /** Resolve an array of entry references from the same collection */
110
+ export function getEntries<C extends keyof ContentEntryMap>(
111
+ entries: {
112
+ collection: C;
113
+ slug: ValidContentEntrySlug<C>;
114
+ }[],
115
+ ): Promise<CollectionEntry<C>[]>;
116
+ export function getEntries<C extends keyof DataEntryMap>(
117
+ entries: {
118
+ collection: C;
119
+ id: keyof DataEntryMap[C];
120
+ }[],
121
+ ): Promise<CollectionEntry<C>[]>;
122
+
123
+ export function render<C extends keyof AnyEntryMap>(
124
+ entry: AnyEntryMap[C][string],
125
+ ): Promise<RenderResult>;
126
+
127
+ export function reference<C extends keyof AnyEntryMap>(
128
+ collection: C,
129
+ ): import('astro/zod').ZodEffects<
130
+ import('astro/zod').ZodString,
131
+ C extends keyof ContentEntryMap
132
+ ? {
133
+ collection: C;
134
+ slug: ValidContentEntrySlug<C>;
135
+ }
136
+ : {
137
+ collection: C;
138
+ id: keyof DataEntryMap[C];
139
+ }
140
+ >;
141
+ // Allow generic `string` to avoid excessive type errors in the config
142
+ // if `dev` is not running to update as you edit.
143
+ // Invalid collection names will be caught at build time.
144
+ export function reference<C extends string>(
145
+ collection: C,
146
+ ): import('astro/zod').ZodEffects<import('astro/zod').ZodString, never>;
147
+
148
+ type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
149
+ type InferEntrySchema<C extends keyof AnyEntryMap> = import('astro/zod').infer<
150
+ ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
151
+ >;
152
+
153
+ type ContentEntryMap = {
154
+ "chapters": {
155
+ "demo/best-pratices.mdx": {
156
+ id: "demo/best-pratices.mdx";
157
+ slug: "demo/best-pratices";
158
+ body: string;
159
+ collection: "chapters";
160
+ data: any
161
+ } & { render(): Render[".mdx"] };
162
+ "demo/components.mdx": {
163
+ id: "demo/components.mdx";
164
+ slug: "demo/components";
165
+ body: string;
166
+ collection: "chapters";
167
+ data: any
168
+ } & { render(): Render[".mdx"] };
169
+ "demo/debug-components.mdx": {
170
+ id: "demo/debug-components.mdx";
171
+ slug: "demo/debug-components";
172
+ body: string;
173
+ collection: "chapters";
174
+ data: any
175
+ } & { render(): Render[".mdx"] };
176
+ "demo/getting-started.mdx": {
177
+ id: "demo/getting-started.mdx";
178
+ slug: "demo/getting-started";
179
+ body: string;
180
+ collection: "chapters";
181
+ data: any
182
+ } & { render(): Render[".mdx"] };
183
+ "demo/greetings.mdx": {
184
+ id: "demo/greetings.mdx";
185
+ slug: "demo/greetings";
186
+ body: string;
187
+ collection: "chapters";
188
+ data: any
189
+ } & { render(): Render[".mdx"] };
190
+ "demo/import-content.mdx": {
191
+ id: "demo/import-content.mdx";
192
+ slug: "demo/import-content";
193
+ body: string;
194
+ collection: "chapters";
195
+ data: any
196
+ } & { render(): Render[".mdx"] };
197
+ "demo/introduction.mdx": {
198
+ id: "demo/introduction.mdx";
199
+ slug: "demo/introduction";
200
+ body: string;
201
+ collection: "chapters";
202
+ data: any
203
+ } & { render(): Render[".mdx"] };
204
+ "demo/markdown.mdx": {
205
+ id: "demo/markdown.mdx";
206
+ slug: "demo/markdown";
207
+ body: string;
208
+ collection: "chapters";
209
+ data: any
210
+ } & { render(): Render[".mdx"] };
211
+ "demo/vibe-coding-charts.mdx": {
212
+ id: "demo/vibe-coding-charts.mdx";
213
+ slug: "demo/vibe-coding-charts";
214
+ body: string;
215
+ collection: "chapters";
216
+ data: any
217
+ } & { render(): Render[".mdx"] };
218
+ "demo/writing-your-content.mdx": {
219
+ id: "demo/writing-your-content.mdx";
220
+ slug: "demo/writing-your-content";
221
+ body: string;
222
+ collection: "chapters";
223
+ data: any
224
+ } & { render(): Render[".mdx"] };
225
+ "your-first-chapter.mdx": {
226
+ id: "your-first-chapter.mdx";
227
+ slug: "your-first-chapter";
228
+ body: string;
229
+ collection: "chapters";
230
+ data: any
231
+ } & { render(): Render[".mdx"] };
232
+ };
233
+ "embeds": {
234
+ "vibe-code-d3-embeds-directives.md": {
235
+ id: "vibe-code-d3-embeds-directives.md";
236
+ slug: "vibe-code-d3-embeds-directives";
237
+ body: string;
238
+ collection: "embeds";
239
+ data: any
240
+ } & { render(): Render[".md"] };
241
+ };
242
+
243
+ };
244
+
245
+ type DataEntryMap = {
246
+ "assets": {
247
+ "data/data": {
248
+ id: "data/data";
249
+ collection: "assets";
250
+ data: any
251
+ };
252
+ "data/font-sprite-mapping": {
253
+ id: "data/font-sprite-mapping";
254
+ collection: "assets";
255
+ data: any
256
+ };
257
+ "data/font_manifest": {
258
+ id: "data/font_manifest";
259
+ collection: "assets";
260
+ data: any
261
+ };
262
+ "data/llm_benchmarks": {
263
+ id: "data/llm_benchmarks";
264
+ collection: "assets";
265
+ data: any
266
+ };
267
+ "data/mnist-variant-model": {
268
+ id: "data/mnist-variant-model";
269
+ collection: "assets";
270
+ data: any
271
+ };
272
+ "data/typography_data": {
273
+ id: "data/typography_data";
274
+ collection: "assets";
275
+ data: any
276
+ };
277
+ };
278
+
279
+ };
280
+
281
+ type AnyEntryMap = ContentEntryMap & DataEntryMap;
282
+
283
+ export type ContentConfig = never;
284
+ }
app/src/components/{Figure.astro β†’ Image.astro} RENAMED
@@ -1,6 +1,6 @@
1
  ---
2
  // @ts-ignore - types provided by Astro at runtime
3
- import { Image } from "astro:assets";
4
 
5
  interface Props {
6
  /** Source image imported via astro:assets */
@@ -25,7 +25,7 @@ interface Props {
25
  linkTarget?: string;
26
  /** Optional rel for the link (default: noopener noreferrer when linkHref provided) */
27
  linkRel?: string;
28
- /** Any additional attributes should be forwarded to the underlying <Image> */
29
  [key: string]: any;
30
  }
31
 
@@ -71,7 +71,7 @@ const resolvedRel = hasLink ? linkRel || "noopener noreferrer" : undefined;
71
  target={resolvedTarget}
72
  rel={resolvedRel}
73
  >
74
- <Image
75
  {...imgProps}
76
  data-zoomable={dataZoomable}
77
  data-downloadable={dataDownloadable}
@@ -80,7 +80,7 @@ const resolvedRel = hasLink ? linkRel || "noopener noreferrer" : undefined;
80
  />
81
  </a>
82
  ) : (
83
- <Image
84
  {...imgProps}
85
  data-zoomable={dataZoomable}
86
  data-downloadable={dataDownloadable}
@@ -108,10 +108,10 @@ const resolvedRel = hasLink ? linkRel || "noopener noreferrer" : undefined;
108
  target={resolvedTarget}
109
  rel={resolvedRel}
110
  >
111
- <Image {...imgProps} data-zoomable={dataZoomable} />
112
  </a>
113
  ) : (
114
- <Image {...imgProps} data-zoomable={dataZoomable} />
115
  )}
116
  <figcaption>
117
  {hasCaptionSlot ? (
@@ -130,7 +130,7 @@ const resolvedRel = hasLink ? linkRel || "noopener noreferrer" : undefined;
130
  target={resolvedTarget}
131
  rel={resolvedRel}
132
  >
133
- <Image
134
  {...imgProps}
135
  data-zoomable={dataZoomable}
136
  data-downloadable={dataDownloadable}
@@ -139,7 +139,7 @@ const resolvedRel = hasLink ? linkRel || "noopener noreferrer" : undefined;
139
  />
140
  </a>
141
  ) : (
142
- <Image
143
  {...imgProps}
144
  data-zoomable={dataZoomable}
145
  data-downloadable={dataDownloadable}
@@ -165,10 +165,10 @@ const resolvedRel = hasLink ? linkRel || "noopener noreferrer" : undefined;
165
  target={resolvedTarget}
166
  rel={resolvedRel}
167
  >
168
- <Image {...imgProps} data-zoomable={dataZoomable} />
169
  </a>
170
  ) : (
171
- <Image {...imgProps} data-zoomable={dataZoomable} />
172
  )
173
  }
174
  </div>
 
1
  ---
2
  // @ts-ignore - types provided by Astro at runtime
3
+ import { Image as AstroImage } from "astro:assets";
4
 
5
  interface Props {
6
  /** Source image imported via astro:assets */
 
25
  linkTarget?: string;
26
  /** Optional rel for the link (default: noopener noreferrer when linkHref provided) */
27
  linkRel?: string;
28
+ /** Any additional attributes should be forwarded to the underlying <AstroImage> */
29
  [key: string]: any;
30
  }
31
 
 
71
  target={resolvedTarget}
72
  rel={resolvedRel}
73
  >
74
+ <AstroImage
75
  {...imgProps}
76
  data-zoomable={dataZoomable}
77
  data-downloadable={dataDownloadable}
 
80
  />
81
  </a>
82
  ) : (
83
+ <AstroImage
84
  {...imgProps}
85
  data-zoomable={dataZoomable}
86
  data-downloadable={dataDownloadable}
 
108
  target={resolvedTarget}
109
  rel={resolvedRel}
110
  >
111
+ <AstroImage {...imgProps} data-zoomable={dataZoomable} />
112
  </a>
113
  ) : (
114
+ <AstroImage {...imgProps} data-zoomable={dataZoomable} />
115
  )}
116
  <figcaption>
117
  {hasCaptionSlot ? (
 
130
  target={resolvedTarget}
131
  rel={resolvedRel}
132
  >
133
+ <AstroImage
134
  {...imgProps}
135
  data-zoomable={dataZoomable}
136
  data-downloadable={dataDownloadable}
 
139
  />
140
  </a>
141
  ) : (
142
+ <AstroImage
143
  {...imgProps}
144
  data-zoomable={dataZoomable}
145
  data-downloadable={dataDownloadable}
 
165
  target={resolvedTarget}
166
  rel={resolvedRel}
167
  >
168
+ <AstroImage {...imgProps} data-zoomable={dataZoomable} />
169
  </a>
170
  ) : (
171
+ <AstroImage {...imgProps} data-zoomable={dataZoomable} />
172
  )
173
  }
174
  </div>
app/src/components/{MultiFigure.astro β†’ MultiImage.astro} RENAMED
@@ -1,6 +1,6 @@
1
  ---
2
  // @ts-ignore - types provided by Astro at runtime
3
- import Figure from "./Figure.astro";
4
 
5
  interface ImageItem {
6
  /** Source image imported via astro:assets */
@@ -83,7 +83,7 @@ const gridColumns = getGridColumns();
83
  >
84
  {images.map((image, index) => (
85
  <div class="multi-image-item">
86
- <Figure
87
  src={image.src}
88
  alt={image.alt}
89
  zoomable={image.zoomable ?? zoomable}
@@ -121,7 +121,7 @@ const gridColumns = getGridColumns();
121
  >
122
  {images.map((image, index) => (
123
  <div class="multi-image-item">
124
- <Figure
125
  src={image.src}
126
  alt={image.alt}
127
  zoomable={image.zoomable ?? zoomable}
 
1
  ---
2
  // @ts-ignore - types provided by Astro at runtime
3
+ import Image from "./Image.astro";
4
 
5
  interface ImageItem {
6
  /** Source image imported via astro:assets */
 
83
  >
84
  {images.map((image, index) => (
85
  <div class="multi-image-item">
86
+ <Image
87
  src={image.src}
88
  alt={image.alt}
89
  zoomable={image.zoomable ?? zoomable}
 
121
  >
122
  {images.map((image, index) => (
123
  <div class="multi-image-item">
124
+ <Image
125
  src={image.src}
126
  alt={image.alt}
127
  zoomable={image.zoomable ?? zoomable}
app/src/components/Reference.astro ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ interface Props {
3
+ /** ID unique pour la rΓ©fΓ©rence */
4
+ id: string;
5
+ /** LΓ©gende HTML pour la rΓ©fΓ©rence */
6
+ caption: string;
7
+ }
8
+
9
+ const { id, caption } = Astro.props as Props;
10
+ ---
11
+
12
+ <div class="reference-wrapper" id={id}>
13
+ <figure class="reference">
14
+ <div class="reference__content">
15
+ <slot />
16
+ </div>
17
+ <figcaption class="reference__caption" set:html={caption} />
18
+ </figure>
19
+ </div>
20
+
21
+ <style>
22
+ .reference-wrapper {
23
+ margin: var(--block-spacing-y) 0;
24
+ }
25
+
26
+ .reference {
27
+ margin: 0;
28
+ }
29
+
30
+ .reference__content {
31
+ /* Le contenu peut Γͺtre n'importe quoi */
32
+ }
33
+
34
+ .reference__caption {
35
+ text-align: left;
36
+ font-size: 0.9rem;
37
+ color: var(--muted-color);
38
+ margin-top: 6px;
39
+ background: var(--page-bg);
40
+ position: relative;
41
+ z-index: var(--z-elevated);
42
+ display: block;
43
+ width: 100%;
44
+ }
45
+ </style>
app/src/content/chapters/demo/best-pratices.mdx CHANGED
@@ -1,7 +1,7 @@
1
 
2
  import visualPoster from '../../assets/image/visual-vocabulary-poster.png';
3
  import Note from '../../../components/Note.astro';
4
- import Figure from '../../../components/Figure.astro';
5
  import HtmlEmbed from '../../../components/HtmlEmbed.astro';
6
  import Sidenote from '../../../components/Sidenote.astro';
7
 
@@ -44,7 +44,7 @@ Favor **concise captions** and callouts that clarify what to look at and why it
44
 
45
  Picking the right visualization depends on your goal (compare values, show distribution, part-to-whole, trends, relationships, etc.). The Visual Vocabulary poster below provides a concise mapping from **analytical task** to **chart types**.
46
 
47
- <Figure
48
  src={visualPoster}
49
  alt="Visual Vocabulary: choosing the right chart by task"
50
  linkHref="https://raw.githubusercontent.com/Financial-Times/chart-doctor/refs/heads/main/visual-vocabulary/poster.png"
 
1
 
2
  import visualPoster from '../../assets/image/visual-vocabulary-poster.png';
3
  import Note from '../../../components/Note.astro';
4
+ import Image from '../../../components/Image.astro';
5
  import HtmlEmbed from '../../../components/HtmlEmbed.astro';
6
  import Sidenote from '../../../components/Sidenote.astro';
7
 
 
44
 
45
  Picking the right visualization depends on your goal (compare values, show distribution, part-to-whole, trends, relationships, etc.). The Visual Vocabulary poster below provides a concise mapping from **analytical task** to **chart types**.
46
 
47
+ <Image
48
  src={visualPoster}
49
  alt="Visual Vocabulary: choosing the right chart by task"
50
  linkHref="https://raw.githubusercontent.com/Financial-Times/chart-doctor/refs/heads/main/visual-vocabulary/poster.png"
app/src/content/chapters/demo/components.mdx CHANGED
@@ -1,4 +1,4 @@
1
- import { Image } from 'astro:assets';
2
  import placeholder from '../../assets/image/placeholder.png';
3
  import audioDemo from '../../assets/audio/audio-example.wav';
4
  import HtmlEmbed from '../../../components/HtmlEmbed.astro';
@@ -7,9 +7,10 @@ import Wide from '../../../components/Wide.astro';
7
  import Note from '../../../components/Note.astro';
8
  import FullWidth from '../../../components/FullWidth.astro';
9
  import Accordion from '../../../components/Accordion.astro';
10
- import Figure from '../../../components/Figure.astro';
11
- import SubFigures from '../../../components/MultiFigure.astro';
12
  import Quote from '../../../components/Quote.astro';
 
13
 
14
  ## Components
15
 
@@ -20,13 +21,13 @@ import Quote from '../../../components/Quote.astro';
20
  To use any component in your MDX file, add the import statement at the top:
21
 
22
  ```mdx
23
- import Figure from '../components/Figure.astro';
24
- import SubFigures from '../components/MultiFigure.astro';
25
  import Note from '../components/Note.astro';
26
 
27
  # Your content
28
 
29
- <Figure src={myImage} alt="Description" />
30
  <Note>This is a note</Note>
31
  ```
32
 
@@ -34,13 +35,13 @@ Here are the components that are available:
34
 
35
 
36
  <div className="feature-grid">
37
- <a href="#figure" className="feature-card">
38
- <strong>Figure</strong>
39
  <span>Optimized images</span>
40
  </a>
41
- <a href="#subfigures" className="feature-card">
42
- <strong>SubFigures</strong>
43
- <span>Multi-panel figures</span>
44
  </a>
45
  <a href="#placement" className="feature-card">
46
  <strong>Placement</strong>
@@ -62,18 +63,22 @@ Here are the components that are available:
62
  <strong>HtmlEmbed</strong>
63
  <span>External content</span>
64
  </a>
 
 
 
 
65
  <a href="#iframe" className="feature-card">
66
  <strong>Iframe</strong>
67
  <span>Web embeds</span>
68
  </a>
69
  </div>
70
 
71
- ### Figure
72
 
73
- **Figures** automatically generate optimized `srcset` and `sizes` so the browser downloads the most appropriate file for the current viewport and DPR. You can also request multiple output formats (e.g., **AVIF**, **WebP**, fallback **PNG/JPEG**) and control **lazy loading/decoding** for better **performance**.
74
 
75
 
76
- <Figure
77
  src={placeholder}
78
  zoomable
79
  downloadable
@@ -94,12 +99,12 @@ Here are the components that are available:
94
 
95
  <Accordion title="Code example">
96
  ```mdx
97
- import Figure from '../../../components/Figure.astro'
98
  import myImage from './assets/image/placeholder.jpg'
99
 
100
- <Figure src={myImage} alt="Optimized figure with caption" />
101
 
102
- <Figure
103
  src={myImage}
104
  layout="fixed"
105
  zoomable
@@ -111,11 +116,11 @@ import myImage from './assets/image/placeholder.jpg'
111
  ```
112
  </Accordion>
113
 
114
- ### SubFigures
115
 
116
- **Display multiple figures** in a grid layout with customizable columns and captions. Perfect for **multi-panel figures**, **comparisons**, and **step-by-step visualizations** β€” just like LaTeX's `subfigure` environment.
117
 
118
- <SubFigures
119
  images={[
120
  { src: placeholder, alt: "Image 1", caption: "First image with caption" },
121
  { src: placeholder, alt: "Image 2", caption: "Second image" },
@@ -130,7 +135,7 @@ import myImage from './assets/image/placeholder.jpg'
130
  ```mdx
131
  import placeholder from '../assets/image/placeholder.png';
132
 
133
- <SubFigures
134
  images={[
135
  { src: placeholder, alt: "Panel A", caption: "(a) First panel" },
136
  { src: placeholder, alt: "Panel B", caption: "(b) Second panel" },
@@ -143,8 +148,15 @@ import placeholder from '../assets/image/placeholder.png';
143
  ```
144
  </Accordion>
145
 
146
- **Layout options:** `2-column`, `3-column`, `4-column`, `auto`
147
- **Features:** Individual subcaptions (a), (b), (c), zoom functionality, responsive design
 
 
 
 
 
 
 
148
 
149
  ### Placement
150
 
@@ -201,6 +213,53 @@ import FullWidth from '../../../components/FullWidth.astro'
201
  </Accordion>
202
 
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  ### Accordion
205
 
206
  Can be used like this `<Accordion>some content</Accordion>`. You can pass any children content.
@@ -276,7 +335,7 @@ Small contextual callout for tips, caveats, or emphasis.
276
  | `title` | No | string | Short title displayed in header |
277
  | `emoji` | No | string | Emoji displayed before the title |
278
  | `class` | No | string | Extra classes for custom styling |
279
- | `variant`| No | 'info' | 'success' | 'danger' | Visual intent of the note |
280
 
281
  <Accordion title="Code example">
282
  ```mdx
 
1
+ import { Image as AstroImage } from 'astro:assets';
2
  import placeholder from '../../assets/image/placeholder.png';
3
  import audioDemo from '../../assets/audio/audio-example.wav';
4
  import HtmlEmbed from '../../../components/HtmlEmbed.astro';
 
7
  import Note from '../../../components/Note.astro';
8
  import FullWidth from '../../../components/FullWidth.astro';
9
  import Accordion from '../../../components/Accordion.astro';
10
+ import Image from '../../../components/Image.astro';
11
+ import MultiImage from '../../../components/MultiImage.astro';
12
  import Quote from '../../../components/Quote.astro';
13
+ import Reference from '../../../components/Reference.astro';
14
 
15
  ## Components
16
 
 
21
  To use any component in your MDX file, add the import statement at the top:
22
 
23
  ```mdx
24
+ import Image from '../components/Image.astro';
25
+ import MultiImage from '../components/MultiImage.astro';
26
  import Note from '../components/Note.astro';
27
 
28
  # Your content
29
 
30
+ <Image src={myImage} alt="Description" />
31
  <Note>This is a note</Note>
32
  ```
33
 
 
35
 
36
 
37
  <div className="feature-grid">
38
+ <a href="#image" className="feature-card">
39
+ <strong>Image</strong>
40
  <span>Optimized images</span>
41
  </a>
42
+ <a href="#multiimage" className="feature-card">
43
+ <strong>MultiImage</strong>
44
+ <span>Multi-panel images</span>
45
  </a>
46
  <a href="#placement" className="feature-card">
47
  <strong>Placement</strong>
 
63
  <strong>HtmlEmbed</strong>
64
  <span>External content</span>
65
  </a>
66
+ <a href="#reference" className="feature-card">
67
+ <strong>Reference</strong>
68
+ <span>Flexible content wrapper</span>
69
+ </a>
70
  <a href="#iframe" className="feature-card">
71
  <strong>Iframe</strong>
72
  <span>Web embeds</span>
73
  </a>
74
  </div>
75
 
76
+ ### Image
77
 
78
+ **Images** automatically generate optimized `srcset` and `sizes` so the browser downloads the most appropriate file for the current viewport and DPR. You can also request multiple output formats (e.g., **AVIF**, **WebP**, fallback **PNG/JPEG**) and control **lazy loading/decoding** for better **performance**.
79
 
80
 
81
+ <Image
82
  src={placeholder}
83
  zoomable
84
  downloadable
 
99
 
100
  <Accordion title="Code example">
101
  ```mdx
102
+ import Image from '../../../components/Image.astro'
103
  import myImage from './assets/image/placeholder.jpg'
104
 
105
+ <Image src={myImage} alt="Optimized image with caption" />
106
 
107
+ <Image
108
  src={myImage}
109
  layout="fixed"
110
  zoomable
 
116
  ```
117
  </Accordion>
118
 
119
+ ### MultiImage
120
 
121
+ **Display multiple images** in a grid layout with customizable columns and captions. Perfect for **multi-panel images**, **comparisons**, and **step-by-step visualizations** β€” just like LaTeX's `subfigure` environment.
122
 
123
+ <MultiImage
124
  images={[
125
  { src: placeholder, alt: "Image 1", caption: "First image with caption" },
126
  { src: placeholder, alt: "Image 2", caption: "Second image" },
 
135
  ```mdx
136
  import placeholder from '../assets/image/placeholder.png';
137
 
138
+ <MultiImage
139
  images={[
140
  { src: placeholder, alt: "Panel A", caption: "(a) First panel" },
141
  { src: placeholder, alt: "Panel B", caption: "(b) Second panel" },
 
148
  ```
149
  </Accordion>
150
 
151
+ | Prop | Required | Type | Description
152
+ |------------------------|----------|-----------------------------------------------------------------------|-------------------------------------------------------
153
+ | `images` | Yes | `ImageItem[]` | Array of image objects with `src`, `alt`, and optional `caption`, `id`, `zoomable`, `downloadable` properties
154
+ | `layout` | No | `"2-column" \| "3-column" \| "4-column" \| "auto"` | Grid layout for the images (default: "3-column")
155
+ | `caption` | No | `string` | Global caption for the entire multi-image figure
156
+ | `zoomable` | No | `boolean` | Enable zoom functionality on all images (can be overridden per image)
157
+ | `downloadable` | No | `boolean` | Show download buttons on all images (can be overridden per image)
158
+ | `class` | No | `string` | Additional CSS classes to apply to the wrapper
159
+ | `id` | No | `string` | Global ID for the multi-image figure (for deep-linking and cross-references)
160
 
161
  ### Placement
162
 
 
213
  </Accordion>
214
 
215
 
216
+ ### Reference
217
+
218
+ The **Reference** component provides a flexible wrapper for any content with an ID and HTML caption. It's perfect for creating **numbered references**, **cross-references**, or **any content that needs to be referenced** throughout your article.
219
+
220
+ <Note emoji="πŸ’‘" variant="info">
221
+ **Note:** The `Image` and `HtmlEmbed` components also support the same `id` and `caption` props for consistent referencing across your article.
222
+ </Note>
223
+
224
+ <Reference id="example-reference" caption="<strong>Figure 1:</strong> Example reference with HTML caption and <em>styling</em>">
225
+ you content here...
226
+ </Reference>
227
+
228
+ | Prop | Required | Type | Description |
229
+ |----------|----------|--------|--------------------------------|
230
+ | `id` | Yes | string | Unique identifier for the reference (used for deep-linking) |
231
+ | `caption`| Yes | string | HTML caption displayed below the content (supports HTML tags) |
232
+
233
+ <Accordion title="Code example">
234
+ ```mdx
235
+ import Reference from '../../../components/Reference.astro'
236
+
237
+ <Reference id="my-reference" caption="<strong>Reference 1:</strong> This is a <em>flexible</em> content wrapper">
238
+ <p>Any content can go here...</p>
239
+ <img src={myImage} alt="Description" />
240
+ <div>Even complex HTML structures!</div>
241
+ </Reference>
242
+
243
+ <Reference id="another-ref" caption="<strong>Table 1:</strong> Data comparison with <a href='#'>source link</a>">
244
+ <table>
245
+ <thead>
246
+ <tr><th>Column 1</th><th>Column 2</th></tr>
247
+ </thead>
248
+ <tbody>
249
+ <tr><td>Data 1</td><td>Data 2</td></tr>
250
+ </tbody>
251
+ </table>
252
+ </Reference>
253
+ ```
254
+ </Accordion>
255
+
256
+ **Use cases:**
257
+ - **Numbered figures** with custom content
258
+ - **Cross-references** that can be linked to from anywhere in the article
259
+ - **Flexible content blocks** that need consistent styling and captioning
260
+ - **Tables, charts, or any content** that requires an ID and description
261
+
262
+
263
  ### Accordion
264
 
265
  Can be used like this `<Accordion>some content</Accordion>`. You can pass any children content.
 
335
  | `title` | No | string | Short title displayed in header |
336
  | `emoji` | No | string | Emoji displayed before the title |
337
  | `class` | No | string | Extra classes for custom styling |
338
+ | `variant`| No | 'neutral' | 'info' | 'success' | 'danger' | Visual intent of the note |
339
 
340
  <Accordion title="Code example">
341
  ```mdx
app/src/content/chapters/demo/debug-components.mdx CHANGED
@@ -1,6 +1,6 @@
1
  import Accordion from '../../../components/Accordion.astro';
2
  import HtmlEmbed from '../../../components/HtmlEmbed.astro';
3
- import Figure from '../../../components/Figure.astro';
4
  import Wide from '../../../components/Wide.astro';
5
  import FullWidth from '../../../components/FullWidth.astro';
6
  import Note from '../../../components/Note.astro';
 
1
  import Accordion from '../../../components/Accordion.astro';
2
  import HtmlEmbed from '../../../components/HtmlEmbed.astro';
3
+ import Image from '../../../components/Image.astro';
4
  import Wide from '../../../components/Wide.astro';
5
  import FullWidth from '../../../components/FullWidth.astro';
6
  import Note from '../../../components/Note.astro';
app/src/content/chapters/demo/import-content.mdx CHANGED
@@ -21,7 +21,7 @@ node index.mjs
21
 
22
  - `\label{eq:name}` β†’ Interactive equations
23
  - `\ref{eq:name}` β†’ Clickable links
24
- - `\includegraphics{}` β†’ `<Figure>` components
25
  - Bibliography integration
26
 
27
  ### Prerequisites
 
21
 
22
  - `\label{eq:name}` β†’ Interactive equations
23
  - `\ref{eq:name}` β†’ Clickable links
24
+ - `\includegraphics{}` β†’ `<Image>` components
25
  - Bibliography integration
26
 
27
  ### Prerequisites
app/src/content/chapters/demo/markdown.mdx CHANGED
@@ -6,7 +6,7 @@ import Wide from '../../../components/Wide.astro';
6
  import Note from '../../../components/Note.astro';
7
  import FullWidth from '../../../components/FullWidth.astro';
8
  import Accordion from '../../../components/Accordion.astro';
9
- import Figure from '../../../components/Figure.astro';
10
 
11
  ## Markdown
12
 
@@ -284,6 +284,7 @@ The **citation keys** come from `app/src/content/bibliography.bib`.
284
 
285
  In research articles, you may have to make references to anything. They are basically html anchors. They can be used internally in the article or externally in other articles.
286
 
 
287
  1. **Title**<br/>
288
  Each title is automatically generated with a slugged version from the citation key. ( slugged title from the citation key )
289
  like for example, the id `#mermaid-diagrams` is generated from the `Mermaid diagrams` title.
@@ -293,6 +294,10 @@ In research articles, you may have to make references to anything. They are basi
293
  You can make a link to an image or a chart by adding an ID on it.<br/>`<HtmlEmbed id="neural-network-mnist-like"/>` then you can link to it with a link like `<a href="#neural-network-mnist-like">Fig 1</a>`.
294
  <br/><br/>**Example** [Chart 1](#neural-network-mnist-like) or [Fig 1](#placeholder-image)
295
 
 
 
 
 
296
  <Accordion title="Code example">
297
  ```mdx
298
  #### Mermaid diagrams
@@ -301,7 +306,7 @@ In research articles, you may have to make references to anything. They are basi
301
  <HtmlEmbed id="neural-network-mnist-like"/>
302
  [Chart 1](#neural-network-mnist-like)
303
 
304
- <Figure id="placeholder-image" src="..."/>
305
  [Fig 1](#placeholder-image)
306
  ```
307
  </Accordion>
@@ -400,19 +405,23 @@ Next section begins here.
400
 
401
  ### Table
402
 
403
- Use pipe tables like `| Column |` with header separator `| --- |`.
404
 
405
- | Method | Score |
406
- |---|---|
407
- | A | 0.78 |
408
- | B | 0.86 |
 
 
409
 
410
  <Accordion title="Code example">
411
  ```mdx
412
- | Method | Score |
413
- | --- | --- |
414
- | A | 0.78 |
415
- | B | 0.86 |
 
 
416
  ```
417
  </Accordion>
418
 
 
6
  import Note from '../../../components/Note.astro';
7
  import FullWidth from '../../../components/FullWidth.astro';
8
  import Accordion from '../../../components/Accordion.astro';
9
+ import Image from '../../../components/Image.astro';
10
 
11
  ## Markdown
12
 
 
284
 
285
  In research articles, you may have to make references to anything. They are basically html anchors. They can be used internally in the article or externally in other articles.
286
 
287
+
288
  1. **Title**<br/>
289
  Each title is automatically generated with a slugged version from the citation key. ( slugged title from the citation key )
290
  like for example, the id `#mermaid-diagrams` is generated from the `Mermaid diagrams` title.
 
294
  You can make a link to an image or a chart by adding an ID on it.<br/>`<HtmlEmbed id="neural-network-mnist-like"/>` then you can link to it with a link like `<a href="#neural-network-mnist-like">Fig 1</a>`.
295
  <br/><br/>**Example** [Chart 1](#neural-network-mnist-like) or [Fig 1](#placeholder-image)
296
 
297
+ <Note emoji="πŸ’‘" variant="info">
298
+ **Available with:** `Reference`, `Image`, and `HtmlEmbed` components all support the `id` prop for creating referenceable anchors.
299
+ </Note>
300
+
301
  <Accordion title="Code example">
302
  ```mdx
303
  #### Mermaid diagrams
 
306
  <HtmlEmbed id="neural-network-mnist-like"/>
307
  [Chart 1](#neural-network-mnist-like)
308
 
309
+ <Image id="placeholder-image" src="..."/>
310
  [Fig 1](#placeholder-image)
311
  ```
312
  </Accordion>
 
405
 
406
  ### Table
407
 
408
+ Use pipe tables like `| Column |` with header separator `| --- |`. You can control alignment with `:---` (left), `:---:` (center), and `---:` (right).
409
 
410
+ | Model | Accuracy | F1-Score | Training Time | Status |
411
+ |:---|:---:|:---:|---:|:---:|
412
+ | **BERT-base** | 0.89 | 0.89 | 2.5h | βœ… |
413
+ | **RoBERTa-large** | 0.92 | 0.92 | 4.2h | βœ… |
414
+ | **DeBERTa-v3** | 0.94 | 0.94 | 5.8h | βœ… |
415
+ | **GPT-3.5-turbo** | 0.91 | 0.91 | 0.1h | βœ… |
416
 
417
  <Accordion title="Code example">
418
  ```mdx
419
+ | Model | Accuracy | F1-Score | Training Time | Status |
420
+ |:---|:---:|:---:|---:|:---:|
421
+ | **BERT-base** | 0.89 | 0.89 | 2.5h | βœ… |
422
+ | **RoBERTa-large** | 0.92 | 0.92 | 4.2h | βœ… |
423
+ | **DeBERTa-v3** | 0.94 | 0.94 | 5.8h | βœ… |
424
+ | **GPT-3.5-turbo** | 0.91 | 0.91 | 0.1h | βœ… |
425
  ```
426
  </Accordion>
427
 
app/src/content/chapters/demo/writing-your-content.mdx CHANGED
@@ -1,5 +1,5 @@
1
  {/* IMPORTS */}
2
- import { Image } from 'astro:assets';
3
  import placeholder from '../../assets/image/placeholder.png';
4
  import Sidenote from '../../../components/Sidenote.astro';
5
  import Wide from '../../../components/Wide.astro';
@@ -87,7 +87,7 @@ Your story. Write your content here.
87
  <small className="muted">**Content** in app/src/content/article.mdx</small>
88
  ```mdx
89
  import placeholder from '../../assets/image/placeholder.png'
90
- import Figure from '../../../components/Figure.astro'
91
  import Sidenote from '../../../components/Sidenote.astro'
92
 
93
  This paragraph is written in Markdown.
@@ -95,7 +95,7 @@ This paragraph is written in Markdown.
95
  <Sidenote>
96
  A short callout inserted via a component.
97
  </Sidenote>
98
- <Figure src={placeholder} alt="Sample image with optimization" />
99
 
100
  This paragraph is also written in Markdown.
101
  ```
 
1
  {/* IMPORTS */}
2
+ import { Image as AstroImage } from 'astro:assets';
3
  import placeholder from '../../assets/image/placeholder.png';
4
  import Sidenote from '../../../components/Sidenote.astro';
5
  import Wide from '../../../components/Wide.astro';
 
87
  <small className="muted">**Content** in app/src/content/article.mdx</small>
88
  ```mdx
89
  import placeholder from '../../assets/image/placeholder.png'
90
+ import Image from '../../../components/Image.astro'
91
  import Sidenote from '../../../components/Sidenote.astro'
92
 
93
  This paragraph is written in Markdown.
 
95
  <Sidenote>
96
  A short callout inserted via a component.
97
  </Sidenote>
98
+ <Image src={placeholder} alt="Sample image with optimization" />
99
 
100
  This paragraph is also written in Markdown.
101
  ```
app/src/styles/components/_table.css CHANGED
@@ -8,7 +8,6 @@
8
  .content-grid main td {
9
  border-bottom: 1px solid var(--border-color);
10
  padding: 6px 8px;
11
- text-align: left;
12
  font-size: 15px;
13
  white-space: nowrap;
14
  /* prevent squashing; allow horizontal scroll instead */
@@ -17,11 +16,6 @@
17
  vertical-align: top;
18
  }
19
 
20
- .content-grid main th:last-child,
21
- .content-grid main td:last-child {
22
- text-align: right;
23
- }
24
-
25
  .content-grid main thead th {
26
  border-bottom: 1px solid var(--border-color);
27
  }
 
8
  .content-grid main td {
9
  border-bottom: 1px solid var(--border-color);
10
  padding: 6px 8px;
 
11
  font-size: 15px;
12
  white-space: nowrap;
13
  /* prevent squashing; allow horizontal scroll instead */
 
16
  vertical-align: top;
17
  }
18
 
 
 
 
 
 
19
  .content-grid main thead th {
20
  border-bottom: 1px solid var(--border-color);
21
  }