Skip to content

Commit c4f7728

Browse files
committed
Add resize-image plugin
1 parent 77e3087 commit c4f7728

File tree

5 files changed

+79
-15
lines changed

5 files changed

+79
-15
lines changed

docs/platforms/apple/common/user-feedback/index.mdx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ The User Feedback feature allows you to collect user feedback from anywhere insi
1919

2020
The User Feedback widget allows users to submit feedback from anywhere inside your application.
2121

22-
import widget from './img/user-feedback-apple-widget.png'
23-
24-
<img src={widget} width={300} alt="User Feedback Widget" />
22+
![An example of the User Feedback Widget on iOS =300x](./img/user-feedback-apple-widget.png)
2523

2624
### Pre-requisites
2725

src/components/docImage/index.tsx

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,32 @@ export default function DocImage({
9999
imgPath = finalSrc;
100100
}
101101

102-
// Parse dimensions from URL hash (works for both internal and external)
103-
const hashDimensions = parseDimensionsFromHash(src);
104-
105-
// Use hash dimensions first, fallback to props
106-
const width = hashDimensions[0] > 0 ? hashDimensions[0] : parseDimension(propsWidth);
107-
const height = hashDimensions[1] > 0 ? hashDimensions[1] : parseDimension(propsHeight);
102+
// Prefer explicit props (coming from MDX attributes) over hash-based dimensions.
103+
// If either width or height prop is provided, treat as manual sizing.
104+
const manualWidth = parseDimension(propsWidth);
105+
const manualHeight = parseDimension(propsHeight);
106+
107+
// If either width or height is specified manually, ignore any hash dimensions entirely
108+
const isManual = manualWidth != null || manualHeight != null;
109+
const hashDimensions = isManual ? [] : parseDimensionsFromHash(src);
110+
const width = isManual
111+
? manualWidth
112+
: hashDimensions[0] > 0
113+
? hashDimensions[0]
114+
: undefined;
115+
const height = isManual
116+
? manualHeight
117+
: hashDimensions[1] > 0
118+
? hashDimensions[1]
119+
: undefined;
108120

109121
return (
110122
<ImageLightbox
111123
src={finalSrc}
112124
imgPath={imgPath}
113125
width={width}
114126
height={height}
127+
isManualDimensions={isManual}
115128
alt={props.alt ?? ''}
116129
{...props}
117130
/>

src/components/imageLightbox/index.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ interface ImageLightboxProps
1515
imgPath: string;
1616
src: string;
1717
height?: number;
18+
isManualDimensions?: boolean;
1819
width?: number;
1920
}
2021

@@ -54,6 +55,7 @@ export function ImageLightbox({
5455
width,
5556
height,
5657
imgPath,
58+
isManualDimensions = false,
5759
style,
5860
className,
5961
...props
@@ -97,8 +99,18 @@ export function ImageLightbox({
9799
const imageClassName = isInline
98100
? className
99101
: 'max-h-[90vh] max-w-[90vw] object-contain';
102+
103+
// Apply sizing:
104+
// - If manual: set only provided dimension(s); missing one becomes 'auto'
105+
// - Else: default responsive
100106
const imageStyle = isInline
101-
? {width: '100%', height: 'auto', ...style}
107+
? isManualDimensions
108+
? {
109+
width: width != null ? `${width}px` : 'auto',
110+
height: height != null ? `${height}px` : 'auto',
111+
...style,
112+
}
113+
: {width: '100%', height: 'auto', ...style}
102114
: {width: 'auto', height: 'auto'};
103115

104116
if (shouldUseNextImage && dimensions) {

src/mdx.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import remarkCodeTitles from './remark-code-title';
3535
import remarkComponentSpacing from './remark-component-spacing';
3636
import remarkExtractFrontmatter from './remark-extract-frontmatter';
3737
import remarkFormatCodeBlocks from './remark-format-code';
38+
import remarkImageResize from './remark-image-resize';
3839
import remarkImageSize from './remark-image-size';
3940
import remarkTocHeadings, {TocNode} from './remark-toc-headings';
4041
import remarkVariables from './remark-variables';
@@ -583,6 +584,7 @@ export async function getFileBySlug(slug: string): Promise<SlugFile> {
583584
remarkFormatCodeBlocks,
584585
[remarkImageSize, {sourceFolder: cwd, publicFolder: path.join(root, 'public')}],
585586
remarkMdxImages,
587+
remarkImageResize,
586588
remarkCodeTitles,
587589
remarkCodeTabs,
588590
remarkComponentSpacing,
@@ -655,11 +657,6 @@ export async function getFileBySlug(slug: string): Promise<SlugFile> {
655657
// for this specific slug easily
656658
options.outdir = assetsCacheDir || outdir;
657659

658-
// Ensure file-loader URLs are absolute from the public folder so
659-
// imported image paths do not end up page-relative (which breaks <img src={imported}>).
660-
// With this, imports will resolve like "/mdx-images/<name>-<hash>.<ext>".
661-
options.publicPath = '/mdx-images';
662-
663660
// Set write to true so that esbuild will output the files.
664661
options.write = true;
665662

src/remark-image-resize.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import {visit} from 'unist-util-visit';
2+
3+
const SIZE_FROM_ALT_RE = /\s*=\s*(\d+)?x?(\d+)?\s*$/;
4+
/**
5+
* remark plugin to parse width/height hints from the image ALT text.
6+
*
7+
* This plugin is intended to run AFTER `remark-mdx-images`, so it processes
8+
* mdxJsxTextElement nodes named `img` (i.e., <img /> in MDX).
9+
*
10+
* Supported ALT suffixes (trailing in ALT text):
11+
* ![Alt text =300x200](./image.png)
12+
* ![Alt text =300x](./image.png)
13+
* ![Alt text =x200](./image.png)
14+
* ![Alt text =300](./image.png)
15+
*
16+
* Behavior:
17+
* - Extracts the trailing "=WxH" (width-only/height-only also supported).
18+
* - Cleans the ALT text by removing the size suffix.
19+
* - Adds numeric `width`/`height` attributes to the <img> element.
20+
*/
21+
export default function remarkImageResize() {
22+
return tree =>
23+
visit(tree, {type: 'mdxJsxTextElement', name: 'img'}, node => {
24+
25+
// Handle MDX JSX <img> produced by remark-mdx-images
26+
const altIndex = node.attributes.findIndex(a => a && a.name === 'alt');
27+
const altValue = altIndex !== -1 && typeof node.attributes[altIndex].value === 'string'
28+
? node.attributes[altIndex].value
29+
: null;
30+
if (altValue) {
31+
const m = altValue.match(SIZE_FROM_ALT_RE);
32+
if (m) {
33+
const [, wStr, hStr] = m;
34+
const cleanedAlt = altValue.replace(SIZE_FROM_ALT_RE, '').trim();
35+
// set cleaned alt
36+
node.attributes[altIndex] = {type: 'mdxJsxAttribute', name: 'alt', value: cleanedAlt};
37+
// remove any pre-existing width/height attributes to avoid duplicates
38+
node.attributes = node.attributes.filter(a => !(a && (a.name === 'width' || a.name === 'height')));
39+
if (wStr) node.attributes.push({type: 'mdxJsxAttribute', name: 'width', value: wStr});
40+
if (hStr) node.attributes.push({type: 'mdxJsxAttribute', name: 'height', value: hStr});
41+
}
42+
}
43+
});
44+
}

0 commit comments

Comments
 (0)