@nypl/web-reader 4.1.0 → 4.3.0
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 +178 -188
- package/dist/cjs/index.js +16 -51
- package/dist/cjs/index.js.map +3 -3
- package/dist/esm/index.js +331 -264
- package/dist/esm/index.js.map +3 -3
- package/dist/types/HtmlReader/index.d.ts +0 -12
- package/dist/types/HtmlReader/lib.d.ts +0 -5
- package/dist/types/HtmlReader/useUpdateCSS.d.ts +1 -2
- package/dist/types/PdfReader/addTocToManifest.d.ts +10 -0
- package/dist/types/PdfReader/index.d.ts +0 -1
- package/dist/types/PdfReader/lib.d.ts +26 -0
- package/dist/types/PdfReader/reducer.d.ts +3 -0
- package/dist/types/PdfReader/types.d.ts +61 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/ui/theme/components/button.d.ts +6 -0
- package/dist/types/utils/localstorage.d.ts +5 -9
- package/package.json +2 -13
- package/dist/types/utils/decryptAxisNow.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
# NYPL Web Reader
|
|
2
2
|
|
|
3
|
-
This project is a web reader built by NYPL for reading eBooks. It
|
|
3
|
+
This project is a web reader built by NYPL for reading eBooks. It was designed using the [Readium Architecture](https://github.com/readium/architecture), and specifically built for Webpubs. Webpub is a spec [defined by the Readium Foundation](https://github.com/readium/webpub-manifest) to provide a common abstraction between many types of web publications. This project currently focuses on HTML-based Webpubs and Webpubs that define PDF collections. An HTML-based Webpub can be generated from many types of eBooks, but most commonly ePubs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Demo - Example App
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This project features an example application under `/example`, which is deployed here: https://nypl-web-reader.vercel.app.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Built With
|
|
10
10
|
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
11
|
+
- [esbuild](https://esbuild.github.io/) - JavaScript bundler for the web-reader package
|
|
12
|
+
- [react-pdf](https://react-pdf.org/) - For creating PDF files on the browser and server
|
|
13
|
+
- [chakra-ui](https://chakra-ui.com/) - For styling the default UI components
|
|
14
|
+
- [TypeScript](https://www.npmjs.com/package/typescript) - JavaScript with syntax for types
|
|
15
|
+
- [React](https://www.npmjs.com/package/react) - For creating user interface components
|
|
16
|
+
- [Jest](https://jestjs.io/) & [React Testing Library](https://testing-library.com/) - For writing unit tests
|
|
17
|
+
- The Example App is packaged with [Parcel](https://parceljs.org/) & deployed with [Vercel](https://vercel.com/). Integration tests are run with [Cypress](https://www.cypress.io/).
|
|
13
18
|
|
|
14
19
|
## Features
|
|
15
20
|
|
|
@@ -23,17 +28,17 @@ A big thanks to [R2D2BC](https://github.com/d-i-t-a/R2D2BC) for providing the un
|
|
|
23
28
|
- [x] Fullscreen
|
|
24
29
|
- [x] Paginated / Scrolling mode toggle
|
|
25
30
|
- [x] Zoom (PDF only)
|
|
26
|
-
- [x] Offline support (prefetch and cache desired content via Service Worker, along with host app shell.
|
|
27
|
-
- [ ] Saving bookmarks / highlights
|
|
28
31
|
- [x] WAI-ARIA compliant accessibility
|
|
29
32
|
- [x] Integration tested
|
|
33
|
+
- [ ] Offline support (prefetch and cache desired content via Service Worker, along with host app shell)
|
|
34
|
+
- [ ] Saving bookmarks / highlights
|
|
30
35
|
|
|
31
|
-
##
|
|
36
|
+
## Examples
|
|
32
37
|
|
|
33
38
|
Basic usage within a React app, using the default UI:
|
|
34
39
|
|
|
35
40
|
```typescript
|
|
36
|
-
import WebReader from 'nypl/web-reader';
|
|
41
|
+
import WebReader from '@nypl/web-reader';
|
|
37
42
|
|
|
38
43
|
const ReaderPage = ({ manifestUrl }) => {
|
|
39
44
|
return (
|
|
@@ -45,96 +50,32 @@ const ReaderPage = ({ manifestUrl }) => {
|
|
|
45
50
|
};
|
|
46
51
|
```
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const ReaderPage = ({manifestUrl}) => {
|
|
55
|
-
const decryptor = new AxisNowDecryptor(...);
|
|
56
|
-
return (
|
|
57
|
-
<WebReader
|
|
58
|
-
getContent={decryptor.getContent}
|
|
59
|
-
manifestUrl={manifestUrl}
|
|
60
|
-
/>
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
To support customization, you can piece together your own UI and call the `useWebReader` hook to get access to the reader API.
|
|
53
|
+
- [More React examples](/example/index.tsx) - Includes examples that render EPUB2 & EPUB3 based webpubs, remote hosted webpubs, and PDFs
|
|
54
|
+
- [Encrypted example](/example/axisnow-encrypted.tsx) - How to pass an content decryptor to the web-reader to render encrypted content
|
|
55
|
+
- [usePDFReader hook example](/example/use-pdf-reader.tsx) - Useful for instances when you know you're only going to be using the web-reader to open PDFs
|
|
56
|
+
- [useHTMLReader hook example](/example/use-html-reader.tsx) - Useful for cases when you know you're only going to be using the web-reader to read EPUBs
|
|
57
|
+
- [Real-world example: Open eBooks Web](https://github.com/NYPL/ereading-clients/blob/staging/apps/oew/src/components/theme-ui/WebReader.tsx) - NYPL application for children to read books on the web. This demonstrates how encrypted AxisNow content is passed to the web-reader.
|
|
58
|
+
- [Real-world example: Digital Research Books (DRB)](https://github.com/NYPL/sfr-bookfinder-front-end/blob/development/src/components/ReaderLayout/ReaderLayout.tsx) - NYPL application that collects digital versions of research books into one convenient place to search.
|
|
66
59
|
|
|
67
|
-
|
|
68
|
-
import { useWebReader, ReaderNav, ReaderFooter } from 'nypl/web-reader';
|
|
60
|
+
## Required Fonts
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
// takes a manifest, instantiates a Navigator, and
|
|
72
|
-
// returns the Navigator, interaction handlers, and
|
|
73
|
-
// the current state of the reader as an object
|
|
74
|
-
const reader = useWebReader({
|
|
75
|
-
webpubManifestUrl,
|
|
76
|
-
});
|
|
62
|
+
In order for the Settings panel to be displayed as intended, the fonts Roboto, Georgia, and OpenDyslexic must be available to your application. Georgia is web safe, meaning it is installed by default on most devices, but the others are not. One way to include them is to copy them from the `fonts` folder in `@nypl/web-reader/example/static` into your `/public` directory. Alternatively, for Roboto, you can embed the Google Font into the <head> of your html (directions [here](https://fonts.google.com/specimen/Roboto)).
|
|
77
63
|
|
|
78
|
-
|
|
79
|
-
<div>
|
|
80
|
-
{/* eg. keep default header, but change its background */}
|
|
81
|
-
<ReaderNav {...reader} className="bg-blue" />
|
|
64
|
+
## Required CSS Injectables for the HTML Reader (EPUBs)
|
|
82
65
|
|
|
83
|
-
|
|
84
|
-
<button onClick={reader.handleNextPage}>Next</button>
|
|
85
|
-
<button onClick={reader.handlePrevPage}>Prev</button>
|
|
66
|
+
**Note:** This section does not apply to PDFs
|
|
86
67
|
|
|
87
|
-
|
|
88
|
-
{reader.content}
|
|
68
|
+
The HTML Reader can inject `<style>` tags (and other tags) into the reader iframe itself, called an "injectable". This is used to add styles to the html content of the publication.
|
|
89
69
|
|
|
90
|
-
|
|
91
|
-
<ReaderFooter {...reader} />
|
|
92
|
-
</div>
|
|
93
|
-
);
|
|
94
|
-
};
|
|
95
|
-
```
|
|
70
|
+
In order for the web-reader to render EPUBs correctly and display the OpenDyslexic font, there are some files that you must import into your application and inject into the `<WebReader />`. Those files are as follows:
|
|
96
71
|
|
|
97
|
-
|
|
72
|
+
1. The `opendyslexic` font
|
|
73
|
+
2. The three default Readium stylesheets
|
|
98
74
|
|
|
99
|
-
|
|
100
|
-
import { usePdfReader } from 'nypl/web-reader';
|
|
75
|
+
We export the Readium CSS stylesheets compiled under `@nypl/web-reader/dist/injectable-html-styles/*.css`. These css files can then be imported via webpack as a url to a static file that is copied to the dist folder. You can then use this url in your injectable config.
|
|
101
76
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return <div>{reader.content}</div>;
|
|
106
|
-
};
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Finally, to use in a vanilla Javascript app:
|
|
110
|
-
|
|
111
|
-
```html
|
|
112
|
-
<div id="web-reader" />
|
|
113
|
-
<script>
|
|
114
|
-
const readerDiv = document.getElementById('web-reader');
|
|
115
|
-
renderReader(readerDiv, {
|
|
116
|
-
manifestUrl: xxx,
|
|
117
|
-
});
|
|
118
|
-
</script>
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## Styling
|
|
122
|
-
|
|
123
|
-
Most styling is included in the basic UI, but we also ship a few css files that must be included:
|
|
124
|
-
|
|
125
|
-
1. Both the HTML and the PDF side have css that is necessary to be included for the dependencies we use to render correctly. This is built automatically into `@nypl/web-reader/dist/esm/index.css` and `@nypl/web-reader/dist/cjs/index.css`. Depending which package you are using, you should include one of those files in your bundle.
|
|
126
|
-
1. The HTML Reader can inject `<style>` tags (and other tags) into the reader iframe itself, called an "injectable". This is used to add styles to the html content of the publication. More on this is below.
|
|
127
|
-
|
|
128
|
-
In order for the Settings panel to be displayed as intended, the fonts Roboto, Georgia, Helvetica, and OpenDyslexic must be available to your application. Georgia is web safe, meaning it is installed by default on most devices, but the others are not. One way to include them is to copy the `fonts` folder and its contents from `@nypl/web-reader/example/static` into your `/public` directory.
|
|
129
|
-
|
|
130
|
-
## Injectables
|
|
131
|
-
|
|
132
|
-
The HTML Reader has the ability to inject custom elements into the reader iframe. This is most useful for passing stylesheets and fonts, but other elements can be injected too. It is recommended to pass the `opendyslexic` font and the default Readium stylesheets as injectables to the iframe.
|
|
133
|
-
|
|
134
|
-
In the below example, we show two different ways to do this.
|
|
135
|
-
|
|
136
|
-
1. We export the Readium CSS stylesheets compiled under `@nypl/web-reader/dist/injectable-html-styles/*.css`. These css files can then be imported via webpack as a url to a static file that is copied to the dist folder. You can then use this url in your injectable config.
|
|
137
|
-
2. The `fontInjectable` uses a plain url to a css file that we host normally on our site. In this case you would be responsible for copying the css file into your source code and making sure it is hosted at some location.
|
|
77
|
+
**Example:**
|
|
78
|
+
You will need to install `file-loader`, `extract-loader`, and `css-loader` and import the files you need like this:
|
|
138
79
|
|
|
139
80
|
```ts
|
|
140
81
|
import readiumBefore from '!file-loader!extract-loader!css-loader!@nypl/web-reader/dist/injectable-html-styles/ReadiumCSS-before.css';
|
|
@@ -155,6 +96,8 @@ const cssInjectables: Injectable[] = [
|
|
|
155
96
|
url: readiumAfter,
|
|
156
97
|
},
|
|
157
98
|
];
|
|
99
|
+
|
|
100
|
+
// The `fontInjectable` uses a plain url to a css file that we host normally on our site. In this case you would be responsible for copying the css file into your source code and making sure it is hosted at some location.
|
|
158
101
|
const fontInjectable: Injectable = {
|
|
159
102
|
type: 'style',
|
|
160
103
|
url: `${origin}/fonts/opendyslexic/opendyslexic.css`,
|
|
@@ -166,39 +109,106 @@ const htmlInjectables = [...cssInjectables, fontInjectable];
|
|
|
166
109
|
const Reader = () => {
|
|
167
110
|
return (
|
|
168
111
|
<WebReader
|
|
169
|
-
|
|
112
|
+
injectablesReflowable={htmlInjectables}
|
|
170
113
|
webpubManifestUrl="example/manifest.json"
|
|
171
114
|
/>
|
|
172
115
|
);
|
|
173
116
|
};
|
|
174
117
|
```
|
|
175
118
|
|
|
176
|
-
|
|
119
|
+
A real-world [example](https://github.com/NYPL/sfr-bookfinder-front-end/blob/development/src/components/ReaderLayout/ReaderLayout.tsx) can be seen in the Digital Research Books project.
|
|
120
|
+
|
|
121
|
+
Alternatively, you can host those three Readium CSS files within your project and import them wherever you render the <WebReader />. This is what we are doing in [Open eBooks](https://github.com/NYPL/ereading-clients/tree/staging/apps/oew/public/css/readium), which enables us to support offline reading mode.
|
|
122
|
+
|
|
123
|
+
### injectablesFixed vs. injectablesReflowable
|
|
124
|
+
|
|
125
|
+
There are two different injectables props you can pass to the web reader.
|
|
126
|
+
|
|
127
|
+
- `injectablesReflowable` is used by HTML-based text books, or any content that makes sense to be resized based on the screen size. For most cases, this is where you should add the Readium CSS files mentioned above.
|
|
128
|
+
- `injectablesFixed` is being used in Open eBooks as a way to style picture books. It could also be used to style other formats like audio and video files.
|
|
129
|
+
|
|
130
|
+
Your app can provide both props or only one. The reader will decide which one to load into the iframe based on the book format defined in the webpub manifest.
|
|
131
|
+
|
|
132
|
+
## Other Injectables
|
|
133
|
+
|
|
134
|
+
You can import and inject other files into the `<WebReader />` to customize behavior. For example, in Open eBooks, we import some [custom JavaScript](https://github.com/NYPL/ereading-clients/blob/staging/apps/oew/src/components/theme-ui/WebReader.tsx#L65) to disable right clicking & copying copywritten content.
|
|
135
|
+
|
|
136
|
+
## Custom Styling
|
|
137
|
+
|
|
138
|
+
Basic default styling is included in the basic UI. We are using [Chakra](https://chakra-ui.com/) to style the default UI components. You can wrap our UI components in your own `<ThemeProvider>` to pass your own custom theme.
|
|
177
139
|
|
|
178
140
|
## Errors
|
|
179
141
|
|
|
180
|
-
We make every effort to throw useful errors. Your app should probably wrap the web reader component in a React `<ErrorBoundary>` to either display the thrown errors or a custom error state for your users in the case one is thrown.
|
|
142
|
+
We make every effort to throw useful errors. Your app should probably wrap the web reader component in a React `<ErrorBoundary>` to either display the thrown errors or a custom error state for your users in the case one is thrown.
|
|
143
|
+
|
|
144
|
+
## Modifying PDF Manifests
|
|
145
|
+
|
|
146
|
+
In some cases it may be desirable to modify the Webpub Manifest before passing it to the web reader. One example of this is with single-resource PDFs. These manifests sometimes arrive without a table of contents. The information for the TOC is embedded in the single PDF file itself. In this situation, we have set up a utility to extract the PDF TOC and add it to the manifest. There is an example of this working at [`/pdf/single-resource-short`](https://nypl-web-reader.vercel.app/pdf/single-resource-short).
|
|
147
|
+
|
|
148
|
+
In order to make this work in your app, you will want to:
|
|
149
|
+
|
|
150
|
+
1. Fetch your manifest
|
|
151
|
+
1. Use `addTocToManifest` to add the table of contents
|
|
152
|
+
1. Generate a synthetic URL for the in-memory JSON object
|
|
153
|
+
1. Pass this generated URL to the web reader.
|
|
154
|
+
|
|
155
|
+
<details>
|
|
156
|
+
<summary>See the example code</summary>
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const fetchAndModifyManifest: Fetcher<string, string> = async (url) => {
|
|
160
|
+
const response = await fetch(url);
|
|
161
|
+
const manifest = await response.json();
|
|
162
|
+
const modifiedManifest = await addTocToManifest(
|
|
163
|
+
manifest,
|
|
164
|
+
getProxiedResource(pdfProxyUrl),
|
|
165
|
+
pdfWorkerSrc
|
|
166
|
+
);
|
|
167
|
+
const syntheticUrl = URL.createObjectURL(
|
|
168
|
+
new Blob([JSON.stringify(modifiedManifest)])
|
|
169
|
+
);
|
|
170
|
+
return syntheticUrl;
|
|
171
|
+
};
|
|
181
172
|
|
|
182
|
-
|
|
173
|
+
const SingleResourcePdf = () => {
|
|
174
|
+
const { data: modifiedManifestUrl, isLoading } = useSWR<string>(
|
|
175
|
+
'/samples/pdf/single-resource-short.json',
|
|
176
|
+
fetchAndModifyManifest
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
if (isLoading || !modifiedManifestUrl) return <div>Loading...</div>;
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<WebReader
|
|
183
|
+
webpubManifestUrl={modifiedManifestUrl}
|
|
184
|
+
proxyUrl={pdfProxyUrl}
|
|
185
|
+
pdfWorkerSrc={`${origin}/pdf-worker/pdf.worker.min.js`}
|
|
186
|
+
/>
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
</details>
|
|
183
192
|
|
|
184
193
|
## Architecture
|
|
185
194
|
|
|
186
|
-
|
|
195
|
+
One of the primary architectural goals of the web reader is to abstract away the particularities of the many individual publication formats by using a common manifest to describe all publication types. This is the [Readium Webpub Manifest](https://readium.org/webpub-manifest/profiles/epub.html). This allows the web-reader to consume Webpub Manifests, not manipulate or generate them.
|
|
196
|
+
|
|
197
|
+
- ePubs are generally run through a Streamer, which fetches the full compressed ePub, generates a manifest for it, and then serves the individual pieces separately. Processing EPUBs into Webpub Manifests can be done with a Readium Streamer or some other way. [epub-to-webpub](https://github.com/NYPL/ePub-to-webpub) is used in the [Open eBooks](https://github.com/NYPL/ereading-clients/tree/staging/apps/oew) project and generates Webpub Manifests from EPUBs and the web-reader consumes them. Digital Research Books generates Webpub manifests for EPUBs using a [Python script](https://github.com/NYPL/drb-etl-pipeline/blob/main/managers/webpubManifest.py).
|
|
198
|
+
- On the PDF side, we don't have a shared utility for generating manifests, but the Digital Research Books project does use a [Python script](https://github.com/NYPL/drb-etl-pipeline/blob/main/managers/webpubManifest.py) to pre-generate PDF manifests from web-scraped content before sending them to the web-reader. These manifests are then stored in an S3 bucket.
|
|
187
199
|
|
|
188
|
-
|
|
200
|
+
A Webpub Manifest gives us metadata and the structure of the publication with links to the content. Depending on the `metadata.conformsTo` field, we know which type of reader to use to render the publication. Each media type (HTML for EPUBS, PDF for PDF publications, etc) has its own `use_X_Reader` hook (`usePdfReader`, `useHtmlReader`, etc).
|
|
201
|
+
|
|
202
|
+
C4 Models have been created to demonstrate how the WebReader and other web reading utilities interact with the DRB & Open eBooks apps. View them here: https://structurizr.com/share/72104
|
|
189
203
|
|
|
190
204
|
**Notes:**
|
|
191
205
|
|
|
192
206
|
- There is one `use_X_Reader` per _media-type_ (PDF, HTML, Image, etc), not per _format_. As in, ePub and Mobi books are different formats that use the same media type (HTML). Audiobooks and PDF collections use different media types. We currently only have plans for HTML and PDF, but other hooks are welcome and should fit right in.
|
|
193
|
-
-
|
|
194
|
-
- For example, DRB is pre-generating PDF manifests from web-scraped content.
|
|
195
|
-
- There is [nypl/epub-to-webpub](https://github.com/NYPL/ePub-to-webpub) to generate Webpub Manifests from EPUBS.
|
|
196
|
-
- ePubs are generally run through a Streamer, which is a piece that fetches the full compressed ePub, generates a manifest for it, and then serves the individual pieces separately.
|
|
197
|
-
- AxisNow encrypted ePubs are served uncompressed. We will generate the manifest for them on the client before instantiating the reader.
|
|
207
|
+
- AxisNow encrypted ePubs are served uncompressed. We will generate the manifest for them on the client before instantiating the reader.
|
|
198
208
|
|
|
199
|
-
### Pieces of the
|
|
209
|
+
### Pieces of the Architecture
|
|
200
210
|
|
|
201
|
-
1. **use_X_Reader
|
|
211
|
+
1. **use_X_Reader Hook**
|
|
202
212
|
|
|
203
213
|
- Takes in the Webpub Manifest and returns:
|
|
204
214
|
- `State` of the reader, such as current settings and location.
|
|
@@ -207,7 +217,7 @@ We always start with a Webpub Manifest, which gives us metadata and the structur
|
|
|
207
217
|
- Internally, it will instantiate whatever package is being used to control that media type, and render the contents into the `Content` element it returns.
|
|
208
218
|
- Each hook for each media type separately manages its own state using a redux-style `useReducer` hook. There is a basic set of common state that is shared and returned from the `use_X_Reader` hook, but custom internal state can also be added, such as the `D2Reader` instance in the `useHtmlReader` hook.
|
|
209
219
|
|
|
210
|
-
2. **useWebReader
|
|
220
|
+
2. **useWebReader Hook**
|
|
211
221
|
|
|
212
222
|
- This is a generic hook that works for both PDF manifests and HTML-type manifests. It will internally call the proper `use_X_Reader` hook for you, and pass through the return value.
|
|
213
223
|
|
|
@@ -221,7 +231,7 @@ We always start with a Webpub Manifest, which gives us metadata and the structur
|
|
|
221
231
|
This is the folder structure:
|
|
222
232
|
|
|
223
233
|
```txt
|
|
224
|
-
/cypress # cypress tests
|
|
234
|
+
/cypress # cypress integration tests
|
|
225
235
|
/example # example app packaged by Parcel
|
|
226
236
|
index.html
|
|
227
237
|
index.tsx # entrypoint for the demo app
|
|
@@ -235,9 +245,7 @@ This is the folder structure:
|
|
|
235
245
|
types.ts # commonly used types
|
|
236
246
|
useWebReader.tsx # the React hook providing the main API into the reader
|
|
237
247
|
/test
|
|
238
|
-
blah.test.tsx # tests
|
|
239
|
-
/stories # stories will go in here
|
|
240
|
-
/.storybook # storybook config
|
|
248
|
+
blah.test.tsx # unit tests go here
|
|
241
249
|
```
|
|
242
250
|
|
|
243
251
|
### Decryption
|
|
@@ -249,41 +257,37 @@ The web reader does support DRM via two possible routes:
|
|
|
249
257
|
|
|
250
258
|
The `AxisNow Encrypted EPUB` example shows how this is done using the private NYPL AxisNow decryptor. The AxisNow scheme is a specific DRM technique not publicly available and the repo and code for the decryptor cannot be shared. Thus this example will not work for the public, but you can read the example code to see how we use the private `Decryptor` package to:
|
|
251
259
|
|
|
252
|
-
- Create a Web Worker using Comlink](https://github.com/GoogleChromeLabs/comlink) that will
|
|
260
|
+
- Create a Web Worker using [Comlink](https://github.com/GoogleChromeLabs/comlink) that will perform the fetching and decryption. This should help keep the main thread free while those heavy tasks are performed.
|
|
253
261
|
- Fetch content from the network
|
|
254
262
|
- Decrypt the HTML content
|
|
255
263
|
- Search for embedded CSS and image assets
|
|
256
264
|
- Fetch those assets and decrypt them
|
|
257
|
-
- Re-embed the decrypted CSS and image assets as Object URLs into the decrypted HTML document
|
|
258
|
-
- Return the HTML string with fully decrypted reources for the web-reader to render in the iframe
|
|
259
|
-
|
|
260
|
-
## Commands
|
|
265
|
+
- Re-embed the decrypted CSS and image assets as Object URLs into the decrypted HTML document
|
|
266
|
+
- Return the HTML string with fully decrypted reources for the web-reader to render in the iframe
|
|
261
267
|
|
|
262
|
-
|
|
268
|
+
## Getting Started
|
|
263
269
|
|
|
264
|
-
|
|
270
|
+
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See [Publishing to NPM](#publishing-to-npm) for notes on how to publish a new version to NPM.
|
|
265
271
|
|
|
266
|
-
###
|
|
272
|
+
### Prerequisites
|
|
267
273
|
|
|
268
|
-
|
|
274
|
+
1. Before getting started, be sure to run `npm install`.
|
|
269
275
|
|
|
270
|
-
|
|
271
|
-
npm run start
|
|
272
|
-
```
|
|
276
|
+
If you are internal to NYPL you can be added to the private `@nypl-simplified-packages/axisnow-access-control-web` package, which is required in order to open the AxisNow Encrypted EPUB example. If you decide to install this package, you'll also need to generate a Personal Access Token in GitHub with `read` permissions and run `GH_PACKAGE_AUTH_TOKEN=<your-token-here> npm install`.
|
|
273
277
|
|
|
274
|
-
|
|
278
|
+
2. In order to open any of the PDF examples in the Example App, you'll need to allow urls in a `WebpubManifest` to be proxied. This is done by passing a `proxyUrl` to the `<WebReader>` component. In order to do that, you must have a proxy running somewhere.
|
|
275
279
|
|
|
276
|
-
|
|
277
|
-
npm run storybook
|
|
278
|
-
```
|
|
280
|
+
We have set up a small express-based CORS proxy that can be run for local development.
|
|
279
281
|
|
|
280
|
-
|
|
282
|
+
- Run the proxy with `npm run cors-proxy`.
|
|
283
|
+
- Pass the proxy url to the example app by setting the following env var in a `.env` file at the root of the project: `CORS_PROXY_URL="http://localhost:3001/?requestUrl="`.
|
|
284
|
+
- In a separate terminal session, start the example app: `npm run example`.
|
|
281
285
|
|
|
282
|
-
|
|
286
|
+
3. In order to open the AxisNow Encrypted EPUB example (`/html/axisnow-encrypted`), you will need to have `process.env.VAULT_UUID` and `process.env.ISBN` set in your `.env` file. Read [example/README.txt](/example/README.txt) for more info.
|
|
283
287
|
|
|
284
|
-
### Example
|
|
288
|
+
### Running the Example App
|
|
285
289
|
|
|
286
|
-
To run the example app:
|
|
290
|
+
To run the example app for local development:
|
|
287
291
|
|
|
288
292
|
```bash
|
|
289
293
|
npm run example
|
|
@@ -291,31 +295,47 @@ npm run example
|
|
|
291
295
|
|
|
292
296
|
The example will rebundle on change, but you have to refresh your browser to see changes (no hot reloading currently).
|
|
293
297
|
|
|
294
|
-
|
|
298
|
+
## Development Notes
|
|
295
299
|
|
|
296
|
-
|
|
300
|
+
### Performance Optimizations
|
|
297
301
|
|
|
298
|
-
|
|
299
|
-
|
|
302
|
+
Please see the main `tsdx` [optimizations docs](https://github.com/palmerhq/tsdx#optimizations). In particular, know that you can take advantage of development-only optimizations:
|
|
303
|
+
|
|
304
|
+
```js
|
|
305
|
+
// ./types/index.d.ts
|
|
306
|
+
declare var __DEV__: boolean;
|
|
307
|
+
|
|
308
|
+
// inside your code...
|
|
309
|
+
if (__DEV__) {
|
|
310
|
+
console.log('foo');
|
|
311
|
+
}
|
|
300
312
|
```
|
|
301
313
|
|
|
302
|
-
|
|
314
|
+
You can also choose to install and use [invariant](https://github.com/palmerhq/tsdx#invariant) and [warning](https://github.com/palmerhq/tsdx#warning) functions.
|
|
303
315
|
|
|
304
|
-
|
|
316
|
+
### Module Formats
|
|
305
317
|
|
|
306
|
-
|
|
318
|
+
CJS and ESModules module formats are supported.
|
|
307
319
|
|
|
308
|
-
|
|
320
|
+
The appropriate paths are configured in `package.json` and `dist/index.js` accordingly. Please [report](https://github.com/NYPL-Simplified/web-reader/issues) if any issues are found.
|
|
309
321
|
|
|
310
|
-
|
|
322
|
+
## Running the Tests
|
|
311
323
|
|
|
312
|
-
|
|
324
|
+
### Unit Tests with Jest
|
|
313
325
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
326
|
+
To run Jest in watch mode:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
npm run test
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
To run all the tests as they run in CI:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
npm run test:ci
|
|
336
|
+
```
|
|
317
337
|
|
|
318
|
-
### Cypress
|
|
338
|
+
### Integration Tests with Cypress
|
|
319
339
|
|
|
320
340
|
The tests we have are located in the `cypress/integration` folder.
|
|
321
341
|
|
|
@@ -333,60 +353,30 @@ To run tests on your terminal without a browser:
|
|
|
333
353
|
npm run cypress:cli
|
|
334
354
|
```
|
|
335
355
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
- `npm run test` - to run Jest in watch mode.
|
|
339
|
-
- `npm run size` - to calculate the real cost of the library for consumers (using [size-limit](https://github.com/ai/size-limit)).
|
|
340
|
-
- `npm run analyze` - to analyze the library bundle for places we can shrink down.
|
|
341
|
-
|
|
342
|
-
## Code Quality
|
|
356
|
+
## Code Quality & Bundle Size Checks
|
|
343
357
|
|
|
344
|
-
Code quality enforcement is set up with `prettier`, `husky`, and `lint-staged`.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
We are using [Chakra](https://chakra-ui.com/) to style our default UI components. You can wrap our UI components in your own `<ThemeProvider>` to pass your own custom theme.
|
|
358
|
+
- `npm run lint` to lint the code yourself. Code quality enforcement is set up in pre-commit hooks with `prettier`, `husky`, and `lint-staged`.
|
|
359
|
+
- `npm run size` - to calculate the real cost of the library for consumers (using [size-limit](https://github.com/ai/size-limit))
|
|
360
|
+
- `npm run analyze` - to analyze the library bundle for places we can shrink down
|
|
349
361
|
|
|
350
362
|
## Continuous Integration
|
|
351
363
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
There are two Github Workflows:
|
|
355
|
-
|
|
356
|
-
- `main` which installs deps w/ cache, lints, tests, and builds on all pushes against a Node and OS matrix
|
|
357
|
-
- `size` which comments cost comparison of your library on every pull request using [size-limit](https://github.com/ai/size-limit)
|
|
358
|
-
|
|
359
|
-
## Optimizations
|
|
360
|
-
|
|
361
|
-
Please see the main `tsdx` [optimizations docs](https://github.com/palmerhq/tsdx#optimizations). In particular, know that you can take advantage of development-only optimizations:
|
|
362
|
-
|
|
363
|
-
```js
|
|
364
|
-
// ./types/index.d.ts
|
|
365
|
-
declare var __DEV__: boolean;
|
|
366
|
-
|
|
367
|
-
// inside your code...
|
|
368
|
-
if (__DEV__) {
|
|
369
|
-
console.log('foo');
|
|
370
|
-
}
|
|
371
|
-
```
|
|
364
|
+
There are three Github Actions Workflows:
|
|
372
365
|
|
|
373
|
-
|
|
366
|
+
- `main` - installs deps w/ cache, lints, tests, and builds on all pushes against a Node and OS matrix
|
|
367
|
+
- `size` - comments cost comparison of your library on every pull request using [size-limit](https://github.com/ai/size-limit)
|
|
368
|
+
- `cypress` - runs the Cypress integration tests on Vercel deployments, which means it runs whenever a pull request is opened or updated
|
|
374
369
|
|
|
375
|
-
##
|
|
370
|
+
## Versioning
|
|
376
371
|
|
|
377
|
-
|
|
372
|
+
We use [SemVer](https://semver.org/) for versioning. For the versions available, see the [releases](https://github.com/NYPL-Simplified/web-reader/releases) on this repository.
|
|
378
373
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
## Deploying the Example Playground
|
|
374
|
+
## Publishing to NPM
|
|
382
375
|
|
|
383
|
-
|
|
376
|
+
To publish the package to [NPM](https://www.npmjs.com/package/@nypl/web-reader), you must first be added to the `nypl` organization within NPM.
|
|
384
377
|
|
|
385
|
-
|
|
386
|
-
cd example # if not already in the example folder
|
|
387
|
-
npm run build # builds to dist
|
|
388
|
-
```
|
|
378
|
+
Run `npm run release` from the main branch. Follow the prompts to add a new version, publish a release to github, and push to npm.
|
|
389
379
|
|
|
390
|
-
##
|
|
380
|
+
## License
|
|
391
381
|
|
|
392
|
-
|
|
382
|
+
This project is licensed under the MIT License - see the [LICENSE](/LICENSE) file for details.
|