Skip to content

Commit

Permalink
unwrap document so puppeteer gets a fullPage screenshot
Browse files Browse the repository at this point in the history
  • Loading branch information
scytacki committed Oct 3, 2024
1 parent a06aab5 commit d6c7a63
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 24 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,13 @@ The `firebase`, `firestore`, and `functions` params can take an `emulator` value

There is an alternative entry point for CLUE available at `/editor/`. This can be used to save and open individual documents from the local file system. Remote documents can be loaded into this editor with the `document` URL parameter. The editor requires a `unit` parameter to configure the toolbar. It can load an exported document content which is typical for section documents. It can also load a raw document content which is the same format that is stored in Firebase. It will save in the same format that was loaded.

By default the editor will save the current document to the browser's session storage. When editor is reloaded this same document will be loaded in. If you make a new tab and visit the editor this document won't be there anymore because it is in session storage. There is a "reset doc" button which clears the storage and reloads the page. You can also use the `noStorage` parameter to prevent it from loading or saving to session storage.
The `noStorage` parameter can override the default behavior. By default the editor will save the current document to the browser's session storage. When editor is reloaded this same document will be loaded in. If you make a new tab and visit the editor this document won't be there anymore because it is in session storage. There is a "reset doc" button which clears the storage and reloads the page. The `noStorage` parameter will prevent it from loading or saving to session storage.

The `document` parameter is useful if you want to work on something that requires a document in a specific state. You can just reload the page and get back to this state. You can use this locally by creating an initial document in doc-editor.html, and save the file to `src/public/[filename]`. Now you can load the document back with the parameter `document=[filename]`. This works because the document parameter will load URLs relative to the current page in the browser. This approach can also be used in Cypress tests. It would mean the test could just load in a document to test instead of having to setup the document first.
The `document` parameter is useful if you want to work on something that requires a document in a specific state. You can just reload the page and get back to this state. You can use this locally by creating an initial document in `/editor/`, and save the file to `src/public/[filename]`. Now you can load the document back with the parameter `document=[filename]`. This works because the document parameter will load URLs relative to the current page in the browser. This approach can also be used in Cypress tests. It would mean the test could just load in a document to test instead of having to setup the document first.

The Standalone Document Editor also supports a `readOnly` url param. If you specify this param the document you open will be opened in readOnly mode. This is useful for testing or debugging issues with tiles that have different displays when in readOnly model.
The `readOnly` parameter will open the document in readOnly mode. This is useful for testing or debugging issues with tiles that have different displays when in readOnly model.

The `unwrapped` parameter will open the document without any surrounding UI. This is useful for taking screenshots of documents.

### QA

Expand Down
18 changes: 7 additions & 11 deletions scripts/ai/document-screenshots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const fileBatchSize = 8;

// The width of the browser window. The height is determined dynamically.
const windowWidth = 1920 / 2;

// The actual height is based on the content
const windowHeight = 540;
const publicRoot = "ai";
const rootPath = `../../src/public/${publicRoot}`;
const documentPath = `${rootPath}/${documentDirectory}`;
Expand Down Expand Up @@ -58,13 +59,13 @@ function newFileName(oldFileName: string) {

// makeSnapshot loads document content at path in a CLUE standalone document editor, takes a snapshot of it,
// then saves it in the output directory as fileName
const urlRoot = `http://localhost:8080/editor/?appMode=dev&unit=example&document=`;
const urlRoot = `http://localhost:8080/editor/?appMode=dev&unit=example&readOnly&unwrapped&document=`;
async function makeSnapshot(path: string, fileName: string) {
console.log(`* Processing snapshot`, path);
const targetFile = `${targetPath}/${fileName}`;

// View the document in the document editor
const browser = await puppeteer.launch({ headless: "new" });
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
const url = `${urlRoot}${path}`;
try {
Expand All @@ -80,14 +81,9 @@ async function makeSnapshot(path: string, fileName: string) {
return;
}

// Approximate the height of the document by adding up the heights of the rows and make the viewport that tall
let pageHeight = 30;
const rowElements = await page.$$(".tile-row");
for (const rowElement of rowElements) {
const boundingBox = await rowElement.boundingBox();
pageHeight += boundingBox?.height ?? 0;
}
await page.setViewport({ width: windowWidth, height: Math.round(pageHeight) });
// The actual height is based on the content because of the `fullPage` option
// passed to `page.screenshot`
await page.setViewport({ width: windowWidth, height: windowHeight });

// Take a screenshot and save it to a file
const buffer = await page.screenshot({ fullPage: true, type: 'png' });
Expand Down
29 changes: 21 additions & 8 deletions src/components/doc-editor/doc-editor-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const kDocEditorDocKey = "clue-doc-editor-doc";
// These are defined at the module level so the initialDoc can be used in two useState
// initializers. The initialDoc should only change when the page is loaded so this is
// safe.
const {document: documentURL, readOnly, noStorage } = urlParams;
const {document: documentURL, readOnly, noStorage, unwrapped } = urlParams;
const savedDocString = noStorage ? undefined : window.sessionStorage.getItem(kDocEditorDocKey);
const initialDoc = savedDocString ? JSON.parse(savedDocString) : defaultDocumentModel;

Expand Down Expand Up @@ -195,6 +195,19 @@ export const DocEditorApp = observer(function DocEditorApp() {
});
}, [loadDocument]);

if (unwrapped) {
// Let the window do the scrolling. If the body scrolls and shows the full content
// then puppeteer's screenshot function can capture the full content easily.
window.document.body.style.overflow = "visible";
return (
<CanvasComponent
document={document}
context="doc-editor-read-only"
readOnly={!!readOnly}
/>
);
}

// This is wrapped in a div.primary-workspace so it can be used with cypress
// tests that are looking for stuff in a div like this
return (
Expand All @@ -213,13 +226,13 @@ export const DocEditorApp = observer(function DocEditorApp() {
</div>
</div>
<EditableDocumentContent
contained={false}
mode="1-up"
isPrimary={true}
readOnly={readOnly}
document={document}
toolbar={appConfig.authorToolbar}
/>
contained={false}
mode="1-up"
isPrimary={true}
readOnly={readOnly}
document={document}
toolbar={appConfig.authorToolbar}
/>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/doc-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ stores.unitLoadedPromise.then(() => {
<AppProvider stores={stores} modalAppElement="#app">
<DocEditorApp/>
<DialogComponent/>
</AppProvider>,
</AppProvider>
</ChakraProvider>,
document.getElementById("app")
);
Expand Down
4 changes: 3 additions & 1 deletion src/utilities/url-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ export interface QueryParams {
document?: string;
// Open new documents as readOnly this helps with testing readOnly views
readOnly?: boolean
// Just display the document contents, no top toolbar or border
unwrapped?: boolean
// Don't load or save the document from browser storage
noStorage?: boolean
}
Expand All @@ -122,7 +124,7 @@ type BooleanParamNames = Exclude<
undefined>;

const booleanParams: BooleanParamNames[] =
[ "demo", "mouseSensor", "localCMSBackend", "noPersistentUI", "readOnly", "noStorage" ];
[ "demo", "mouseSensor", "localCMSBackend", "noPersistentUI", "readOnly", "noStorage", "unwrapped" ];

const processBooleanValue = (value: string | (string | null)[] | null | undefined) => {
if (value === undefined || value === "false") {
Expand Down

0 comments on commit d6c7a63

Please sign in to comment.