reviw 0.13.2 → 0.13.3

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 (2) hide show
  1. package/cli.cjs +72 -5
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -149,6 +149,13 @@ marked.use({
149
149
  }
150
150
  var titleAttr = title ? ' title="' + escapeHtmlForXss(title) + '"' : "";
151
151
  var altAttr = text ? ' alt="' + escapeHtmlForXss(text) + '"' : "";
152
+ // Check if this is a video file - wrap in <a> tag for video player functionality
153
+ var videoExtensions = /\.(mp4|mov|webm|avi|mkv|m4v|ogv)$/i;
154
+ if (videoExtensions.test(href)) {
155
+ // For videos, return a clickable link with video icon
156
+ var displayText = text || href.split('/').pop();
157
+ return '<a href="' + escapeHtmlForXss(href) + '"' + titleAttr + ' class="video-link">📹' + escapeHtmlForXss(displayText) + '</a>';
158
+ }
152
159
  return '<img src="' + escapeHtmlForXss(href) + '"' + altAttr + titleAttr + '>';
153
160
  }
154
161
  }
@@ -5740,7 +5747,7 @@ function createFileServer(filePath, fileIndex = 0) {
5740
5747
  }
5741
5748
 
5742
5749
  // Static file serving for images and other assets
5743
- if (req.method === "GET") {
5750
+ if (req.method === "GET" || req.method === "HEAD") {
5744
5751
  const MIME_TYPES = {
5745
5752
  ".png": "image/png",
5746
5753
  ".jpg": "image/jpeg",
@@ -5753,9 +5760,21 @@ function createFileServer(filePath, fileIndex = 0) {
5753
5760
  ".js": "application/javascript",
5754
5761
  ".json": "application/json",
5755
5762
  ".pdf": "application/pdf",
5763
+ // Video formats
5764
+ ".mp4": "video/mp4",
5765
+ ".webm": "video/webm",
5766
+ ".mov": "video/quicktime",
5767
+ ".avi": "video/x-msvideo",
5768
+ ".mkv": "video/x-matroska",
5769
+ ".m4v": "video/x-m4v",
5770
+ ".ogv": "video/ogg",
5756
5771
  };
5757
5772
  try {
5758
- const urlPath = decodeURIComponent(req.url.split("?")[0]);
5773
+ let urlPath = decodeURIComponent(req.url.split("?")[0]);
5774
+ // Remove leading slash so path.join works correctly with relative baseDir
5775
+ if (urlPath.startsWith("/")) {
5776
+ urlPath = urlPath.slice(1);
5777
+ }
5759
5778
  if (urlPath.includes("..")) {
5760
5779
  res.writeHead(403, { "Content-Type": "text/plain" });
5761
5780
  res.end("forbidden");
@@ -5770,9 +5789,57 @@ function createFileServer(filePath, fileIndex = 0) {
5770
5789
  if (fs.existsSync(staticPath) && fs.statSync(staticPath).isFile()) {
5771
5790
  const ext = path.extname(staticPath).toLowerCase();
5772
5791
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
5773
- const content = fs.readFileSync(staticPath);
5774
- res.writeHead(200, { "Content-Type": contentType });
5775
- res.end(content);
5792
+ const stat = fs.statSync(staticPath);
5793
+ const fileSize = stat.size;
5794
+
5795
+ // Check if this is a video file that needs Range Request support
5796
+ const isVideo = contentType.startsWith("video/");
5797
+ const rangeHeader = req.headers.range;
5798
+
5799
+ if (isVideo && rangeHeader) {
5800
+ // Parse Range header (e.g., "bytes=0-1023")
5801
+ const parts = rangeHeader.replace(/bytes=/, "").split("-");
5802
+ const start = parseInt(parts[0], 10);
5803
+ const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
5804
+ const chunkSize = end - start + 1;
5805
+
5806
+ res.writeHead(206, {
5807
+ "Content-Range": `bytes ${start}-${end}/${fileSize}`,
5808
+ "Accept-Ranges": "bytes",
5809
+ "Content-Length": chunkSize,
5810
+ "Content-Type": contentType,
5811
+ });
5812
+
5813
+ if (req.method === "HEAD") {
5814
+ res.end();
5815
+ } else {
5816
+ const stream = fs.createReadStream(staticPath, { start, end });
5817
+ stream.pipe(res);
5818
+ }
5819
+ } else {
5820
+ // Non-range request or non-video file
5821
+ const headers = {
5822
+ "Content-Type": contentType,
5823
+ "Content-Length": fileSize,
5824
+ };
5825
+ // Add Accept-Ranges for video files so browser knows it can seek
5826
+ if (isVideo) {
5827
+ headers["Accept-Ranges"] = "bytes";
5828
+ }
5829
+ res.writeHead(200, headers);
5830
+
5831
+ // HEAD requests don't need body
5832
+ if (req.method === "HEAD") {
5833
+ res.end();
5834
+ } else if (fileSize > 1024 * 1024) {
5835
+ // Use streaming for large files (> 1MB)
5836
+ const stream = fs.createReadStream(staticPath);
5837
+ stream.pipe(res);
5838
+ } else {
5839
+ const content = fs.readFileSync(staticPath);
5840
+ res.end(content);
5841
+ }
5842
+ }
5776
5843
  return;
5777
5844
  }
5778
5845
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reviw",
3
- "version": "0.13.2",
3
+ "version": "0.13.3",
4
4
  "description": "Lightweight file reviewer with in-browser comments for CSV, TSV, Markdown, and Git diffs.",
5
5
  "type": "module",
6
6
  "bin": {