forked from sheetjs/docs.sheetjs.com
		
	v3manifest
This commit is contained in:
		
							parent
							
								
									7fbd794137
								
							
						
					
					
						commit
						709553e22e
					
				@ -130,6 +130,37 @@ _Writing Files_
 | 
			
		||||
XLSX.writeFile(wb, "SheetJS.xlsx");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Implementation Details</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
Under the hood, it creates a special URL and clicks a link. The library method
 | 
			
		||||
includes a few workarounds for legacy browsers
 | 
			
		||||
 | 
			
		||||
`XLSX.writeFile(wb, "SheetJS.xlsx");` is roughly equivalent to:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* write data -- note that writeFile infers bookType from filename */
 | 
			
		||||
const u8 = XLSX.write(wb, { bookType: "xlsx", type: "buffer" });
 | 
			
		||||
/* create Blob */
 | 
			
		||||
const blob = new Blob([u8]);
 | 
			
		||||
/* create object URL */
 | 
			
		||||
const url = URL.createObjectURL(new Blob([u8]));
 | 
			
		||||
 | 
			
		||||
/* create `A` DOM element */
 | 
			
		||||
const a = document.createElement("a");
 | 
			
		||||
/* set export file name */
 | 
			
		||||
a.download = "SheetJS.xlsx";
 | 
			
		||||
/* wire up the object URL to the DOM element */
 | 
			
		||||
a.href = url;
 | 
			
		||||
/* add to the page */
 | 
			
		||||
document.body.appendChild(a);
 | 
			
		||||
/* click the link */
 | 
			
		||||
a.click();
 | 
			
		||||
/* remove the element from the page */
 | 
			
		||||
document.body.removeChild(a);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
:::caution Web Workers
 | 
			
		||||
 | 
			
		||||
`XLSX.writeFile` requires DOM access and will not work in a Web Worker!
 | 
			
		||||
@ -378,6 +409,51 @@ var wb = readFile("sheetjs.numbers");
 | 
			
		||||
writeFile(wb, "sheetjs.xlsx");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Implementation Details</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
**`XLSX.readFile(filepath)`** is equivalent to:
 | 
			
		||||
 | 
			
		||||
_CommonJS_
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var fs = require("fs");
 | 
			
		||||
var buf = fs.readFileSync(filepath);
 | 
			
		||||
var wb = XLSX.read(buf);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
_ECMAScript Modules_
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { read } from "xlsx";
 | 
			
		||||
import { readFileSync } from "fs";
 | 
			
		||||
 | 
			
		||||
var buf = readFileSync(filepath);
 | 
			
		||||
var wb = read(buf);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**`XLSX.writeFile(wb, filepath)`** is equivalent to:
 | 
			
		||||
 | 
			
		||||
_CommonJS_
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
var fs = require("fs"), path = require("path");
 | 
			
		||||
var buf = XLSX.write(wb, { bookType: path.extname(filepath).slice(1), type: "buffer" });
 | 
			
		||||
fs.writeFileSync(filepath, buf);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
_ECMAScript Modules_
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import { write } from "xlsx";
 | 
			
		||||
import { writeFileSync } from "fs";
 | 
			
		||||
import { extname } from "path";
 | 
			
		||||
 | 
			
		||||
var buf = write(wb, { bookType: extname(filepath).slice(1), type: "buffer" });
 | 
			
		||||
writeFileSync(filepath, buf);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
### ExtendScript
 | 
			
		||||
 | 
			
		||||
In Photoshop and other Adobe apps, `readFile` and `writeFile` use the `File`
 | 
			
		||||
@ -390,6 +466,19 @@ var wb = XLSX.readFile("sheetjs.xlsx");
 | 
			
		||||
XLSX.writeFile(wb, "sheetjs.csv");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The [ExtendScript demo](/docs/demos/extensions/extendscript) covers the "Common
 | 
			
		||||
Extensibility Platform" (CEP) and "Unified Extensibility Platform" (UXP) details.
 | 
			
		||||
 | 
			
		||||
### Chrome Extensions
 | 
			
		||||
 | 
			
		||||
In Manifest v2 Chrome extensions, `writeFile` calls `chrome.downloads.download`.
 | 
			
		||||
 | 
			
		||||
This approach uses `URL.createObjectURL`, an API that is not supported in a
 | 
			
		||||
Manifest v3 Background Service Worker. For small exports, raw Base64 URLs can be
 | 
			
		||||
generated and downloaded.
 | 
			
		||||
 | 
			
		||||
The [Chromium demo](/docs/demos/extensions/chromium) covers the details.
 | 
			
		||||
 | 
			
		||||
### Deno
 | 
			
		||||
 | 
			
		||||
`readFile` uses `Deno.readFileSync` and `writeFile` uses `Deno.writeFileSync`:
 | 
			
		||||
@ -410,6 +499,34 @@ Any Deno script using `XLSX.writeFile` requires the `--allow-write` entitlement.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Implementation Details</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
**`XLSX.readFile(filepath)`** is equivalent to:
 | 
			
		||||
 | 
			
		||||
_ECMAScript Modules_
 | 
			
		||||
 | 
			
		||||
<CodeBlock language="ts">{`\
 | 
			
		||||
// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
 | 
			
		||||
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
 | 
			
		||||
\n\
 | 
			
		||||
const u8: Uint8Array = Deno.readFileSync(filepath);
 | 
			
		||||
const wb: XLSX.WorkBook = XLSX.read(u8);`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
**`XLSX.writeFile(wb, filepath)`** is equivalent to:
 | 
			
		||||
 | 
			
		||||
_ECMAScript Modules_
 | 
			
		||||
 | 
			
		||||
<CodeBlock language="ts">{`\
 | 
			
		||||
// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
 | 
			
		||||
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
 | 
			
		||||
\n\
 | 
			
		||||
const u8 = XLSX.write(wb, { bookType: filepath.slice(filepath.lastIndexOf(".")+1), type: "buffer" });
 | 
			
		||||
Deno.writeFileSync(filepath, u8);`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
### Bun
 | 
			
		||||
 | 
			
		||||
Bun requires the `fs` module:
 | 
			
		||||
@ -423,10 +540,11 @@ var wb = readFile("sheetjs.numbers");
 | 
			
		||||
writeFile(wb, "sheetjs.xlsx");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The implementation is identical to [NodeJS ECMAScript Modules](#nodejs).
 | 
			
		||||
 | 
			
		||||
### Apps
 | 
			
		||||
 | 
			
		||||
Desktop and mobile apps have their own specific APIs covered in separate demos:
 | 
			
		||||
 | 
			
		||||
- [Electron and other desktop apps](/docs/demos/desktop)
 | 
			
		||||
- [React Native and other mobile apps](/docs/demos/mobile)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										112
									
								
								docz/docs/03-demos/09-cloud/11-deno.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										112
									
								
								docz/docs/03-demos/09-cloud/11-deno.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
			
		||||
---
 | 
			
		||||
title: Deno Deploy
 | 
			
		||||
pagination_prev: demos/local/index
 | 
			
		||||
pagination_next: demos/extensions/index
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
import current from '/version.js';
 | 
			
		||||
import CodeBlock from '@theme/CodeBlock';
 | 
			
		||||
 | 
			
		||||
Deno Deploy offers "Serverless Functions" powered by Deno.
 | 
			
		||||
 | 
			
		||||
The [Deno installation](/docs/getting-started/installation/deno) instructions
 | 
			
		||||
apply to Deno Deploy scripts.
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
 | 
			
		||||
Deno Deploy does not offer any sort of temporary file access in functions.
 | 
			
		||||
 | 
			
		||||
This breaks web frameworks that use the filesystem in body parsing.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
When the demo was last tested, Deno Deploy required a GitHub account.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## Supported Frameworks
 | 
			
		||||
 | 
			
		||||
When the demo was last tested, the `drash` server framework used an in-memory
 | 
			
		||||
approach for parsing POST request bodies.
 | 
			
		||||
 | 
			
		||||
### Parsing Data
 | 
			
		||||
 | 
			
		||||
When files are submitted via HTTP POST, the `bodyParam` method can fetch data.
 | 
			
		||||
The `content` property of the returned object can be parsed with `XLSX.read`.
 | 
			
		||||
 | 
			
		||||
The following example assumes the file is submitted at field name `file`:
 | 
			
		||||
 | 
			
		||||
<CodeBlock language="ts">{`\
 | 
			
		||||
// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
 | 
			
		||||
import { read, utils } from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
 | 
			
		||||
import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts";
 | 
			
		||||
\n\
 | 
			
		||||
class SheetJSResource extends Drash.Resource {
 | 
			
		||||
  public paths = ["/"];
 | 
			
		||||
\n\
 | 
			
		||||
  public POST(request: Drash.Request, response: Drash.Response) {
 | 
			
		||||
    // highlight-start
 | 
			
		||||
    /* get data from body */
 | 
			
		||||
    const file = request.bodyParam<Drash.Types.BodyFile>("file");
 | 
			
		||||
    /* parse */
 | 
			
		||||
    var wb = read(file.content, {type: "buffer", dense: true});
 | 
			
		||||
    // highlight-end
 | 
			
		||||
    /* generate HTML from first worksheet */
 | 
			
		||||
    return response.html(utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]));
 | 
			
		||||
  }
 | 
			
		||||
}`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
## Demo
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2023 June 05. The service <https://s2c.sheetjs.com>
 | 
			
		||||
was implemented using this exact sequence.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
1) Register and Sign in.
 | 
			
		||||
 | 
			
		||||
2) Click "New Project" to create a new Project. In the next screen, look for the
 | 
			
		||||
"Hello World" sample and click the corresponding "Fork" button.
 | 
			
		||||
 | 
			
		||||
3) Download [`s2c.ts`](pathname:///deno/s2c.ts).  Open with a text editor and
 | 
			
		||||
copy the contents into the playground editor (left pane).
 | 
			
		||||
 | 
			
		||||
4) Click "Save and Deploy".
 | 
			
		||||
 | 
			
		||||
### Testing
 | 
			
		||||
 | 
			
		||||
5) Download the test file <https://sheetjs.com/pres.xlsx>
 | 
			
		||||
 | 
			
		||||
6) In the browser window, click "Choose File" and select the downloaded file.
 | 
			
		||||
Click "Submit" and the page will show the contents in a HTML TABLE.
 | 
			
		||||
 | 
			
		||||
7) Click the "Fullscreen" icon in the top-right corner of the page window.
 | 
			
		||||
 | 
			
		||||
8) Open a terminal window and download <https://sheetjs.com/pres.numbers>:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -LO https://sheetjs.com/pres.numbers
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
9) Copy the first `curl` line from the page and run in the terminal. For
 | 
			
		||||
example, if the deployment is `clean-badger-69`, the command would be
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -X POST -F"file=@pres.numbers" https://clean-badger-69.deno.dev/
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The output will be an HTML table
 | 
			
		||||
 | 
			
		||||
10) Copy the second `curl` line from the page and run in the terminal. For
 | 
			
		||||
example, if the deployment is `clean-badger-69`, the command would be
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
curl -X POST -F"file=@pres.numbers" -F"type=csv" https://clean-badger-69.deno.dev/
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The output will be CSV.
 | 
			
		||||
@ -15,9 +15,11 @@ support.  Over the years there have been a few different JavaScript platforms:
 | 
			
		||||
- "ExtendScript": This uses an old JavaScript dialect but is supported in older
 | 
			
		||||
  versions of Creative Suite and Creative Cloud.
 | 
			
		||||
 | 
			
		||||
- "CEP": This was recommended in CS6 but eventually deprecated.
 | 
			
		||||
- "Common Extensibility Platform" (CEP): This was introduced in Creative Suite.
 | 
			
		||||
  App automation uses ExtendScript, but integration logic uses modern JS.
 | 
			
		||||
 | 
			
		||||
- "UXP": This is the current Adobe recommendation for new CC extensions.
 | 
			
		||||
- "Unified Extensibility Platform" (UXP): This is the current recommendation for
 | 
			
		||||
  new Adobe CC extensions in supported apps (Photoshop 2021+ and InDesign 2022+)
 | 
			
		||||
 | 
			
		||||
This demo intends to cover parts relevant to SheetJS.  General setup as well as
 | 
			
		||||
general Adobe considerations are not covered here.  A basic familiarity with
 | 
			
		||||
 | 
			
		||||
@ -4,39 +4,88 @@ pagination_prev: demos/cloud/index
 | 
			
		||||
pagination_next: demos/bigdata/index
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was written using the Manifest V2 extension platform.  Chrome Web
 | 
			
		||||
Store will not accept new V2 extensions, but these can be sideloaded using the
 | 
			
		||||
"Load unpacked" extension option.
 | 
			
		||||
This demo showcases Manifest V2 and Manifest V3 extensions. Chrome Web Store
 | 
			
		||||
will not accept new V2 extensions, but these can be sideloaded using the
 | 
			
		||||
"Load unpacked" extension option in Developer mode.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
This library is compatible with Chrome and Chromium extensions and should just
 | 
			
		||||
work out of the box.  Specific API support is listed in the Chrome extensions
 | 
			
		||||
API documentation.
 | 
			
		||||
The [Standalone scripts](/docs/getting-started/installation/standalone) can be
 | 
			
		||||
integrated in a Chromium extension.
 | 
			
		||||
 | 
			
		||||
[Right-Click and download the final CRX](pathname:///chromium/SheetJSDemo.crx)
 | 
			
		||||
This demo includes examples for exporting bookmarks from a popup and scraping
 | 
			
		||||
tables with a content script and a background script.
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
[The demo](#demo) includes unpacked extensions for Manifest V2 and Manifest V3.
 | 
			
		||||
 | 
			
		||||
New releases of Chrome / Chromium will block with `CRX_REQUIRED_PROOF_MISSING`.
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
To try the extension:
 | 
			
		||||
 | 
			
		||||
1) Right-click and select "Save Link As ..." to save the CRX file
 | 
			
		||||
 | 
			
		||||
2) Open `chrome://extensions/` in the browser and enable Developer mode
 | 
			
		||||
 | 
			
		||||
3) Click and drag the downloaded CRX file into the Extensions page to install.
 | 
			
		||||
This demo was last tested on 2023 June 06 against Chrome 114
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## Loading SheetJS Scripts
 | 
			
		||||
 | 
			
		||||
SheetJS libraries should be bundled in the extension. For path purposes, it is
 | 
			
		||||
strongly recommended to place `xlsx.full.min.js` in the root folder.
 | 
			
		||||
 | 
			
		||||
#### Popup Pages
 | 
			
		||||
 | 
			
		||||
In Manifest V2 and Manifest V3 extensions, popup pages can load the standalone
 | 
			
		||||
script using a normal `<script>` tag:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<script type="text/javascript" src="xlsx.full.min.js"></script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Content Scripts
 | 
			
		||||
 | 
			
		||||
In Manifest V2 and Manifest V3 extensions, the standalone script can be loaded
 | 
			
		||||
through the `content_scripts` field:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
  /* in manifest.json v2 or v3 */
 | 
			
		||||
  "content_scripts": [{
 | 
			
		||||
    "matches": ["<all_urls>"],
 | 
			
		||||
    "js": ["xlsx.full.min.js", "content.js"],
 | 
			
		||||
    "run_at": "document_end"
 | 
			
		||||
  }],
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `XLSX` global will be visible to other content scripts.
 | 
			
		||||
 | 
			
		||||
#### Background Scripts
 | 
			
		||||
 | 
			
		||||
In Manifest V2 extensions, if the standalone script is added as a background
 | 
			
		||||
script, other background scripts will be able to access the `XLSX` global!
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
  /* in manifest.json v2 only! */
 | 
			
		||||
  "background": {
 | 
			
		||||
    "scripts": ["xlsx.full.min.js", "table.js"],
 | 
			
		||||
    "persistent": false
 | 
			
		||||
  },
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In Manifest V3 extensions, background service workers can load the standalone
 | 
			
		||||
script through `importScripts`:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* assuming background script is in the same folder as xlsx.full.min.js */
 | 
			
		||||
importScripts("./xlsx.full.min.js");
 | 
			
		||||
// now XLSX will be available
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Relevant Operations
 | 
			
		||||
 | 
			
		||||
The official documentation covers details including required permissions.
 | 
			
		||||
 | 
			
		||||
### Generating Downloads
 | 
			
		||||
 | 
			
		||||
#### Manifest V2
 | 
			
		||||
 | 
			
		||||
The `writeFile` function works in a Chrome or Chromium extension:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
@ -46,6 +95,21 @@ XLSX.writeFile(wb, "export.xlsx");
 | 
			
		||||
Under the hood, it uses the `chrome.downloads` API.  `"downloads"` permission
 | 
			
		||||
should be set in `manifest.json`.
 | 
			
		||||
 | 
			
		||||
#### Manifest V3
 | 
			
		||||
 | 
			
		||||
In a background service worker, `URL.createObjectURL` is unavailable. Instead,
 | 
			
		||||
`XLSX.write` can generate a Base64 string for a synthetic URL:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* generate Base64 string */
 | 
			
		||||
const b64 = XLSX.write(wb, {bookType: "xlsx", type: "base64"});
 | 
			
		||||
chrome.downloads.download({
 | 
			
		||||
  /* make a base64 url manually */
 | 
			
		||||
  url: `data:application/octet-stream;base64,${b64}`,
 | 
			
		||||
  filename: `SheetJSTables.xlsx`
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Content Script Table Scraping
 | 
			
		||||
 | 
			
		||||
`table_to_book` and `table_to_sheet` can help build workbooks from DOM tables:
 | 
			
		||||
@ -64,24 +128,50 @@ for(var i = 0; i < tables.length; ++i) {
 | 
			
		||||
The demo extension includes multiple features to demonstrate sample usage.
 | 
			
		||||
Production extensions should include proper error handling.
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Testing Unpacked Extension</b> (click to show)</summary>
 | 
			
		||||
<details open><summary><b>Testing Unpacked Extension</b> (click to hide)</summary>
 | 
			
		||||
 | 
			
		||||
1) [Right-Click and download the zip](pathname:///chromium/SheetJSChromiumUnpacked.zip)
 | 
			
		||||
1) Download the zip for the desired Manifest version:
 | 
			
		||||
 | 
			
		||||
2) Create a `SheetJSChromium` folder in your Downloads directory, move the zip
 | 
			
		||||
   file into the folder, and extract the zip file.
 | 
			
		||||
- [Manifest V2](pathname:///chromium/SheetJSChromiumUnpackedV2.zip)
 | 
			
		||||
- [Manifest V3](pathname:///chromium/SheetJSChromiumUnpackedV3.zip)
 | 
			
		||||
 | 
			
		||||
3) Open `chrome://extensions/` in the browser and enable Developer mode
 | 
			
		||||
2) Open `chrome://extensions/` in the browser and enable Developer mode
 | 
			
		||||
 | 
			
		||||
4) Click "Load Unpacked" and select the `SheetJSChromium` folder.
 | 
			
		||||
3) Drag and drop the downloaded zip file into the window.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
### Bookmark Exporter
 | 
			
		||||
 | 
			
		||||
<details open><summary><b>Testing</b> (click to hide)</summary>
 | 
			
		||||
 | 
			
		||||
0) Go to <https://sheetjs.com> and create a bookmark in the browser.
 | 
			
		||||
 | 
			
		||||
1) Click the Extensions icon (puzzle icon to the right of the address bar) and
 | 
			
		||||
select "SheetJS Demo".
 | 
			
		||||
 | 
			
		||||
2) If a small popup is not displayed, click on the SheetJS icon
 | 
			
		||||
 | 
			
		||||
3) Click "Export Bookmarks" and click "Save". Open the downloaded file!
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
```mermaid
 | 
			
		||||
sequenceDiagram
 | 
			
		||||
  actor U as User
 | 
			
		||||
  participant P as Popup
 | 
			
		||||
  participant A as Chromium
 | 
			
		||||
  U->>P: click icon
 | 
			
		||||
  P->>A: `chrome.bookmarks.getTree`
 | 
			
		||||
  A->>P: bookmark tree
 | 
			
		||||
  Note over P: walk tree
 | 
			
		||||
  Note over P: make workbook
 | 
			
		||||
  P->>U: `XLSX.writeFile`
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`chrome.bookmarks` API enables bookmark tree traversal.  The "Export Bookmarks"
 | 
			
		||||
button in the extension pop-up recursively walks the bookmark tree, pushes the
 | 
			
		||||
bookmark URLs into a data array, and exports into a simple spreadsheet:
 | 
			
		||||
bookmark URLs into a data array, and exports into a simple spreadsheet.
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* walk the bookmark tree */
 | 
			
		||||
@ -108,17 +198,57 @@ chrome.bookmarks.getTree(function(res) {
 | 
			
		||||
 | 
			
		||||
### Table Exporter
 | 
			
		||||
 | 
			
		||||
The `content.js` content script converts a table in the DOM to workbook object
 | 
			
		||||
using the `table_to_book` utility function:
 | 
			
		||||
<details open><summary><b>Testing</b> (click to hide)</summary>
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
// event page script trigger
 | 
			
		||||
chrome.tabs.sendMessage(tab.id);
 | 
			
		||||
// content script convert
 | 
			
		||||
var wb = XLSX.utils.table_to_book(elt);
 | 
			
		||||
// event page script callback
 | 
			
		||||
XLSX.writeFile(wb, "export.xlsx");
 | 
			
		||||
1) Go to <https://sheetjs.com/demo/table>
 | 
			
		||||
 | 
			
		||||
2) Right-click anywhere in the page and select "SheetJS Demo" > "Export All Tables in Page"
 | 
			
		||||
 | 
			
		||||
3) Save and open the downloaded file!
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
The background script configures a context menu with the option to export data.
 | 
			
		||||
The flow diagrams show the data flow when the user chooses to export. They
 | 
			
		||||
differ in the denouement
 | 
			
		||||
 | 
			
		||||
```mermaid
 | 
			
		||||
sequenceDiagram
 | 
			
		||||
  actor U as User
 | 
			
		||||
  participant P as Background Script
 | 
			
		||||
  participant A as Content Script
 | 
			
		||||
  U->>P: Context Click > "Export"
 | 
			
		||||
  Note over P: Query for active tab
 | 
			
		||||
  P->>A: Ask active tab for data
 | 
			
		||||
  Note over A: `table_to_sheet`
 | 
			
		||||
  Note over A: generate workbook
 | 
			
		||||
  A->>P: workbook object
 | 
			
		||||
  Note over U,A: ... different denouement for Manifest V2 / V3 extensions ...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Since the workbook object is a plain JS object, the object is sent back to an
 | 
			
		||||
event page script which generates the file and attempts a download.
 | 
			
		||||
#### Manifest V2
 | 
			
		||||
 | 
			
		||||
For Manifest V2 extensions, `XLSX.writeFile` just works:
 | 
			
		||||
 | 
			
		||||
```mermaid
 | 
			
		||||
sequenceDiagram
 | 
			
		||||
  actor U as User
 | 
			
		||||
  participant P as Background Script
 | 
			
		||||
  Note over P,U: ... background script received workbook ...
 | 
			
		||||
  P->>U: `XLSX.writeFile` download
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Manifest V3
 | 
			
		||||
 | 
			
		||||
For Manifest V3 extensions, since `URL.createObjectURL` is not available in
 | 
			
		||||
background service workers, a synthetic URL is created:
 | 
			
		||||
 | 
			
		||||
```mermaid
 | 
			
		||||
sequenceDiagram
 | 
			
		||||
  actor U as User
 | 
			
		||||
  participant P as Background Script
 | 
			
		||||
  Note over P,U: ... background script received workbook ...
 | 
			
		||||
  Note over P: `XLSX.write` Base64
 | 
			
		||||
  Note over P: Create Data URL
 | 
			
		||||
  P->>U: `chrome.downloads.download`
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								docz/static/chromium/SheetJSChromiumUnpackedV3.zip
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/chromium/SheetJSChromiumUnpackedV3.zip
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										118
									
								
								docz/static/deno/s2c.ts
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										118
									
								
								docz/static/deno/s2c.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,118 @@
 | 
			
		||||
// @deno-types="https://cdn.sheetjs.com/xlsx-0.19.3/package/types/index.d.ts"
 | 
			
		||||
import { read, utils, set_cptable, version } from 'https://cdn.sheetjs.com/xlsx-0.19.3/package/xlsx.mjs';
 | 
			
		||||
import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.19.3/package/dist/cpexcel.full.mjs';
 | 
			
		||||
set_cptable(cptable);
 | 
			
		||||
 | 
			
		||||
import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts";
 | 
			
		||||
 | 
			
		||||
class SheetJSResource extends Drash.Resource {
 | 
			
		||||
  public paths = ["/"];
 | 
			
		||||
 | 
			
		||||
  public OPTIONS(request: Drash.Request, response: Drash.Response) {
 | 
			
		||||
    const allHttpMethods: string[] = [ "GET", "POST", "PUT", "DELETE" ];
 | 
			
		||||
    response.headers.set("Allow", allHttpMethods.join());
 | 
			
		||||
    response.headers.set("Access-Control-Allow-Methods", allHttpMethods.join());
 | 
			
		||||
    response.headers.set("access-control-allow-origin", "*");
 | 
			
		||||
    response.status_code = 204;
 | 
			
		||||
    return response;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public POST(request: Drash.Request, response: Drash.Response) {
 | 
			
		||||
    const file = request.bodyParam<Drash.Types.BodyFile>("file");
 | 
			
		||||
    const type = request.bodyParam<string>("type");
 | 
			
		||||
    try { response.headers.set("access-control-allow-origin", "*"); } catch(e) {}
 | 
			
		||||
    if (!file) throw new Error("File is required!");
 | 
			
		||||
    var wb = read(file.content, {type: "buffer", dense: true});
 | 
			
		||||
    return response.html( (type == "csv" ? utils.sheet_to_csv : utils.sheet_to_html)(wb.Sheets[wb.SheetNames[0]]));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public GET(request: Drash.Request, response: Drash.Response): void {
 | 
			
		||||
    try { response.headers.set("access-control-allow-origin", "*"); } catch(e) {}
 | 
			
		||||
    return response.html(`\
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <title>SheetJS Spreadsheet to HTML Conversion Service</title>
 | 
			
		||||
    <meta charset="utf-8" />
 | 
			
		||||
<style>
 | 
			
		||||
* {
 | 
			
		||||
	padding: 0;
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html, body {
 | 
			
		||||
	width: 100vw;
 | 
			
		||||
	max-width: 100%;
 | 
			
		||||
	font-size: 16px;
 | 
			
		||||
	font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
 | 
			
		||||
	-webkit-font-smoothing: antialiased;
 | 
			
		||||
	background: white;
 | 
			
		||||
	color: black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
	padding-top: 5px;
 | 
			
		||||
  max-width: 760px;
 | 
			
		||||
  margin-left: auto;
 | 
			
		||||
  margin-right: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
table {
 | 
			
		||||
  border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
table, tr, th, td { border: 1px solid; }
 | 
			
		||||
div {
 | 
			
		||||
  padding: 5px;
 | 
			
		||||
}
 | 
			
		||||
li { margin: 5px 0;}
 | 
			
		||||
</style>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
<h2><a href="//sheetjs.com/">SheetJS</a> Spreadsheet Conversion Service</h2>
 | 
			
		||||
<br/>
 | 
			
		||||
<h3>API</h3>
 | 
			
		||||
<br/>
 | 
			
		||||
Send a <code>POST</code> request to <a id="u">https://s2c.sheetjs.com</a> with the file in the <code>file</code> body parameter:<br/>
 | 
			
		||||
<br/>
 | 
			
		||||
<pre>
 | 
			
		||||
    curl -X POST -F"file=@pres.numbers" <span id="v">https://s2c.sheetjs.com/</span>
 | 
			
		||||
</pre>
 | 
			
		||||
<br/>
 | 
			
		||||
The response will be an HTML TABLE generated from the first worksheet.
 | 
			
		||||
<br/><br/>
 | 
			
		||||
For CSV data, pass the parameter <code>type=csv</code>:<br/>
 | 
			
		||||
<br/>
 | 
			
		||||
<pre>
 | 
			
		||||
    curl -X POST -F"file=@pres.numbers" -F"type=csv" <span id="w">https://s2c.sheetjs.com/</span>
 | 
			
		||||
</pre>
 | 
			
		||||
<br/><br/>
 | 
			
		||||
<h3>Try it out!</h3>
 | 
			
		||||
<br/>
 | 
			
		||||
<form action="/" method="post" enctype="multipart/form-data">
 | 
			
		||||
<input type="file" name="file" /><br/><br/>
 | 
			
		||||
Use the file input element to select a file, then click "Submit"<br/><br/>
 | 
			
		||||
<button type="submit">Submit</button><br/><br/>
 | 
			
		||||
</form>
 | 
			
		||||
 | 
			
		||||
SheetJS Library Version: <code>${version}</code>
 | 
			
		||||
  </body>
 | 
			
		||||
  <script>w.innerHTML = v.innerHTML = u.innerHTML = u.href = window.location;</script>
 | 
			
		||||
</html>`,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const server = new Drash.Server({
 | 
			
		||||
  hostname: "",
 | 
			
		||||
  port: 3000,
 | 
			
		||||
  protocol: "http",
 | 
			
		||||
  resources: [
 | 
			
		||||
    SheetJSResource,
 | 
			
		||||
  ],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
server.run();
 | 
			
		||||
 | 
			
		||||
console.log(`Server running at ${server.address}.`);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user