photosuite 0.4.0 → 0.5.0-beta

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
@@ -1,356 +1,317 @@
1
- <div align="center">
2
- <a href="/">
3
- <img src="/public/logo.svg" alt="Photosuite" width="120" />
4
- <br/>
5
- <h1>Photosuite</h1>
6
- </a>
7
-
8
- <p>
9
- <a href="https://photosuite.lhasa.icu">Official Website</a> •
10
- <a href="https://github.com/achuanya/photosuite/releases">Latest Release</a> •
11
- <a href="https://github.com/achuanya/photosuite/blob/main/Changelog.md">Changelog</a> •
12
- <a href="./README.zh-CN.md">简体中文</a>
13
- </p>
14
- </div>
15
-
16
- Photosuite is a simple yet feature-rich image integration tailored for independent blogs. It modularly integrates lightbox, EXIF data, path resolution, image grid, and more into a single, zero-config package. Out of the box, no tedious configuration required—give your blog images a fresh look with just one line of code!
17
-
18
- ## Features
19
-
20
- * **Lightbox**: Customized Fancybox integration, minimalist and practical.
21
- * **Static EXIF**: Integrated `exiftool-vendored.js` supporting custom EXIF parameters.
22
- * **Path Resolution**: Just insert the filename, and the path is auto-resolved at build time.
23
- * **Captions**: Automatically displays image `alt` attributes as captions.
24
- * **Image Grid**: Automatically groups consecutive images (2-3) into a grid layout, each independently clickable.
25
- * **Extreme Performance**: All features are purely static, processed at build time, runtime dependency-free, modular, and loaded on demand.
26
- * **Zero-Config**: Default settings satisfy most needs, with rich options for deep customization.
27
-
28
- ## Installation
29
-
30
- ```bash
31
- pnpm add photosuite
32
- # or
33
- npm install photosuite
34
- # or
35
- yarn add photosuite
36
- ```
37
-
38
- ## Quick Start
39
-
40
- Integrating Photosuite with Astro is very simple, just add the following configuration to `astro.config.js`:
41
-
42
- ```javascript
43
- import { defineConfig } from 'astro/config';
44
- import photosuite from 'photosuite';
45
- import "photosuite/dist/photosuite.css";
46
-
47
- export default defineConfig({
48
- integrations: [
49
- photosuite({
50
- // [Required] Specify the CSS selector for the scope
51
- // Recommended: Your content container to avoid affecting other parts of the site. Supports multiple selectors separated by commas.
52
- scope: '#main',
53
- })
54
- ]
55
- });
56
- ```
57
-
58
- Once configured, Photosuite will automatically process all images within your specified scope.
59
-
60
- ## Features & Configuration
61
-
62
- ### 1. Path Resolution
63
-
64
- Managing image paths in blog posts can be tedious. Photosuite offers flexible resolution strategies that you can configure according to your needs.
65
-
66
- **Scenario A: All images in a single domain/directory**
67
-
68
- ```javascript
69
- photosuite({
70
- scope: '#main',
71
- imageBase: 'https://cdn.example.com/images/',
72
- })
73
- ```
74
-
75
- **Markdown Usage:**
76
- ```markdown
77
- ![My Photo](photo.jpg)
78
- <!-- Resolves to: https://cdn.example.com/images/photo.jpg -->
79
- ```
80
-
81
- **Scenario B: Separate image directory per post (Default)**
82
-
83
- You can specify the directory name in the Frontmatter:
84
-
85
- ```yaml
86
- ---
87
- title: My First GitHub PR
88
- imageDir: "2025-11-26-my-first-github-pr"
89
- ---
90
-
91
- ![My Photo](photo.jpg)
92
- <!-- Resolves to: https://cdn.example.com/images/2025-11-26-my-first-github-pr/photo.jpg -->
93
- ```
94
-
95
- **Scenario C: Use filename as directory**
96
-
97
- ```javascript
98
- photosuite({
99
- scope: '#main',
100
- imageBase: 'https://cdn.example.com/',
101
- fileDir: true, // Enable this option
102
- })
103
- ```
104
-
105
- If your post filename is `2025-11-26-my-first-github-pr.md`, the image path automatically resolves to:
106
-
107
- `https://cdn.example.com/images/2025-11-26-my-first-github-pr/photo.jpg`
108
-
109
- ### 2. EXIF Data Display
110
-
111
- Photosuite uses `exiftool-vendored.js` to extract information at build time.
112
-
113
- **Default Configuration:**
114
- Default display: Camera Model, Lens Model, Focal Length, Aperture, Shutter Speed, ISO, Date Original.
115
-
116
- > NIKON Z 30 · NIKKOR Z DX 16-50mm f/3.5-6.3 VR · 20.5 mm · ƒ/3.8 · 1/15 · ISO 1000 · 2025/12/9
117
-
118
- **Custom Configuration:**
119
-
120
- ```javascript
121
- photosuite({
122
- // ...
123
- exif: {
124
- enabled: true,
125
- // Custom fields: Focal Length, Aperture, Shutter Speed, ISO
126
- fields: ['FocalLength', 'FNumber', 'ExposureTime', 'ISO'],
127
- // Custom separator
128
- separator: ' · '
129
- }
130
- })
131
- ```
132
-
133
- **Per-Page Filtering:**
134
-
135
- `scope` is a CSS selector that only governs *client-side* behavior (lightbox, captions, grid). The EXIF rehype plugin runs at build time on **every** Markdown file's `<img>` tags and rewrites their DOM into `.photosuite-item` + `.photosuite-exif`. If you have non-article pages (e.g. `about.md`) outside the `scope` container, you'll still see the injected EXIF markup in the HTML.
136
-
137
- To restrict EXIF injection to specific pages, use either of:
138
-
139
- **Option 1 Glob patterns in config**:
140
-
141
- ```javascript
142
- photosuite({
143
- scope: '#article',
144
- exif: {
145
- // Only process matched files; omit to process all
146
- include: ['src/content/posts/**/*.md'],
147
- // Skip matched files; takes precedence over include
148
- exclude: ['src/content/pages/**/*.md'],
149
- },
150
- })
151
- ```
152
-
153
- Patterns are matched against paths relative to the project root, normalized with `/` separators. Supported wildcards: `*` (within a segment), `**` (across segments), `?` (single character).
154
-
155
- **Option 2 Frontmatter opt-out**:
156
-
157
- ```yaml
158
- ---
159
- title: About
160
- exif: false # or: photosuite: false
161
- ---
162
- ```
163
-
164
- Pages with `exif: false`, `photosuite: false`, or `photosuite.exif: false` in frontmatter are skipped regardless of `include`/`exclude`.
165
-
166
- ### 3. Image Grid
167
-
168
- Photosuite supports automatically combining consecutive images into a grid layout. When 2-3 images are placed adjacently in Markdown, they will be automatically combined into a grid, and each image remains independently clickable.
169
-
170
- **Markdown Usage:**
171
-
172
- Two-image grid:
173
- ```markdown
174
- ![Image 1](photo1.jpg)
175
- ![Image 2](photo2.jpg)
176
- ```
177
-
178
- Three-image grid:
179
- ```markdown
180
- ![Image 1](photo1.jpg)
181
- ![Image 2](photo2.jpg)
182
- ![Image 3](photo3.jpg)
183
- ```
184
-
185
- **Features:**
186
- - Automatically detects consecutive images (2-3 images)
187
- - Each image has consistent width, evenly dividing the container
188
- - Each image is independently clickable with lightbox support
189
- - Interactive experience: Image zooms in slightly on hover
190
- - Responsive design: automatically switches to single-column layout on mobile devices
191
-
192
- **Configuration:**
193
- ```javascript
194
- photosuite({
195
- // ...
196
- // Disable image grid
197
- imageGrid: false,
198
- })
199
- ```
200
-
201
- ### 4. Lightbox & Captions
202
-
203
- Fancybox has been customized to differ slightly from the official version.
204
-
205
- Supports native configuration, refer to: [Fancybox](https://fancyapps.com/fancybox/)
206
-
207
- ```javascript
208
- photosuite({
209
- // ...
210
- // Disable lightbox
211
- fancybox: false,
212
-
213
- // Disable captions
214
- imageAlts: false,
215
-
216
- // Fancybox native options
217
- fancyboxOptions: {
218
- Carousel: {
219
- infinite: false,
220
- Toolbar: {
221
- display: {
222
- left: ["infobar"],
223
- middle: [],
224
- right: ["slideshow", "download", "thumbs", "close"],
225
- },
226
- },
227
- },
228
- }
229
- })
230
- ```
231
-
232
- ## Complete Configuration Reference
233
-
234
- ### Parameter List
235
-
236
- | Parameter | Type | Required | Default | Description |
237
- | :--- | :--- | :---: | :--- | :--- |
238
- | `scope` | `string` | ✅ | - | **Scope**. CSS selector, only processes images within this container. Supports multiple selectors separated by commas. |
239
- | `selector` | `string` | ❌ | `"a[data-fancybox]"` | **Image Selector**. Specifies which images need lightbox effect. |
240
- | `imageBase` | `string` | ❌ | - | **Base Image URL**. Prefix used for splicing relative paths. |
241
- | `imageDir` | `string` | ❌ | `"imageDir"` | **Directory Field Name**. Field name in Markdown Frontmatter to specify image subdirectory. |
242
- | `fileDir` | `boolean` | ❌ | `false` | **Filename Archiving**. Whether to automatically use Markdown filename as image subdirectory. |
243
- | `fancybox` | `boolean` | ❌ | `true` | **Enable Lightbox**. Whether to load Fancybox module. |
244
- | `imageAlts` | `boolean` | ❌ | `true` | **Enable Captions**. Whether to display `alt` attribute as image caption. |
245
- | `imageGrid` | `boolean` | ❌ | `true` | **Enable Image Grid**. Whether to combine consecutive images (2-3) into a grid layout. |
246
- | `exif` | `boolean` \| `object` | ❌ | `true` | **Enable EXIF**. `false` to disable, `true` for default config, or pass object to customize via fields:[]. |
247
- | `fancyboxOptions` | `object` | ❌ | - | **Native Lightbox Config**. Configuration items passed through to Fancybox. |
248
-
249
- ### Full Configuration Code Example
250
-
251
- ```javascript
252
- import photosuite from 'photosuite';
253
- import "photosuite/dist/photosuite.css";
254
-
255
- photosuite({
256
- // ----------------
257
- // Required
258
- // ----------------
259
- scope: '#main', // Your content container class name
260
-
261
- // ----------------
262
- // Optional (Values below are defaults)
263
- // ----------------
264
-
265
- // Basic Settings
266
- selector: 'a[data-fancybox]',
267
-
268
- // Path Resolution
269
- imageBase: '',
270
- imageDir: 'imageDir',
271
- fileDir: false,
272
-
273
- // Feature Toggles
274
- fancybox: true,
275
- imageAlts: true,
276
- imageGrid: true,
277
-
278
- // EXIF Detailed Configuration
279
- exif: {
280
- enabled: true,
281
- fields: [
282
- 'Model', // Camera Model
283
- 'LensModel', // Lens Model
284
- 'FocalLength', // Focal Length
285
- 'FNumber', // Aperture
286
- 'ExposureTime', // Shutter Speed
287
- 'ISO', // ISO
288
- 'DateTimeOriginal' // Date Original
289
- ],
290
- separator: ' · ', // Separator
291
- // Per-page filtering (since v0.3.1)
292
- include: undefined, // string[] of glob patterns; omit to process all pages
293
- exclude: undefined, // string[] of glob patterns; takes precedence over include
294
- },
295
-
296
- // Fancybox native options
297
- fancyboxOptions: {
298
- wheel: "slide", // Enable wheel navigation
299
- Hash: false, // Disable URL hash
300
- Html: { // HTML content configuration
301
- video: { // Video configuration
302
- autoplay: false, // Disable video autoplay
303
- },
304
- },
305
- Carousel: { // Carousel configuration
306
- Thumbs: false, // Disable thumbnails
307
- infinite: false, // Disable infinite loop
308
- Toolbar: { // Toolbar configuration
309
- display: { // Display items configuration
310
- left: ["counter"], // Left side: page counter
311
- right: ["autoplay", "close"], // Right side: autoplay and close buttons
312
- },
313
- },
314
- },
315
- }
316
- })
317
- ```
318
-
319
- ## FAQ
320
-
321
- **Q: My non-article pages (e.g. about page) still show EXIF info even though they're outside the `scope` container.**
322
- A: `scope` only controls *client-side* behavior. The EXIF rehype plugin runs at build time on every Markdown file. Restrict it via `exif.include` / `exif.exclude` glob patterns, or add `exif: false` to a page's frontmatter. See [EXIF Data Display § Per-Page Filtering](#2-exif-data-display).
323
-
324
- **Q: Why isn't EXIF data showing?**
325
- A: Please check the following:
326
- 1. Does the image contain EXIF data? (Some compression tools strip EXIF)
327
- 2. EXIF data is only displayed when at least the exposure triangle (Focal Length, Aperture, Shutter Speed) is present.
328
-
329
- **Q: I only want to use Photosuite on certain images, what should I do?**
330
- A: You can precisely control the scope via CSS selectors (comma-separated for multiple selectors). For example, only take effect inside elements with ID `#main`:
331
-
332
- ```javascript
333
- photosuite({
334
- scope: '#main',
335
- // ... other configurations
336
- })
337
- ```
338
-
339
- ## Contributors
340
-
341
- One line of code, one plugin, for independent blogs, it is insignificant, like dust.
342
-
343
- But we insist on taking root in this soil, letting thought be free, and letting the soul rest!
344
-
345
- [![](https://contrib.rocks/image?repo=achuanya/photosuite)](https://github.com/achuanya/photosuite/graphs/contributors)
346
-
347
- ## Users
348
-
349
- - [Frevia](https://www.frevia.site)
350
- - [ZhiJun's Blog](https://blog.zhijun.io)
351
-
352
- If you are using using Photosuite, please edit this file to add your blog.
353
-
354
- ## License
355
-
1
+ <div align="center">
2
+ <a href="/">
3
+ <img src="/public/logo.svg" alt="Photosuite" width="120" />
4
+ <br/>
5
+ <h1>Photosuite</h1>
6
+ </a>
7
+
8
+ <p>
9
+ <a href="https://photosuite.lhasa.icu">Official Website</a> •
10
+ <a href="https://github.com/achuanya/photosuite/releases">Latest Release</a> •
11
+ <a href="https://github.com/achuanya/photosuite/blob/main/Changelog.md">Changelog</a> •
12
+ <a href="./README.zh-CN.md">简体中文</a>
13
+ </p>
14
+ </div>
15
+
16
+ Photosuite is a simple yet feature-rich image integration tailored for independent blogs. It modularly integrates lightbox, EXIF data, path resolution, image grid, and more into a single, zero-config package. Out of the box, no tedious configuration required—give your blog images a fresh look with just one line of code!
17
+
18
+ ## Features
19
+
20
+ * **Lightbox**: Customized Fancybox integration, minimalist and practical.
21
+ * **Static EXIF**: Integrated `exiftool-vendored.js` supporting custom EXIF parameters.
22
+ * **Path Resolution**: Just insert the filename, and the path is auto-resolved at build time.
23
+ * **Captions**: Automatically displays image `alt` attributes as captions.
24
+ * **Image Grid**: Automatically groups consecutive images (2-3) into a grid layout, each independently clickable.
25
+ * **Extreme Performance**: All features are purely static, processed at build time, runtime dependency-free, modular, and loaded on demand.
26
+ * **Zero-Config**: Default settings satisfy most needs, with rich options for deep customization.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pnpm add photosuite
32
+ # or
33
+ npm install photosuite
34
+ # or
35
+ yarn add photosuite
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ Integrating Photosuite with Astro is very simple, just add the following configuration to `astro.config.js`:
41
+
42
+ ```javascript
43
+ import { defineConfig } from 'astro/config';
44
+ import photosuite from 'photosuite';
45
+ import "photosuite/dist/photosuite.css";
46
+
47
+ export default defineConfig({
48
+ integrations: [
49
+ photosuite({
50
+ // [Required] Specify the CSS selector for the scope
51
+ // Recommended: Your content container to avoid affecting other parts of the site. Supports multiple selectors separated by commas.
52
+ scope: '#main',
53
+ })
54
+ ]
55
+ });
56
+ ```
57
+
58
+ Once configured, Photosuite will automatically process all images within your specified scope.
59
+
60
+ ## Features & Configuration
61
+
62
+ ### 1. Path Resolution
63
+
64
+ Managing image paths in blog posts can be tedious. Photosuite offers flexible resolution strategies that you can configure according to your needs.
65
+
66
+ **Scenario A: All images in a single domain/directory**
67
+
68
+ ```javascript
69
+ photosuite({
70
+ scope: '#main',
71
+ imageBase: 'https://cdn.example.com/images/',
72
+ })
73
+ ```
74
+
75
+ **Markdown Usage:**
76
+ ```markdown
77
+ ![My Photo](photo.jpg)
78
+ <!-- Resolves to: https://cdn.example.com/images/photo.jpg -->
79
+ ```
80
+
81
+ **Scenario B: Separate image directory per post (Default)**
82
+
83
+ You can specify the directory name in the Frontmatter:
84
+
85
+ ```yaml
86
+ ---
87
+ title: My First GitHub PR
88
+ imageDir: "2025-11-26-my-first-github-pr"
89
+ ---
90
+
91
+ ![My Photo](photo.jpg)
92
+ <!-- Resolves to: https://cdn.example.com/images/2025-11-26-my-first-github-pr/photo.jpg -->
93
+ ```
94
+
95
+ **Scenario C: Use filename as directory**
96
+
97
+ ```javascript
98
+ photosuite({
99
+ scope: '#main',
100
+ imageBase: 'https://cdn.example.com/',
101
+ fileDir: true, // Enable this option
102
+ })
103
+ ```
104
+
105
+ If your post filename is `2025-11-26-my-first-github-pr.md`, the image path automatically resolves to:
106
+
107
+ `https://cdn.example.com/images/2025-11-26-my-first-github-pr/photo.jpg`
108
+
109
+ ### 2. EXIF Data Display
110
+
111
+ Photosuite uses `exiftool-vendored.js` to extract information at build time.
112
+
113
+ **Default Configuration:**
114
+ Default display: Camera Model, Lens Model, Focal Length, Aperture, Shutter Speed, ISO, Date Original.
115
+
116
+ > NIKON Z 30 · NIKKOR Z DX 16-50mm f/3.5-6.3 VR · 20.5 mm · ƒ/3.8 · 1/15 · ISO 1000 · 2025/12/9
117
+
118
+ **Custom Configuration:**
119
+
120
+ ```javascript
121
+ photosuite({
122
+ // ...
123
+ exif: {
124
+ enabled: true,
125
+ // Custom fields: Focal Length, Aperture, Shutter Speed, ISO
126
+ fields: ['FocalLength', 'FNumber', 'ExposureTime', 'ISO'],
127
+ // Custom separator
128
+ separator: ' · '
129
+ }
130
+ })
131
+ ```
132
+
133
+ ### 3. Image Grid
134
+
135
+ Photosuite supports automatically combining consecutive images into a grid layout. When 2-3 images are placed adjacently in Markdown, they will be automatically combined into a grid, and each image remains independently clickable.
136
+
137
+ **Markdown Usage:**
138
+
139
+ Two-image grid:
140
+ ```markdown
141
+ ![Image 1](photo1.jpg)
142
+ ![Image 2](photo2.jpg)
143
+ ```
144
+
145
+ Three-image grid:
146
+ ```markdown
147
+ ![Image 1](photo1.jpg)
148
+ ![Image 2](photo2.jpg)
149
+ ![Image 3](photo3.jpg)
150
+ ```
151
+
152
+ **Features:**
153
+ - Automatically detects consecutive images (2-3 images)
154
+ - Each image has consistent width, evenly dividing the container
155
+ - Each image is independently clickable with lightbox support
156
+ - Interactive experience: Image zooms in slightly on hover
157
+ - Responsive design: automatically switches to single-column layout on mobile devices
158
+
159
+ **Configuration:**
160
+ ```javascript
161
+ photosuite({
162
+ // ...
163
+ // Disable image grid
164
+ imageGrid: false,
165
+ })
166
+ ```
167
+
168
+ ### 4. Lightbox & Captions
169
+
170
+ Fancybox has been customized to differ slightly from the official version.
171
+
172
+ Supports native configuration, refer to: [Fancybox](https://fancyapps.com/fancybox/)
173
+
174
+ ```javascript
175
+ photosuite({
176
+ // ...
177
+ // Disable lightbox
178
+ fancybox: false,
179
+
180
+ // Disable captions
181
+ imageAlts: false,
182
+
183
+ // Fancybox native options
184
+ fancyboxOptions: {
185
+ Carousel: {
186
+ infinite: false,
187
+ Toolbar: {
188
+ display: {
189
+ left: ["infobar"],
190
+ middle: [],
191
+ right: ["slideshow", "download", "thumbs", "close"],
192
+ },
193
+ },
194
+ },
195
+ }
196
+ })
197
+ ```
198
+
199
+ ## Complete Configuration Reference
200
+
201
+ ### Parameter List
202
+
203
+ | Parameter | Type | Required | Default | Description |
204
+ | :--- | :--- | :---: | :--- | :--- |
205
+ | `scope` | `string` | ✅ | - | **Scope**. CSS selector, only processes images within this container. Supports multiple selectors separated by commas. |
206
+ | `selector` | `string` | ❌ | `"a[data-fancybox]"` | **Image Selector**. Specifies which images need lightbox effect. |
207
+ | `imageBase` | `string` | ❌ | - | **Base Image URL**. Prefix used for splicing relative paths. |
208
+ | `imageDir` | `string` | ❌ | `"imageDir"` | **Directory Field Name**. Field name in Markdown Frontmatter to specify image subdirectory. |
209
+ | `fileDir` | `boolean` | ❌ | `false` | **Filename Archiving**. Whether to automatically use Markdown filename as image subdirectory. |
210
+ | `fancybox` | `boolean` | ❌ | `true` | **Enable Lightbox**. Whether to load Fancybox module. |
211
+ | `imageAlts` | `boolean` | ❌ | `true` | **Enable Captions**. Whether to display `alt` attribute as image caption. |
212
+ | `imageGrid` | `boolean` | ❌ | `true` | **Enable Image Grid**. Whether to combine consecutive images (2-3) into a grid layout. |
213
+ | `exif` | `boolean` \| `object` | ❌ | `true` | **Enable EXIF**. `false` to disable, `true` for default config, or pass object to customize via fields:[]. |
214
+ | `fancyboxOptions` | `object` | ❌ | - | **Native Lightbox Config**. Configuration items passed through to Fancybox. |
215
+
216
+ ### Full Configuration Code Example
217
+
218
+ ```javascript
219
+ import photosuite from 'photosuite';
220
+ import "photosuite/dist/photosuite.css";
221
+
222
+ photosuite({
223
+ // ----------------
224
+ // Required
225
+ // ----------------
226
+ scope: '#main', // Your content container class name
227
+
228
+ // ----------------
229
+ // Optional (Values below are defaults)
230
+ // ----------------
231
+
232
+ // Basic Settings
233
+ selector: 'a[data-fancybox]',
234
+
235
+ // Path Resolution
236
+ imageBase: '',
237
+ imageDir: 'imageDir',
238
+ fileDir: false,
239
+
240
+ // Feature Toggles
241
+ fancybox: true,
242
+ imageAlts: true,
243
+ imageGrid: true,
244
+
245
+ // EXIF Detailed Configuration
246
+ exif: {
247
+ enabled: true,
248
+ fields: [
249
+ 'Model', // Camera Model
250
+ 'LensModel', // Lens Model
251
+ 'FocalLength', // Focal Length
252
+ 'FNumber', // Aperture
253
+ 'ExposureTime', // Shutter Speed
254
+ 'ISO', // ISO
255
+ 'DateTimeOriginal' // Date Original
256
+ ],
257
+ separator: ' · ' // Separator
258
+ },
259
+
260
+ // Fancybox native options
261
+ fancyboxOptions: {
262
+ wheel: "slide", // Enable wheel navigation
263
+ Hash: false, // Disable URL hash
264
+ Html: { // HTML content configuration
265
+ video: { // Video configuration
266
+ autoplay: false, // Disable video autoplay
267
+ },
268
+ },
269
+ Carousel: { // Carousel configuration
270
+ Thumbs: false, // Disable thumbnails
271
+ infinite: false, // Disable infinite loop
272
+ Toolbar: { // Toolbar configuration
273
+ display: { // Display items configuration
274
+ left: ["counter"], // Left side: page counter
275
+ right: ["autoplay", "close"], // Right side: autoplay and close buttons
276
+ },
277
+ },
278
+ },
279
+ }
280
+ })
281
+ ```
282
+
283
+ ## FAQ
284
+
285
+ **Q: Why isn't EXIF data showing?**
286
+ A: Please check the following:
287
+ 1. Does the image contain EXIF data? (Some compression tools strip EXIF)
288
+ 2. EXIF data is only displayed when at least the exposure triangle (Focal Length, Aperture, Shutter Speed) is present.
289
+
290
+ **Q: I only want to use Photosuite on certain images, what should I do?**
291
+ A: You can precisely control the scope via CSS selectors (comma-separated for multiple selectors). For example, only take effect inside elements with ID `#main`:
292
+
293
+ ```javascript
294
+ photosuite({
295
+ scope: '#main',
296
+ // ... other configurations
297
+ })
298
+ ```
299
+
300
+ ## Contributors
301
+
302
+ One line of code, one plugin, for independent blogs, it is insignificant, like dust.
303
+
304
+ But we insist on taking root in this soil, letting thought be free, and letting the soul rest!
305
+
306
+ [![](https://contrib.rocks/image?repo=achuanya/photosuite)](https://github.com/achuanya/photosuite/graphs/contributors)
307
+
308
+ ## Users
309
+
310
+ - [Frevia](https://www.frevia.site)
311
+ - [ZhiJun's Blog](https://blog.zhijun.io)
312
+
313
+ If you are using using Photosuite, please edit this file to add your blog.
314
+
315
+ ## License
316
+
356
317
  [GPL-3.0](./LICENSE)