From 1f1071f5a977b87f6051cf8275b6ddaad641dbe3 Mon Sep 17 00:00:00 2001 From: David Ball Date: Mon, 24 Jun 2024 01:02:26 -0400 Subject: [PATCH] feat: Embedded Microsoft Office Viewer and Google Docs Viewer web services and no longer download as default action when viewer is supported when loading directory with file attachment that doesn't automatically render. --- app/helpers/functions.mts | 10 ++++ app/page/router.mts | 6 +-- app/page/vercel-serve.mts | 60 ++++++++++++------------ app/views/directory.ejs | 67 +++++++++++++++++++++++---- app/views/includes/bottom-scripts.ejs | 3 +- app/views/includes/common-head.ejs | 2 +- 6 files changed, 104 insertions(+), 44 deletions(-) diff --git a/app/helpers/functions.mts b/app/helpers/functions.mts index 13907508..5c6e2000 100644 --- a/app/helpers/functions.mts +++ b/app/helpers/functions.mts @@ -186,6 +186,14 @@ const renderArchive = (html: string, paths: string[]) => { return html; } +const isMsOfficeViewerSupported = (file: string) => { + return path.extname(file).search(/^((?:.pptx)|(?:.docx)|(?:.xlsx)|(?:.ppt)|(?:.doc)|(?:.xls))$/ig) != -1; +} + +const isGoogleDocsViewerSupported = (file: string) => { + return isMsOfficeViewerSupported(file) || path.extname(file).search(/^((?:.pdf))$/ig) != -1; +} + export default { leftTrimFirstDirectory, trimSlashes, @@ -205,4 +213,6 @@ export default { inspect, md, moment, + isMsOfficeViewerSupported, + isGoogleDocsViewerSupported, }; \ No newline at end of file diff --git a/app/page/router.mts b/app/page/router.mts index 65dfb26c..bd072740 100644 --- a/app/page/router.mts +++ b/app/page/router.mts @@ -78,7 +78,7 @@ export default function () { } }); const renderData = { breadcrumbs, content, filePath, fullFilePath, paths, req, route, ...fmData }; - res.render("page", { h: helpers, ...renderData }); + res.render("page", { h: helpers, path, config, ...renderData }); }); }); @@ -122,7 +122,7 @@ export default function () { console.log(`Setting route for ${route}`); pageRouter.get(route, async (req, res) => { const html = fs.readFileSync(fullFilePath).toString(); - const renderData = { route, filePath, fullFilePath, req, paths, html }; + const renderData = { route, filePath, fullFilePath, req, paths, html, path, config }; res.render("archive", { h: helpers, ...renderData }); }); }); @@ -183,7 +183,7 @@ export default function () { } }); const renderData = { breadcrumbs, route, filePath, fullFilePath, req, paths, directory: path.join('public', directory), videoURL, subtitleURL, subtitleVTT, info }; - res.render("video-player", { h: helpers, ...renderData }); + res.render("video-player", { h: helpers, path, config, ...renderData }); } }); }); diff --git a/app/page/vercel-serve.mts b/app/page/vercel-serve.mts index 1308e953..98524f1c 100644 --- a/app/page/vercel-serve.mts +++ b/app/page/vercel-serve.mts @@ -81,15 +81,15 @@ export interface ServeHandlerOptions { * current working directory. * * For example, if serving a Jekyll app, it would look like this: - * { - * "public": "_site" - * } + * { + * "public": "_site" + * } * * Using absolute path: * - * { - * "public": "/path/to/your/_site" - * } + * { + * "public": "/path/to/your/_site" + * } * * NOTE: The path cannot contain globs or regular expressions. */ @@ -101,17 +101,17 @@ export interface ServeHandlerOptions { * with status code 301 to the same path, but with the extension dropped. * * You can disable the feature like follows: - * { - * "cleanUrls": false - * } + * { + * "cleanUrls": false + * } * * However, you can also restrict it to certain paths: - * { - * "cleanUrls": [ - * "/app/**", - * "/!components/**" - * ] - * } + * { + * "cleanUrls": [ + * "/app/**", + * "/!components/**" + * ] + * } * * NOTE: The paths can only contain globs that are matched using minimatch. */ @@ -121,19 +121,19 @@ export interface ServeHandlerOptions { * different one behind the curtains, this option is what you need. * * It's perfect for single page applications (SPAs), for example: - * { - * "rewrites": [ - * { "source": "app/**", "destination": "/index.html" }, - * { "source": "projects/edit", "destination": "/edit-project.html" } - * ] - * } + * { + * "rewrites": [ + * { "source": "app/**", "destination": "/index.html" }, + * { "source": "projects/edit", "destination": "/edit-project.html" } + * ] + * } * * You can also use so-called "routing segments" as follows: - * { - * "rewrites": [ - * { "source": "/projects/:id/edit", "destination": "/edit-project-:id.html" }, - * ] - * } + * { + * "rewrites": [ + * { "source": "/projects/:id/edit", "destination": "/edit-project-:id.html" }, + * ] + * } * * Now, if a visitor accesses /projects/123/edit, it will respond with the file /edit-project-123.html. * @@ -184,8 +184,9 @@ export const directoryTemplate = (vals: ServeDirectoryTemplateParameters) => { }); } return new Promise((resolve, reject) => { - ejs.renderFile(path.join(config.viewsPath, 'directory.ejs'), { breadcrumbs, h: helpers, ...vals }, (err, str) => { + ejs.renderFile(path.join(config.viewsPath, 'directory.ejs'), { h: helpers, path, config, breadcrumbs, ...vals }, (err, str) => { if (err) { + console.error(err); reject(err); } else { resolve(str); @@ -196,8 +197,9 @@ export const directoryTemplate = (vals: ServeDirectoryTemplateParameters) => { export const errorTemplate = (vals: ServeErrorTemplateParameters) => { return new Promise((resolve, reject) => { - ejs.renderFile(path.join(config.viewsPath, 'error.ejs'), { h: helpers, ...vals }, (err, str) => { + ejs.renderFile(path.join(config.viewsPath, 'error.ejs'), { h: helpers, path, config, ...vals }, (err, str) => { if (err) { + console.error(err); reject(err); } else { resolve(str); @@ -1012,4 +1014,4 @@ export default async (request: Request, response: ServerResponse, serveConfig: S response.writeHead(response.statusCode || 200, headers); stream.pipe(response); -}; +}; \ No newline at end of file diff --git a/app/views/directory.ejs b/app/views/directory.ejs index edfe52dd..adb96576 100644 --- a/app/views/directory.ejs +++ b/app/views/directory.ejs @@ -4,18 +4,13 @@ <%=h.getDirectoryTitle(directory)%> <%- include('./includes/common-head.ejs') %> - - <%- include('./includes/top-navbar.ejs') %> - <%- include('./includes/no-trash-svg.ejs') %> -
<%- include('./includes/breadcrumbs.ejs') %>
- <% if (h.directoryContainsReadme(directory)) {%>
@@ -27,13 +22,69 @@ Document Date: <%= h.moment(h.readmeFm(directory).docDate).format('MMMM D, YYYY') %> <% } %> <%if (typeof h.readmeFm(directory).file !== 'undefined') { %> - Attached Document: <%- h.readmeFm(directory).file %> + Document: <%- h.readmeFm(directory).file %> <% } %>

<% } %> <% if (typeof h.readmeFm(directory).file !== 'undefined') { %> - + +
+ <% if (h.isMsOfficeViewerSupported(h.readmeFm(directory).file)) { %> +
+ +
+ <% } %> + <% if (h.isGoogleDocsViewerSupported(h.readmeFm(directory).file)) { %> +
+ +
+ <% } %> +
+ +
+ + <% if (!h.isMsOfficeViewerSupported(h.readmeFm(directory).file) && !h.isGoogleDocsViewerSupported(h.readmeFm(directory).file)) { %> + + <% } %> +
<% } else { %> <%- h.printReadme(directory) %> <% } %> @@ -54,7 +105,6 @@
<% } %> <% } %> -
    <% files.forEach(function(value, index) { %>
  • @@ -65,7 +115,6 @@ <% }); %>
- <%- include('./includes/bottom-navbar.ejs') %> <%- include('./includes/bottom-scripts.ejs') %> diff --git a/app/views/includes/bottom-scripts.ejs b/app/views/includes/bottom-scripts.ejs index c0bfd4da..71577113 100644 --- a/app/views/includes/bottom-scripts.ejs +++ b/app/views/includes/bottom-scripts.ejs @@ -1,6 +1,5 @@ - - + \ No newline at end of file diff --git a/app/views/includes/common-head.ejs b/app/views/includes/common-head.ejs index 7188b755..64a86044 100644 --- a/app/views/includes/common-head.ejs +++ b/app/views/includes/common-head.ejs @@ -10,7 +10,6 @@ - @@ -26,3 +25,4 @@ +