-
Notifications
You must be signed in to change notification settings - Fork 203
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update devserver to use express, Mustache and serve PDFJS-enabled PDFs
- Rewrite dev server as `express` app - Add `mustache-express` as template engine - Restructure document directories; add PDFs - Add `pdfjs-init.js` script for embedding PDFJS with H client - Update linting config to ignore static scripts
- Loading branch information
1 parent
bbd365a
commit da9c1d7
Showing
385 changed files
with
61,934 additions
and
274 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ build/** | |
**/vendor/**/*.js | ||
**/coverage/** | ||
docs/_build/* | ||
dev-server/static/**/*.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
build/ | ||
/build/ | ||
node_modules/ | ||
coverage/ | ||
docs/_build/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ | |
build/ | ||
coverage/ | ||
docs/ | ||
dev-server/static/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.
Binary file not shown.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
'use strict'; | ||
/* eslint-env node */ | ||
|
||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const express = require('express'); | ||
const log = require('fancy-log'); | ||
const mustacheExpress = require('mustache-express'); | ||
const Mustache = require('mustache'); | ||
|
||
const { createServer, useSsl } = require('./create-server'); | ||
|
||
const HTML_PATH = `${__dirname}/documents/html/`; | ||
const PDF_PATH = `${__dirname}/documents/pdf/`; | ||
const TEMPLATE_PATH = `${__dirname}/templates/`; | ||
|
||
/** | ||
* @typedef Config | ||
* @property {string} clientUrl - The URL of the client's boot script | ||
*/ | ||
|
||
/** | ||
* Generate `<script>` content for client configuration and injection | ||
* | ||
* @param {string} clientUrl | ||
* @return {string} | ||
*/ | ||
function renderConfig(clientUrl) { | ||
const scriptTemplate = fs.readFileSync( | ||
`${TEMPLATE_PATH}client-config.js.mustache`, | ||
'utf-8' | ||
); | ||
return Mustache.render(scriptTemplate, { clientUrl }); | ||
} | ||
|
||
/** | ||
* Build context for rendering templates in the defined views directory. This | ||
* is dead simple at present but could be extended as needs grow. | ||
* | ||
* @param {Config} config | ||
*/ | ||
function templateContext(config) { | ||
return { | ||
hypothesisScript: renderConfig(config.clientUrl), | ||
}; | ||
} | ||
|
||
/** | ||
* An HTTP server which serves test documents with the development client embedded. | ||
* | ||
* @param {number} port - The port that the test server should listen on. | ||
* @param {Config} config - Config for the server | ||
*/ | ||
function serveDev(port, config) { | ||
const app = express(); | ||
|
||
app.engine('mustache', mustacheExpress()); | ||
app.set('view engine', 'mustache'); | ||
app.set('views', [HTML_PATH, path.join(__dirname, '/templates')]); | ||
|
||
app.use(express.static(path.join(__dirname, 'static'))); | ||
|
||
// Serve static PDF files out of the PDF directory, but serve under | ||
// `/pdf-source/` — these are needed by PDF JS viewer | ||
app.use('/pdf-source', express.static(PDF_PATH)); | ||
|
||
// Enable CORS for assets so that cross-origin font loading works. | ||
app.use(function (req, res, next) { | ||
res.append('Access-Control-Allow-Origin', '*'); | ||
res.append('Access-Control-Allow-Methods', 'GET'); | ||
next(); | ||
}); | ||
|
||
// Landing page | ||
app.get('/', (req, res) => { | ||
res.render('index', templateContext(config)); | ||
}); | ||
|
||
// Serve HTML documents with injected client script | ||
app.get('/document/:document', (req, res, next) => { | ||
if (fs.existsSync(`${HTML_PATH}${req.params.document}.mustache`)) { | ||
res.render(req.params.document, templateContext(config)); | ||
} else { | ||
next(); | ||
} | ||
}); | ||
|
||
// Serve PDF documents with PDFJS viewer and client script | ||
app.get('/pdf/:pdf', (req, res, next) => { | ||
if (fs.existsSync(`${PDF_PATH}${req.params.pdf}.pdf`)) { | ||
const fullUrl = `${req.protocol}://${req.hostname}:${port}${req.originalUrl}`; | ||
res.render('pdfjs-viewer', { | ||
documentUrl: fullUrl, // The URL that annotations are associated with | ||
url: `/pdf-source/${req.params.pdf}.pdf`, // The URL for the PDF source file | ||
clientUrl: config.clientUrl, | ||
}); | ||
} else { | ||
next(); | ||
} | ||
}); | ||
|
||
// Nothing else matches: this is a 404 | ||
app.use((req, res) => { | ||
res.render('404', templateContext(config)); | ||
}); | ||
|
||
createServer(app).listen(port, () => { | ||
const scheme = useSsl ? 'https' : 'http'; | ||
log(`Dev web server started at ${scheme}://localhost:${port}/`); | ||
}); | ||
} | ||
|
||
module.exports = serveDev; |
5 changes: 0 additions & 5 deletions
5
dev-server/static/scripts/pdfjs-2/web/images/toolbarButton-menuArrow-dark.svg
This file was deleted.
Oops, something went wrong.
4 changes: 0 additions & 4 deletions
4
dev-server/static/scripts/pdfjs-2/web/images/toolbarButton-menuArrow.svg
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
'use strict'; | ||
|
||
// Note: This file is not transpiled. | ||
// Listen for `webviewerloaded` event to configure the viewer after its files | ||
// have been loaded but before it is initialized. | ||
document.addEventListener('webviewerloaded', () => { | ||
const appOptions = window.PDFViewerApplicationOptions; | ||
const app = window.PDFViewerApplication; | ||
|
||
// Ensure that PDF.js viewer events such as "documentloaded" are dispatched | ||
// to the DOM. The client relies on this. | ||
appOptions.set('eventBusDispatchToDOM', true); | ||
|
||
// Disable preferences support, as otherwise this will result in `eventBusDispatchToDOM` | ||
// being overridden with the default value of `false`. | ||
appOptions.set('disablePreferences', true); | ||
|
||
// Prevent loading of default viewer PDF. | ||
appOptions.set('defaultUrl', ''); | ||
|
||
// Read configuration rendered into template as global vars. | ||
const documentUrl = window.DOCUMENT_URL; | ||
const url = window.PDF_URL; | ||
const clientEmbedUrl = window.CLIENT_URL; | ||
|
||
// Wait for the PDF viewer to be fully initialized and then load the Hypothesis client. | ||
// | ||
// This is required because the client currently assumes that `PDFViewerApplication` | ||
// is fully initialized when it loads. Note that "fully initialized" only means | ||
// that the PDF viewer application's components have been initialized. The | ||
// PDF itself will still be loading, and the client will wait for that to | ||
// complete before fetching annotations. | ||
// | ||
const pdfjsInitialized = new Promise(resolve => { | ||
// Poll `app.initialized` as there doesn't appear to be an event that | ||
// we can listen to. | ||
const timer = setInterval(function () { | ||
if (app.initialized) { | ||
clearTimeout(timer); | ||
resolve(); | ||
} | ||
}, 20); | ||
}); | ||
|
||
pdfjsInitialized.then(() => { | ||
// Prevent PDF.js' `Promise` polyfill, if it was used, from being | ||
// overwritten by the one that ships with Hypothesis (both from core-js). | ||
// | ||
// See https://github.com/hypothesis/via/issues/81#issuecomment-531121534 | ||
if ( | ||
typeof Promise === 'function' && | ||
typeof PromiseRejectionEvent === 'undefined' | ||
) { | ||
window.PromiseRejectionEvent = function FakePromiseRejectionEvent() { | ||
// core-js doesn't actually use this, it just tests for `typeof PromiseRejectionEvent` | ||
console.warn('Tried to construct fake `PromiseRejectionEvent`'); | ||
}; | ||
} | ||
|
||
// Load the Hypothesis client. | ||
const embedScript = document.createElement('script'); | ||
embedScript.src = clientEmbedUrl; | ||
document.body.appendChild(embedScript); | ||
|
||
// Load the PDF specified in the URL. | ||
// | ||
// This is done after the viewer components are initialized to avoid some | ||
// race conditions in `PDFViewerApplication` if the PDF finishes loading | ||
// (eg. from the HTTP cache) before the viewer is fully initialized. | ||
// | ||
// See https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions#can-i-specify-a-different-pdf-in-the-default-viewer | ||
// and https://github.com/mozilla/pdf.js/issues/10435#issuecomment-452706770 | ||
app.open({ | ||
// Load PDF through Via to work around CORS restrictions. | ||
url: url, | ||
|
||
// Make sure `PDFViewerApplication.url` returns the original URL, as this | ||
// is the URL associated with annotations. | ||
originalUrl: documentUrl, | ||
}); | ||
}); | ||
}); |
File renamed without changes.
Oops, something went wrong.