mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Populate doc title, description and thumbnail in app.html
Summary: Fills in the title and description/thumbnail (for templates) in app.html if the page being requested is for a document. Test Plan: Tested manually. Reviewers: paulfitz Reviewed By: paulfitz Subscribers: dsagal Differential Revision: https://phab.getgrist.com/D3544
This commit is contained in:
parent
7078922a65
commit
c54dde3dba
@ -128,6 +128,10 @@ function pagePanelsDoc(owner: IDisposableOwner, appModel: AppModel, appObj: App)
|
|||||||
|
|
||||||
// Set document title to strings like "DocName - Grist"
|
// Set document title to strings like "DocName - Grist"
|
||||||
owner.autoDispose(subscribe(pageModel.currentDocTitle, (use, docName) => {
|
owner.autoDispose(subscribe(pageModel.currentDocTitle, (use, docName) => {
|
||||||
|
// If the document hasn't loaded yet, don't update the title; since the HTML document already has
|
||||||
|
// a title element with the document's name, there's no need for further action.
|
||||||
|
if (!pageModel.currentDoc.get()) { return; }
|
||||||
|
|
||||||
document.title = `${docName}${getPageTitleSuffix(getGristConfig())}`;
|
document.title = `${docName}${getPageTitleSuffix(getGristConfig())}`;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import {User} from './entity/User';
|
|||||||
import {HomeDBManager} from './lib/HomeDBManager';
|
import {HomeDBManager} from './lib/HomeDBManager';
|
||||||
|
|
||||||
// Special public organization that contains examples and templates.
|
// Special public organization that contains examples and templates.
|
||||||
const TEMPLATES_ORG_DOMAIN = process.env.GRIST_ID_PREFIX ?
|
export const TEMPLATES_ORG_DOMAIN = process.env.GRIST_ID_PREFIX ?
|
||||||
`templates-${process.env.GRIST_ID_PREFIX}` :
|
`templates-${process.env.GRIST_ID_PREFIX}` :
|
||||||
'templates';
|
'templates';
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import {getPageTitleSuffix, GristLoadConfig, HideableUiElements, IHideableUiElement} from 'app/common/gristUrls';
|
import {getPageTitleSuffix, GristLoadConfig, HideableUiElements, IHideableUiElement} from 'app/common/gristUrls';
|
||||||
import {getTagManagerSnippet} from 'app/common/tagManager';
|
import {getTagManagerSnippet} from 'app/common/tagManager';
|
||||||
|
import {Document} from 'app/common/UserAPI';
|
||||||
import {isAnonymousUser, RequestWithLogin} from 'app/server/lib/Authorizer';
|
import {isAnonymousUser, RequestWithLogin} from 'app/server/lib/Authorizer';
|
||||||
import {RequestWithOrg} from 'app/server/lib/extractOrg';
|
import {RequestWithOrg} from 'app/server/lib/extractOrg';
|
||||||
import {GristServer} from 'app/server/lib/GristServer';
|
import {GristServer} from 'app/server/lib/GristServer';
|
||||||
import {getSupportedEngineChoices} from 'app/server/lib/serverUtils';
|
import {getSupportedEngineChoices} from 'app/server/lib/serverUtils';
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import * as fse from 'fs-extra';
|
import * as fse from 'fs-extra';
|
||||||
|
import jsesc from 'jsesc';
|
||||||
|
import * as handlebars from 'handlebars';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
export interface ISendAppPageOptions {
|
export interface ISendAppPageOptions {
|
||||||
@ -65,8 +68,10 @@ export function makeGristConfig(homeUrl: string|null, extra: Partial<GristLoadCo
|
|||||||
export function makeMessagePage(staticDir: string) {
|
export function makeMessagePage(staticDir: string) {
|
||||||
return async (req: express.Request, resp: express.Response, message: any) => {
|
return async (req: express.Request, resp: express.Response, message: any) => {
|
||||||
const fileContent = await fse.readFile(path.join(staticDir, "message.html"), 'utf8');
|
const fileContent = await fse.readFile(path.join(staticDir, "message.html"), 'utf8');
|
||||||
const content = fileContent
|
const content = fileContent.replace(
|
||||||
.replace("<!-- INSERT MESSAGE -->", `<script>window.message = ${JSON.stringify(message)};</script>`);
|
"<!-- INSERT MESSAGE -->",
|
||||||
|
`<script>window.message = ${jsesc(message, {isScriptContext: true, json: true})};</script>`
|
||||||
|
);
|
||||||
resp.status(200).type('html').send(content);
|
resp.status(200).type('html').send(content);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -98,10 +103,15 @@ export function makeSendAppPage(opts: {
|
|||||||
const warning = testLogin ? "<div class=\"dev_warning\">Authentication is not enforced</div>" : "";
|
const warning = testLogin ? "<div class=\"dev_warning\">Authentication is not enforced</div>" : "";
|
||||||
const content = fileContent
|
const content = fileContent
|
||||||
.replace("<!-- INSERT WARNING -->", warning)
|
.replace("<!-- INSERT WARNING -->", warning)
|
||||||
|
.replace("<!-- INSERT TITLE -->", getPageTitle(config))
|
||||||
|
.replace("<!-- INSERT META -->", getPageMetadataHtmlSnippet(config))
|
||||||
.replace("<!-- INSERT TITLE SUFFIX -->", getPageTitleSuffix(server?.getGristConfig()))
|
.replace("<!-- INSERT TITLE SUFFIX -->", getPageTitleSuffix(server?.getGristConfig()))
|
||||||
.replace("<!-- INSERT BASE -->", `<base href="${staticBaseUrl}">` + tagManagerSnippet)
|
.replace("<!-- INSERT BASE -->", `<base href="${staticBaseUrl}">` + tagManagerSnippet)
|
||||||
.replace("<!-- INSERT CUSTOM -->", customHeadHtmlSnippet)
|
.replace("<!-- INSERT CUSTOM -->", customHeadHtmlSnippet)
|
||||||
.replace("<!-- INSERT CONFIG -->", `<script>window.gristConfig = ${JSON.stringify(config)};</script>`);
|
.replace(
|
||||||
|
"<!-- INSERT CONFIG -->",
|
||||||
|
`<script>window.gristConfig = ${jsesc(config, {isScriptContext: true, json: true})};</script>`
|
||||||
|
);
|
||||||
resp.status(options.status).type('html').send(content);
|
resp.status(options.status).type('html').send(content);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -123,3 +133,51 @@ function configuredPageTitleSuffix() {
|
|||||||
const result = process.env.GRIST_PAGE_TITLE_SUFFIX;
|
const result = process.env.GRIST_PAGE_TITLE_SUFFIX;
|
||||||
return result === "_blank" ? "" : result;
|
return result === "_blank" ? "" : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a page title suitable for inserting into an HTML title element.
|
||||||
|
*
|
||||||
|
* Currently returns the document name if the page being requested is for a document, or
|
||||||
|
* a placeholder, "Loading...", that's updated in the client once the page has loaded.
|
||||||
|
*
|
||||||
|
* Note: The string returned is escaped and safe to insert into HTML.
|
||||||
|
*/
|
||||||
|
function getPageTitle(config: GristLoadConfig): string {
|
||||||
|
const maybeDoc = getDocFromConfig(config);
|
||||||
|
if (!maybeDoc) { return 'Loading...'; }
|
||||||
|
|
||||||
|
return handlebars.Utils.escapeExpression(maybeDoc.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of 0 or more HTML metadata elements.
|
||||||
|
*
|
||||||
|
* Currently includes the document description and thumbnail if the requested page is
|
||||||
|
* for a document and the document has one set.
|
||||||
|
*
|
||||||
|
* Note: The string returned is escaped and safe to insert into HTML.
|
||||||
|
*/
|
||||||
|
function getPageMetadataHtmlSnippet(config: GristLoadConfig): string {
|
||||||
|
const metadataElements: string[] = [];
|
||||||
|
const maybeDoc = getDocFromConfig(config);
|
||||||
|
|
||||||
|
const description = maybeDoc?.options?.description;
|
||||||
|
if (description) {
|
||||||
|
const content = handlebars.Utils.escapeExpression(description);
|
||||||
|
metadataElements.push(`<meta name="description" content="${content}">`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const thumbnail = maybeDoc?.options?.icon;
|
||||||
|
if (thumbnail) {
|
||||||
|
const content = handlebars.Utils.escapeExpression(thumbnail);
|
||||||
|
metadataElements.push(`<meta name="thumbnail" content="${content}">`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadataElements.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDocFromConfig(config: GristLoadConfig): Document | null {
|
||||||
|
if (!config.getDoc || !config.assignmentId) { return null; }
|
||||||
|
|
||||||
|
return config.getDoc[config.assignmentId] ?? null;
|
||||||
|
}
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"@types/fs-extra": "5.0.4",
|
"@types/fs-extra": "5.0.4",
|
||||||
"@types/image-size": "0.0.29",
|
"@types/image-size": "0.0.29",
|
||||||
"@types/js-yaml": "3.11.2",
|
"@types/js-yaml": "3.11.2",
|
||||||
|
"@types/jsesc": "3.0.1",
|
||||||
"@types/jsonwebtoken": "7.2.8",
|
"@types/jsonwebtoken": "7.2.8",
|
||||||
"@types/lodash": "4.14.117",
|
"@types/lodash": "4.14.117",
|
||||||
"@types/lru-cache": "5.1.1",
|
"@types/lru-cache": "5.1.1",
|
||||||
@ -113,6 +114,7 @@
|
|||||||
"fs-extra": "7.0.0",
|
"fs-extra": "7.0.0",
|
||||||
"grain-rpc": "0.1.7",
|
"grain-rpc": "0.1.7",
|
||||||
"grainjs": "1.0.2",
|
"grainjs": "1.0.2",
|
||||||
|
"handlebars": "4.4.5",
|
||||||
"highlight.js": "9.13.1",
|
"highlight.js": "9.13.1",
|
||||||
"http-proxy-agent": "5.0.0",
|
"http-proxy-agent": "5.0.0",
|
||||||
"https-proxy-agent": "5.0.1",
|
"https-proxy-agent": "5.0.1",
|
||||||
@ -120,6 +122,7 @@
|
|||||||
"image-size": "0.6.3",
|
"image-size": "0.6.3",
|
||||||
"jquery": "2.2.1",
|
"jquery": "2.2.1",
|
||||||
"js-yaml": "3.12.0",
|
"js-yaml": "3.12.0",
|
||||||
|
"jsesc": "3.0.2",
|
||||||
"jsonwebtoken": "8.3.0",
|
"jsonwebtoken": "8.3.0",
|
||||||
"knockout": "3.5.0",
|
"knockout": "3.5.0",
|
||||||
"locale-currency": "0.0.2",
|
"locale-currency": "0.0.2",
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf8">
|
<meta charset="utf8">
|
||||||
|
<!-- INSERT META -->
|
||||||
|
|
||||||
<!-- INSERT BASE -->
|
<!-- INSERT BASE -->
|
||||||
|
|
||||||
@ -15,7 +16,7 @@
|
|||||||
<link rel="stylesheet" href="icons/icons.css">
|
<link rel="stylesheet" href="icons/icons.css">
|
||||||
<!-- INSERT CUSTOM -->
|
<!-- INSERT CUSTOM -->
|
||||||
|
|
||||||
<title>Loading...<!-- INSERT TITLE SUFFIX --></title>
|
<title><!-- INSERT TITLE --><!-- INSERT TITLE SUFFIX --></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- INSERT WARNING -->
|
<!-- INSERT WARNING -->
|
||||||
|
36
yarn.lock
36
yarn.lock
@ -3230,6 +3230,17 @@ gtoken@^5.0.4:
|
|||||||
google-p12-pem "^3.0.3"
|
google-p12-pem "^3.0.3"
|
||||||
jws "^4.0.0"
|
jws "^4.0.0"
|
||||||
|
|
||||||
|
handlebars@4.4.5:
|
||||||
|
version "4.4.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.4.5.tgz#1b1f94f9bfe7379adda86a8b73fb570265a0dddd"
|
||||||
|
integrity sha512-0Ce31oWVB7YidkaTq33ZxEbN+UDxMMgThvCe8ptgQViymL5DPis9uLdTA13MiRPhgvqyxIegugrP97iK3JeBHg==
|
||||||
|
dependencies:
|
||||||
|
neo-async "^2.6.0"
|
||||||
|
optimist "^0.6.1"
|
||||||
|
source-map "^0.6.1"
|
||||||
|
optionalDependencies:
|
||||||
|
uglify-js "^3.1.4"
|
||||||
|
|
||||||
har-schema@^2.0.0:
|
har-schema@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||||
@ -4352,6 +4363,11 @@ minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5:
|
|||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||||
|
|
||||||
|
minimist@~0.0.1:
|
||||||
|
version "0.0.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||||
|
integrity sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==
|
||||||
|
|
||||||
minimist@~1.1.1:
|
minimist@~1.1.1:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8"
|
||||||
@ -4575,7 +4591,7 @@ negotiator@0.6.2:
|
|||||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||||
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
||||||
|
|
||||||
neo-async@^2.6.2:
|
neo-async@^2.6.0, neo-async@^2.6.2:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||||
@ -4820,6 +4836,14 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
|
optimist@^0.6.1:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
|
||||||
|
integrity sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==
|
||||||
|
dependencies:
|
||||||
|
minimist "~0.0.1"
|
||||||
|
wordwrap "~0.0.2"
|
||||||
|
|
||||||
os-browserify@~0.3.0:
|
os-browserify@~0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
|
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
|
||||||
@ -6510,6 +6534,11 @@ typescript@4.7.4:
|
|||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
|
||||||
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
|
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
|
||||||
|
|
||||||
|
uglify-js@^3.1.4:
|
||||||
|
version "3.16.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.16.3.tgz#94c7a63337ee31227a18d03b8a3041c210fd1f1d"
|
||||||
|
integrity sha512-uVbFqx9vvLhQg0iBaau9Z75AxWJ8tqM9AV890dIZCLApF4rTcyHwmAvLeEdYRs+BzYWu8Iw81F79ah0EfTXbaw==
|
||||||
|
|
||||||
uid-safe@2.1.5, uid-safe@~2.1.5:
|
uid-safe@2.1.5, uid-safe@~2.1.5:
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
|
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
|
||||||
@ -6864,6 +6893,11 @@ winston@2.4.5:
|
|||||||
isstream "0.1.x"
|
isstream "0.1.x"
|
||||||
stack-trace "0.0.x"
|
stack-trace "0.0.x"
|
||||||
|
|
||||||
|
wordwrap@~0.0.2:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
|
||||||
|
integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==
|
||||||
|
|
||||||
wrap-ansi@^5.1.0:
|
wrap-ansi@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
|
||||||
|
Loading…
Reference in New Issue
Block a user