scorm-review 1.2.0 → 1.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.
Files changed (3) hide show
  1. package/README.md +361 -0
  2. package/dist/cli.js +38 -5
  3. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,361 @@
1
+ # scorm-review
2
+
3
+ > Inject the **coreview** annotation tool into any SCORM package — no server, no browser extension, no setup needed on the reviewer's end.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ - [What it does](#what-it-does)
10
+ - [How it works](#how-it-works)
11
+ - [Requirements](#requirements)
12
+ - [Installation](#installation)
13
+ - [Option A — Use with npx (no install)](#option-a--use-with-npx-no-install)
14
+ - [Option B — Install globally](#option-b--install-globally)
15
+ - [Usage](#usage)
16
+ - [Convert a SCORM zip](#convert-a-scorm-zip)
17
+ - [Convert a SCORM folder](#convert-a-scorm-folder)
18
+ - [Convert a plain HTML file](#convert-a-plain-html-file)
19
+ - [Specify a custom output path](#specify-a-custom-output-path)
20
+ - [Show help](#show-help)
21
+ - [Output explained](#output-explained)
22
+ - [What gets changed inside your package](#what-gets-changed-inside-your-package)
23
+ - [How to send to a reviewer](#how-to-send-to-a-reviewer)
24
+ - [CLI reference](#cli-reference)
25
+ - [How it works internally](#how-it-works-internally)
26
+ - [Entry point detection](#entry-point-detection)
27
+ - [Script injection](#script-injection)
28
+ - [coreview.js bundling](#coreviewjs-bundling)
29
+ - [Project structure](#project-structure)
30
+ - [Building from source](#building-from-source)
31
+ - [Troubleshooting](#troubleshooting)
32
+
33
+ ---
34
+
35
+ ## What it does
36
+
37
+ `scorm-review` takes a SCORM package (zip file, unzipped folder, or a standalone HTML file) and injects the **coreview** annotation tool into it. The output is a new file your reviewers can open in any browser and leave comments directly on the slides — no install needed on their end.
38
+
39
+ ```
40
+ Before: my-course.zip ← plain SCORM package
41
+ After: my-course_review.zip ← same package + annotation panel built in
42
+ ```
43
+
44
+ Reviewers open `index.html` from the output zip and the annotation sidebar appears automatically.
45
+
46
+ ---
47
+
48
+ ## How it works
49
+
50
+ 1. Opens the input (zip, folder, or HTML file)
51
+ 2. Finds the HTML entry point (`index.html`)
52
+ 3. Injects a `<script>` tag referencing `coreview.js` into that HTML file
53
+ 4. Adds `coreview.js` (the annotation tool) next to the entry HTML
54
+ 5. Saves the modified package as a new zip (or HTML file for single-file input)
55
+
56
+ The original file is never modified. A new `_review` file is always created.
57
+
58
+ ---
59
+
60
+ ## Requirements
61
+
62
+ - [Node.js](https://nodejs.org/) **v18 or higher**
63
+
64
+ That's all. No other tools, no browser extensions, no server.
65
+
66
+ To check your Node.js version:
67
+
68
+ ```bash
69
+ node --version
70
+ # Should print v18.x.x or higher
71
+ ```
72
+
73
+ If you don't have Node.js, download the LTS version from [nodejs.org](https://nodejs.org).
74
+
75
+ ---
76
+
77
+ ## Installation
78
+
79
+ ### Option A — Use with npx (no install)
80
+
81
+ Run it directly without installing anything:
82
+
83
+ ```bash
84
+ npx scorm-review ./my-course.zip
85
+ ```
86
+
87
+ `npx` is included with Node.js. On first run it fetches the package automatically.
88
+
89
+ ### Option B — Install globally
90
+
91
+ Install once, use from anywhere without the `npx` prefix:
92
+
93
+ ```bash
94
+ npm install -g scorm-review
95
+ ```
96
+
97
+ Then:
98
+
99
+ ```bash
100
+ scorm-review ./my-course.zip
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Usage
106
+
107
+ ### Convert a SCORM zip
108
+
109
+ ```bash
110
+ npx scorm-review ./my-course.zip
111
+ ```
112
+
113
+ Output in the same folder:
114
+
115
+ ```
116
+ Input: my-course.zip
117
+ Output: C:\path\to\my-course_review.zip
118
+
119
+ Processing SCORM zip... done.
120
+
121
+ ✓ Created: my-course_review.zip (15.2 MB)
122
+ ```
123
+
124
+ ### Convert a SCORM folder
125
+
126
+ If your SCORM package is already unzipped:
127
+
128
+ ```bash
129
+ npx scorm-review ./my-course/
130
+ ```
131
+
132
+ The tool walks the folder, finds `index.html`, injects the annotation tool, and packages everything back into a zip.
133
+
134
+ ### Convert a plain HTML file
135
+
136
+ For a standalone HTML file (not a SCORM package):
137
+
138
+ ```bash
139
+ npx scorm-review ./page.html
140
+ ```
141
+
142
+ Output: `page_review.html` — the script is embedded inline so no separate `coreview.js` file is needed.
143
+
144
+ ### Specify a custom output path
145
+
146
+ Use `-o` or `--output` to choose where the output file is saved:
147
+
148
+ ```bash
149
+ npx scorm-review ./my-course.zip -o ./output/my-course_review.zip
150
+ ```
151
+
152
+ The output directory is created automatically if it doesn't exist.
153
+
154
+ ### Show help
155
+
156
+ ```bash
157
+ npx scorm-review --help
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Output explained
163
+
164
+ | Input | Output file | Notes |
165
+ |---|---|---|
166
+ | `my-course.zip` | `my-course_review.zip` | New zip with `coreview.js` added and `index.html` injected |
167
+ | `my-course/` (folder) | `my-course_review.zip` | Folder re-zipped with `coreview.js` added and `index.html` injected |
168
+ | `page.html` | `page_review.html` | Single file — script embedded inline |
169
+
170
+ The output is always saved **next to the input file** unless you specify `-o`.
171
+
172
+ ---
173
+
174
+ ## What gets changed inside your package
175
+
176
+ Only two things change inside the output zip compared to the original:
177
+
178
+ 1. **`coreview.js` is added** — placed in the same folder as `index.html`
179
+ 2. **One `<script>` tag is added to `index.html`** — injected just before `</body>`
180
+
181
+ ```html
182
+ <!-- Added by scorm-review -->
183
+ <script
184
+ src="./coreview.js"
185
+ data-project="scorm-review"
186
+ data-note="Please review all slides. Check layout, wording, and content."
187
+ data-start-open="false">
188
+ </script>
189
+ ```
190
+
191
+ Everything else — folder structure, file names, SCORM manifest, assets — is **untouched**.
192
+
193
+ If a `coreview.js` script tag already exists in the HTML, it is replaced rather than duplicated.
194
+
195
+ ---
196
+
197
+ ## How to send to a reviewer
198
+
199
+ 1. Run `scorm-review` on your SCORM package
200
+ 2. Send the `_review.zip` to your reviewer (email, shared drive, etc.)
201
+ 3. Reviewer unzips it and opens `index.html` in any modern browser (Chrome, Edge, Firefox, Safari)
202
+ 4. The annotation panel appears automatically — they can leave comments on any slide
203
+ 5. They share their annotated session back to you (via the coreview export feature)
204
+
205
+ No installs, no accounts, no browser extensions required on the reviewer's side.
206
+
207
+ ---
208
+
209
+ ## CLI reference
210
+
211
+ ```
212
+ scorm-review <input> [options]
213
+
214
+ Arguments:
215
+ <input> Path to a .zip file, a folder, or a .html file
216
+
217
+ Options:
218
+ -o, --output <path> Custom output file path (default: <name>_review.zip next to input)
219
+ -h, --help Show help message
220
+
221
+ Supported input types:
222
+ .zip SCORM package zip file
223
+ folder/ Unzipped SCORM package directory
224
+ .html / .htm Plain HTML file
225
+
226
+ Exit codes:
227
+ 0 Success
228
+ 1 Error (path not found, unsupported file type, no HTML entry point found)
229
+ ```
230
+
231
+ ---
232
+
233
+ ## How it works internally
234
+
235
+ ### Entry point detection
236
+
237
+ The tool looks for the HTML entry point in this priority order:
238
+
239
+ 1. `index.html` at the root of the zip/folder
240
+ 2. `Index.html` at the root (case-insensitive fallback)
241
+ 3. `<subfolder>/index.html` — one level deep (common in SCORM packages where content is inside `scorm_package/`)
242
+ 4. Any `.html` file anywhere in the package
243
+
244
+ If no HTML file is found, the tool exits with an error.
245
+
246
+ ### Script injection
247
+
248
+ The `<script>` tag is injected just before `</body>`. If the HTML has no `</body>` tag, the script is appended to the end of the file.
249
+
250
+ Any existing `coreview.js` script tags are removed before injecting the new one — so re-running the tool on an already-injected package is safe and idempotent.
251
+
252
+ ### coreview.js bundling
253
+
254
+ `coreview.js` is **baked into the CLI binary at build time** using esbuild. This means:
255
+
256
+ - The CLI is a single file with no runtime file dependencies
257
+ - The same version of the annotation tool ships with every release
258
+ - No network access is needed at runtime — everything is self-contained
259
+
260
+ ---
261
+
262
+ ## Project structure
263
+
264
+ ```
265
+ scorm-review-cli/
266
+ ├── src/
267
+ │ ├── cli.ts # Entry point — argument parsing, file I/O, orchestration
268
+ │ ├── bundler.ts # Core logic — zip handling, HTML injection, folder packing
269
+ │ └── bundler-template.ts # Template used during the build to embed coreview.js
270
+ ├── dist/ # Compiled output (generated by build)
271
+ │ └── cli.js # Single-file compiled CLI (published to npm)
272
+ ├── build.mjs # esbuild build script — compiles + inlines coreview.js
273
+ ├── tsconfig.json # TypeScript configuration
274
+ └── package.json
275
+ ```
276
+
277
+ ### Key files
278
+
279
+ **`src/cli.ts`** — Handles all CLI concerns: argument parsing, input validation, calling the right bundler function, and writing the output file. Contains no bundling logic itself.
280
+
281
+ **`src/bundler.ts`** — Contains three exported functions:
282
+ - `bundleScormZip(zipBuffer, coreviewScript)` — processes a zip Buffer
283
+ - `bundleScormFolder(folderPath, coreviewScript)` — processes a folder on disk
284
+ - `bundlePlainHtml(htmlBuffer, coreviewScript)` — processes a standalone HTML file
285
+
286
+ **`build.mjs`** — esbuild script that reads `coreview.js` from disk, base64-encodes it (or inlines it as a string), and substitutes the `__COREVIEW_SCRIPT__` constant at bundle time. The result is `dist/cli.js`, a single portable file with no external dependencies.
287
+
288
+ ---
289
+
290
+ ## Building from source
291
+
292
+ ```bash
293
+ # Install dev dependencies
294
+ npm install
295
+
296
+ # Build dist/cli.js
297
+ npm run build
298
+ ```
299
+
300
+ The build script (`build.mjs`) uses esbuild to:
301
+ 1. Compile TypeScript to JavaScript
302
+ 2. Bundle all imports into a single file
303
+ 3. Inline `coreview.js` as a string constant at build time
304
+ 4. Output `dist/cli.js` with the Node.js shebang line
305
+
306
+ To test the built binary locally:
307
+
308
+ ```bash
309
+ node dist/cli.js ./samplefolder/sample3.zip
310
+ ```
311
+
312
+ ---
313
+
314
+ ## Troubleshooting
315
+
316
+ **`npx: command not found`**
317
+
318
+ Node.js is not installed or not on your PATH. Download from [nodejs.org](https://nodejs.org) and reinstall.
319
+
320
+ ---
321
+
322
+ **`Error: Path not found: ...`**
323
+
324
+ The file or folder you specified doesn't exist at that path. Check for typos, or use the full absolute path:
325
+
326
+ ```bash
327
+ npx scorm-review "C:\Users\yourname\Desktop\my-course.zip"
328
+ ```
329
+
330
+ ---
331
+
332
+ **`Error: No HTML entry point found`**
333
+
334
+ The zip doesn't contain an `index.html`. Possible causes:
335
+ - You pointed at a zip that isn't a SCORM package
336
+ - The SCORM package has a non-standard entry point (e.g. `story.html` instead of `index.html`)
337
+ - The `index.html` is nested more than one level deep
338
+
339
+ Try unzipping manually and pointing the tool at the folder that contains `index.html`:
340
+
341
+ ```bash
342
+ npx scorm-review ./unzipped-course/
343
+ ```
344
+
345
+ ---
346
+
347
+ **`Error: Unsupported file type ".pptx"`**
348
+
349
+ Only `.zip`, `.html`, `.htm`, and folders are accepted. Other file types are not supported.
350
+
351
+ ---
352
+
353
+ **Output zip is much larger than the original**
354
+
355
+ This is expected when the original zip used maximum compression. The tool re-compresses with level 6 (balanced), which may produce a slightly larger file compared to an original that was compressed at level 9. The content is identical.
356
+
357
+ ---
358
+
359
+ **Running the tool again on a `_review.zip` adds a second injection**
360
+
361
+ Re-running on an already-processed file is safe — the tool removes any existing `coreview.js` script tag before injecting a new one, so no duplication occurs.
package/dist/cli.js CHANGED
@@ -9745,19 +9745,52 @@ var import_fs = __toESM(require("fs"));
9745
9745
  var import_path = __toESM(require("path"));
9746
9746
  function findEntryHtml(files) {
9747
9747
  const norm = files.map((f) => f.replace(/\\/g, "/"));
9748
- if (norm.includes("index.html")) return "index.html";
9749
- if (norm.includes("Index.html")) return "Index.html";
9750
- const nested = norm.find((f) => /^[^/]+\/index\.html$/i.test(f));
9751
- if (nested) return nested;
9748
+ const rootCandidates = [
9749
+ "index.html",
9750
+ "Index.html",
9751
+ "story.html",
9752
+ "Story.html",
9753
+ "index_lms.html",
9754
+ "launch.html",
9755
+ "default.html"
9756
+ ];
9757
+ for (const candidate of rootCandidates) {
9758
+ const match = norm.find((f) => f.toLowerCase() === candidate.toLowerCase());
9759
+ if (match) return match;
9760
+ }
9761
+ const nestedCandidates = ["index.html", "story.html", "index_lms.html", "launch.html", "default.html"];
9762
+ for (const candidate of nestedCandidates) {
9763
+ const match = norm.find((f) => new RegExp(`^[^/]+/${candidate}$`, "i").test(f));
9764
+ if (match) return match;
9765
+ }
9766
+ const rootHtml = norm.find((f) => /^[^/]+\.html?$/i.test(f));
9767
+ if (rootHtml) return rootHtml;
9752
9768
  const anyHtml = norm.find((f) => /\.html?$/i.test(f));
9753
9769
  return anyHtml ?? null;
9754
9770
  }
9755
9771
  function injectCoreviewTag(html) {
9756
9772
  const scriptTag = `<script src="./coreview.js" data-project="scorm-review" data-note="Please review all slides. Check layout, wording, and content." data-start-open="false"></script>`;
9757
9773
  html = html.replace(/<script[^>]*src="[^"]*coreview\.js"[^>]*><\/script>\s*/gi, "");
9758
- if (/<\/body>/i.test(html)) {
9774
+ const hasBody = /<\/body>/i.test(html);
9775
+ const hasHtml = /<\/html>/i.test(html);
9776
+ if (hasBody && hasHtml) {
9777
+ const bodyIdx = html.search(/<\/body>/i);
9778
+ const htmlIdx = html.search(/<\/html>/i);
9779
+ const betweenBodyAndHtml = html.slice(bodyIdx + "</body>".length, htmlIdx).trim();
9780
+ if (betweenBodyAndHtml.length > 0) {
9781
+ return html.replace(/<\/html>/i, `${scriptTag}
9782
+ </html>`);
9783
+ }
9759
9784
  return html.replace(/<\/body>/i, `${scriptTag}
9760
9785
  </body>`);
9786
+ }
9787
+ if (hasBody) {
9788
+ return html.replace(/<\/body>/i, `${scriptTag}
9789
+ </body>`);
9790
+ }
9791
+ if (hasHtml) {
9792
+ return html.replace(/<\/html>/i, `${scriptTag}
9793
+ </html>`);
9761
9794
  }
9762
9795
  return html + "\n" + scriptTag;
9763
9796
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scorm-review",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Convert SCORM zip packages into self-contained review HTML files",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {