react-file-preview-engine 0.1.4 → 0.1.6
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 +72 -19
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -184,7 +184,7 @@ This means you can **override** built-in renderers by providing a custom rendere
|
|
|
184
184
|
|
|
185
185
|
#### Markdown Renderer Example
|
|
186
186
|
|
|
187
|
-
This example adds support for markdown files.
|
|
187
|
+
This example adds support for markdown files.
|
|
188
188
|
|
|
189
189
|
```tsx
|
|
190
190
|
import React, { useEffect, useState } from "react";
|
|
@@ -195,12 +195,12 @@ import rehypeRaw from "rehype-raw";
|
|
|
195
195
|
import { useRemark } from "react-remarkify";
|
|
196
196
|
import rehypeSanitize from "rehype-sanitize";
|
|
197
197
|
|
|
198
|
-
const markdownRenderer: Renderer
|
|
198
|
+
const markdownRenderer: Renderer = {
|
|
199
199
|
name: "markdown",
|
|
200
200
|
canRender({ mimeType }) {
|
|
201
201
|
return mimeType === "text/markdown";
|
|
202
202
|
},
|
|
203
|
-
Component({ src, onLoad, onError
|
|
203
|
+
Component({ src, onLoad, onError }) {
|
|
204
204
|
const [markdown, setMarkdown] = useState("");
|
|
205
205
|
|
|
206
206
|
useEffect(() => {
|
|
@@ -224,7 +224,7 @@ const markdownRenderer: Renderer<{ renderAsHtml?: boolean }> = {
|
|
|
224
224
|
remarkToRehypeOptions: { allowDangerousHtml: true },
|
|
225
225
|
});
|
|
226
226
|
|
|
227
|
-
return
|
|
227
|
+
return <div>{reactContent}</div>;
|
|
228
228
|
},
|
|
229
229
|
};
|
|
230
230
|
|
|
@@ -235,9 +235,62 @@ export default function App() {
|
|
|
235
235
|
|
|
236
236
|
#### Passing Additional Context
|
|
237
237
|
|
|
238
|
+
You can extend renderers with custom configuration using `additionalContext`. This example enhances the markdown renderer to toggle between HTML and raw text rendering.
|
|
239
|
+
|
|
240
|
+
> **Important:** `additionalContext` must remain stable across renders. Use `useMemo` for dynamic values or define it outside your component for static values.
|
|
241
|
+
|
|
238
242
|
```tsx
|
|
243
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
244
|
+
import FilePreviewer from "react-file-preview-engine";
|
|
245
|
+
import type { Renderer } from "react-file-preview-engine/types";
|
|
246
|
+
import remarkGfm from "remark-gfm";
|
|
247
|
+
import rehypeRaw from "rehype-raw";
|
|
248
|
+
import { useRemark } from "react-remarkify";
|
|
249
|
+
import rehypeSanitize from "rehype-sanitize";
|
|
250
|
+
|
|
251
|
+
const markdownRenderer: Renderer<{ renderAsHtml?: boolean }> = {
|
|
252
|
+
name: "markdown",
|
|
253
|
+
canRender({ mimeType }) {
|
|
254
|
+
return mimeType === "text/markdown";
|
|
255
|
+
},
|
|
256
|
+
Component({ src, onLoad, onError, renderAsHtml = true }) {
|
|
257
|
+
const [markdown, setMarkdown] = useState("");
|
|
258
|
+
|
|
259
|
+
useEffect(() => {
|
|
260
|
+
const controller = new AbortController();
|
|
261
|
+
|
|
262
|
+
fetch(src, { signal: controller.signal })
|
|
263
|
+
.then((res) => res.text())
|
|
264
|
+
.then((text) => {
|
|
265
|
+
setMarkdown(text);
|
|
266
|
+
onLoad();
|
|
267
|
+
})
|
|
268
|
+
.catch(onError);
|
|
269
|
+
|
|
270
|
+
return () => controller.abort();
|
|
271
|
+
}, [src]);
|
|
272
|
+
|
|
273
|
+
const reactContent = useRemark({
|
|
274
|
+
markdown,
|
|
275
|
+
remarkPlugins: [remarkGfm],
|
|
276
|
+
rehypePlugins: [rehypeRaw, rehypeSanitize],
|
|
277
|
+
remarkToRehypeOptions: { allowDangerousHtml: true },
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
return renderAsHtml ? <div>{reactContent}</div> : <pre>{markdown}</pre>;
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
|
|
239
284
|
export default function App() {
|
|
240
|
-
|
|
285
|
+
const [renderAsHtml, setRenderAsHtml] = useState(true);
|
|
286
|
+
const additionalContext = useMemo(() => ({ renderAsHtml }), [renderAsHtml]); // Keep stable across renders
|
|
287
|
+
|
|
288
|
+
return (
|
|
289
|
+
<>
|
|
290
|
+
<button onClick={() => setRenderAsHtml(!renderAsHtml)}>Toggle {renderAsHtml ? "Raw" : "HTML"}</button>
|
|
291
|
+
<FilePreviewer src="/README.md" fileName="README.md" customRenderers={[markdownRenderer]} additionalContext={additionalContext} />
|
|
292
|
+
</>
|
|
293
|
+
);
|
|
241
294
|
}
|
|
242
295
|
```
|
|
243
296
|
|
|
@@ -251,20 +304,20 @@ You can explore the actual renderer definitions in the [`defaultRenderers` const
|
|
|
251
304
|
|
|
252
305
|
### FilePreviewer Props
|
|
253
306
|
|
|
254
|
-
| Prop | Type | Required | Default | Description
|
|
255
|
-
| ------------------- | ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
256
|
-
| `src` | [`FileSource`](#filesource) | Yes | – | Source URL of the file to preview
|
|
257
|
-
| `mimeType` | `string` | No | inferred | MIME type of the file
|
|
258
|
-
| `fileName` | `string` | No | - | Used for MIME inference and accessibility
|
|
259
|
-
| `autoPlay` | `boolean` | No | `false` | Auto play audio and video
|
|
260
|
-
| `loader` | `ReactNode` | No | [`<Loader />`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/components.tsx) | Shown while the file is loading
|
|
261
|
-
| `customRenderers` | [`Renderer[]`](#renderer) | No | - | Additional or overriding renderers
|
|
262
|
-
| `additionalContext` | `object` | No | - | Extra data passed to renderers
|
|
263
|
-
| `errorRenderer` | [`Renderer`](#renderer) | No | [`fallbackRenderer`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/lib/rendererRegistry.tsx) | Renderer used on error
|
|
264
|
-
| `containerProps` | [`DivProps`](#divprops) | No | - | Props applied to preview container
|
|
265
|
-
| `iconProps` | [`DivProps`](#divprops) | No | - | Props applied to fallback icon
|
|
266
|
-
| `onLoad` | [`Eventhandler`](#eventhandler) | No | – | Called when preview is ready
|
|
267
|
-
| `onError` | [`Eventhandler`](#eventhandler) | No | – | Called when preview fails
|
|
307
|
+
| Prop | Type | Required | Default | Description |
|
|
308
|
+
| ------------------- | ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
309
|
+
| `src` | [`FileSource`](#filesource) | Yes | – | Source URL of the file to preview |
|
|
310
|
+
| `mimeType` | `string` | No | inferred | MIME type of the file |
|
|
311
|
+
| `fileName` | `string` | No | - | Used for MIME inference and accessibility |
|
|
312
|
+
| `autoPlay` | `boolean` | No | `false` | Auto play audio and video |
|
|
313
|
+
| `loader` | `ReactNode` | No | [`<Loader />`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/components.tsx) | Shown while the file is loading |
|
|
314
|
+
| `customRenderers` | [`Renderer[]`](#renderer) | No | - | Additional or overriding renderers |
|
|
315
|
+
| `additionalContext` | `object` | No | - | Extra data passed to the renderers. Must remain stable across renders |
|
|
316
|
+
| `errorRenderer` | [`Renderer`](#renderer) | No | [`fallbackRenderer`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/lib/rendererRegistry.tsx) | Renderer used on error |
|
|
317
|
+
| `containerProps` | [`DivProps`](#divprops) | No | - | Props applied to preview container |
|
|
318
|
+
| `iconProps` | [`DivProps`](#divprops) | No | - | Props applied to fallback icon |
|
|
319
|
+
| `onLoad` | [`Eventhandler`](#eventhandler) | No | – | Called when preview is ready |
|
|
320
|
+
| `onError` | [`Eventhandler`](#eventhandler) | No | – | Called when preview fails |
|
|
268
321
|
|
|
269
322
|
## Types
|
|
270
323
|
|
package/dist/index.js
CHANGED
|
@@ -191,7 +191,7 @@ function injectStyle(css) {
|
|
|
191
191
|
style.appendChild(document.createTextNode(css));
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
injectStyle("@layer rfpe {\n :where(.rfpe-container) {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n max-width: 100lvw;\n max-width: 100vw;\n }\n :where(.rfpe-icon) {\n width: 50px;\n
|
|
194
|
+
injectStyle("@layer rfpe {\n :where(.rfpe-container) {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n max-width: 100lvw;\n max-width: 100vw;\n }\n :where(.rfpe-icon) {\n width: 50px;\n }\n}\n.rfpe-audio {\n width: 100%;\n}\n.rfpe-iframe {\n background-color: white;\n}\n.rfpe-iframe,\n.rfpe-image,\n.rfpe-video {\n width: 100%;\n height: 100%;\n}\n.rfpe-image,\n.rfpe-video {\n object-fit: contain;\n}\n.rfpe-text {\n width: 100%;\n height: 100%;\n overflow: auto;\n white-space: pre-wrap;\n}\n.rfpe-loader {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n}\n.rfpe-loader-spinner {\n box-sizing: border-box;\n width: 22px;\n aspect-ratio: 1;\n border-radius: 50%;\n border: 2px solid transparent;\n border-top-color: black;\n border-bottom-color: black;\n animation: rfpe-spin-fast 0.6s ease infinite;\n}\n.rfpe-loader-text {\n font-size: 0.875rem;\n}\n@keyframes rfpe-spin-fast {\n to {\n transform: rotate(360deg);\n }\n}\n");
|
|
195
195
|
|
|
196
196
|
// src/index.tsx
|
|
197
197
|
var { additionalContext: defaultContext, customRenderers: defaultRenderers2, props: defaultProps } = defaults;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-file-preview-engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A renderer-driven React file preview engine with extensible architecture for images, video, audio, pdf, html, and custom formats.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sahil Aggarwal <aggarwalsahil2004@gmail.com>",
|