Commit 344204ff authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Update dev server document configuration and add some templating

parent 2fd096ba
......@@ -72,6 +72,7 @@
"lodash.debounce": "^4.0.3",
"loose-envify": "^1.4.0",
"mocha": "8.1.1",
"mustache": "^4.0.1",
"npm-packlist": "^2.0.1",
"postcss": "^7.0.13",
"postcss-url": "^8.0.0",
......
......@@ -3,19 +3,74 @@
const fs = require('fs');
const log = require('fancy-log');
const urlParser = require('url');
const Mustache = require('mustache');
const { createServer, useSsl } = require('./create-server');
function readmeText() {
return fs.readFileSync('./README.md', 'utf-8');
const DOCUMENT_PATH = './test-documents/';
const DOCUMENT_PATTERN = /\.html\.mustache/;
/**
* Render some content in an HTML document with `<pre>` tags
*
* @param {string} filename - source to inject between `<pre>` tags
* @return {string}
*/
function preformattedContent(filename) {
const textContent = fs.readFileSync(filename, 'utf-8');
const template = fs.readFileSync(
`${DOCUMENT_PATH}preformatted.template.mustache`,
'utf-8'
);
return Mustache.render(template, { textContent });
}
function licenseText() {
return fs.readFileSync('./LICENSE', 'utf-8');
/**
* Generate `<script>` content for client configuration and injection
*
* @param {string} clientUrl
* @return {string}
*/
function renderConfig(clientUrl) {
const scriptTemplate = fs.readFileSync(
`${DOCUMENT_PATH}client-config.js.mustache`,
'utf-8'
);
return Mustache.render(scriptTemplate, { clientUrl });
}
function codeOfConductText() {
return fs.readFileSync('./CODE_OF_CONDUCT', 'utf-8');
/**
* Read in the file at `filename` and render it as a template, injecting
* script source for the embedded client.
*
* @param {string} filename
* @param {string} clientUrl
* @param [{Object}] context - optional extra view context
* @return {string} Rendered HTML template with injected script
*/
function injectClientScript(filename, clientUrl, context = {}) {
const documentTemplate = fs.readFileSync(filename, 'utf-8');
const scriptContent = renderConfig(clientUrl);
context = { ...context, hypothesisScript: scriptContent };
return Mustache.render(documentTemplate, context);
}
/**
* Provide a "route" for all HTML documents in the test-documents directory
*
* @return {Object<string, string>} - Routes, mapping route (path) to
* filepath of HTML document
*/
function buildDocumentRoutes() {
const documentRoutes = {};
const documentPaths = fs
.readdirSync(DOCUMENT_PATH)
.filter(filename => filename.match(DOCUMENT_PATTERN));
documentPaths.forEach(filename => {
const shortName = filename.replace(DOCUMENT_PATTERN, '');
documentRoutes[`/document/${shortName}`] = `${DOCUMENT_PATH}${filename}`;
});
return documentRoutes;
}
/**
......@@ -32,118 +87,30 @@ function codeOfConductText() {
* @constructor
*/
function DevServer(port, config) {
const documentRoutes = buildDocumentRoutes();
const preformattedRoutes = {
'/document/code_of_conduct': './CODE_OF_CONDUCT',
'/document/license': './LICENSE',
};
function listen() {
const app = function (req, response) {
const url = urlParser.parse(req.url);
let content;
if (url.pathname === '/document/license') {
content = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hypothesis in-line frame document - License</title>
</head>
<body>
<pre style="margin: 20px;">${licenseText()}</pre>
</body>
</html>
`;
} else if (url.pathname === '/document/code_of_conduct') {
content = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hypothesis in-line frame document - Code of conduct</title>
</head>
<body>
<pre style="margin: 20px;">${codeOfConductText()}</pre>
</body>
</html>
`;
if (documentRoutes[url.pathname]) {
content = injectClientScript(
documentRoutes[url.pathname],
config.clientUrl
);
} else if (preformattedRoutes[url.pathname]) {
content = preformattedContent(preformattedRoutes[url.pathname]);
} else {
content = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hypothesis Client Test</title>
</head>
<body>
<div data-hypothesis-trigger style="margin: 75px 0 0 75px;">
Number of annotations:
<span data-hypothesis-annotation-count>...</span>
</div>
<div style="margin: 10px 0 0 75px;">
<button id="add-test" style="padding: 0.6em; font-size: 0.75em">Toggle 2nd Frame</button>
</div>
<div style="margin: 10px 0 0 75px;">
<iframe enable-annotation id="iframe1" src="/document/license" style="width: 50%;height: 300px;"></iframe>
</div>
<div id="iframe2-container" style="margin: 10px 0 0 75px;">
</div>
<pre style="margin: 20px 75px 75px 75px;">${readmeText()}</pre>
<script>
var appHost = document.location.hostname;
window.hypothesisConfig = function () {
// See https://h.readthedocs.io/projects/client/en/latest/publishers/config/
return {
// enableExperimentalNewNoteButton: true,
// showHighlights: 'always',
// theme: 'clean',
// Example focused user mode
// focus: {
// user: {
// username: 'foo',
// authority: 'lms',
// displayName: 'Foo Bar',
// }
// },
// Example services config
// services: [{
// apiUrl: 'http://localhost:5000/api',
// authority: 'partner.org',
// allowLeavingGroups: false,
// groups: ['a-group-id', 'another-group-id'],
// }],
// Open the sidebar when the page loads
openSidebar: true,
};
};
var embedScript = document.createElement('script');
embedScript.src = '${
config.clientUrl
}'.replace('{current_host}', document.location.hostname);
document.body.appendChild(embedScript);
var iframeIsAdded = false;
var addIframeBtn = document.querySelector('#add-test');
if(addIframeBtn){
addIframeBtn.addEventListener('click', function() {
if (!iframeIsAdded) {
var iframe1 = document.querySelector('#iframe1');
var iframeNew = iframe1.cloneNode();
iframeNew.src = "/document/code_of_conduct";
iframeNew.id = "iframe2";
iframeIsAdded = true;
document.querySelector('#iframe2-container').appendChild(iframeNew);
} else {
var iframe2 = document.querySelector('#iframe2');
iframe2.parentNode.removeChild(iframe2);
iframeIsAdded = false;
}
});
}
</script>
</body>
</html>
`;
content = injectClientScript(
`${DOCUMENT_PATH}index.template.mustache`,
config.clientUrl,
{ readme: fs.readFileSync('./README.md', 'utf-8') }
);
}
response.end(content);
};
......
This directory contains documents that are served by the local
web server (via `make dev`). Files here with a `.mustache.html` extension
will be available in the browser at the path
`localhost:<port>/document/<filename-without-extension>`,
e.g. `foo.mustache.html` would be available at `localhost:<port>/document/foo`.
Mustache-templated HTML documents may use `{{{ hypothesisScript }}}` to inject
the client application as configured by `client-config.js.mustache`.
Other things here:
- `client-config.js.mustache` - configuration for the client and JS to inject
the client into HTML pages. You can make edits here if you'd like to
change how the application is configured in the local web pages.
- `index.template.mustache` is the main "landing page" for the local dev server.
- `preformatted.template.mustach` is a template used to render some additional content
used by `index.template.mustache`
See `scripts/gulp/dev-server.js` for more information on how these files
are composed.
<script>
var appHost = document.location.hostname;
window.hypothesisConfig = function() {
return {
// enableExperimentalNewNoteButton: true,
// showHighlights: 'always',
// theme: 'clean',
// Example focused user mode
// focus: {
// user: {
// username: 'foo',
// authority: 'lms',
// displayName: 'Foo Bar',
// }
// },
// Example services config
// services: [{
// apiUrl: 'http://localhost:5000/api',
// authority: 'partner.org',
// allowLeavingGroups: false,
// groups: ['a-group-id', 'another-group-id'],
// }],
// Open the sidebar when the page loads
openSidebar: true,
};
};
var embedScript = document.createElement('script');
embedScript.src = '{{{clientUrl}}}'.replace('{current_host}', document.location.hostname);
document.body.appendChild(embedScript);
</script>
\ No newline at end of file
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hypothesis Client Test</title>
</head>
<body>
<div data-hypothesis-trigger style="margin: 75px 0 0 75px;">
Number of annotations:
<span data-hypothesis-annotation-count>...</span>
</div>
<div style="margin: 10px 0 0 75px;">
<button id="add-test" style="padding: 0.6em; font-size: 0.75em">Toggle 2nd Frame</button>
</div>
<div style="margin: 10px 0 0 75px;">
<iframe enable-annotation id="iframe1" src="/document/license" style="width: 50%;height: 300px;"></iframe>
</div>
<div id="iframe2-container" style="margin: 10px 0 0 75px;">
</div>
<pre style="margin: 20px 75px 75px 75px;">{{{readme}}}</pre>
{{{hypothesisScript}}}
<script>
var iframeIsAdded = false;
var addIframeBtn = document.querySelector('#add-test');
if(addIframeBtn){
addIframeBtn.addEventListener('click', function() {
if (!iframeIsAdded) {
var iframe1 = document.querySelector('#iframe1');
var iframeNew = iframe1.cloneNode();
iframeNew.src = "/document/code_of_conduct";
iframeNew.id = "iframe2";
iframeIsAdded = true;
document.querySelector('#iframe2-container').appendChild(iframeNew);
} else {
var iframe2 = document.querySelector('#iframe2');
iframe2.parentNode.removeChild(iframe2);
iframeIsAdded = false;
}
});
}
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hypothesis in-line frame document</title>
</head>
<body>
<pre style="margin: 20px;">{{{textContent}}}</pre>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
......@@ -5540,6 +5540,11 @@ ms@2.1.2, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
mustache@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2"
integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA==
mute-stdout@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment