diff --git a/docz/docs/02-getting-started/01-installation/02-frameworks.md b/docz/docs/02-getting-started/01-installation/02-frameworks.md
index e5b7f6e..4504fb0 100644
--- a/docz/docs/02-getting-started/01-installation/02-frameworks.md
+++ b/docz/docs/02-getting-started/01-installation/02-frameworks.md
@@ -57,19 +57,19 @@ For existing projects, the easiest approach is to uninstall and reinstall:
{`\
npm rm --save xlsx
-npm i --save file:vendor/xlsx-${current}.tgz`}
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
pnpm rm xlsx
-pnpm install file:vendor/xlsx-${current}.tgz`}
+pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
{`\
yarn remove xlsx
-yarn add file:vendor/xlsx-${current}.tgz`}
+yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
diff --git a/docz/docs/03-demos/02-extendscript.md b/docz/docs/03-demos/02-extendscript.md
index ec94a84..0397d29 100644
--- a/docz/docs/03-demos/02-extendscript.md
+++ b/docz/docs/03-demos/02-extendscript.md
@@ -167,7 +167,7 @@ and place in the scripts directory. For CS6 Windows 10 the path is typically
3) File > File Info ... and confirm there is an Author. If not, set to `SheetJS`
4) File > Scripts > write and use the popup to select the Documents folder.
- Enter `SheetJSPSTest.xlsx` and hit "Save"
+ Enter `SheetJSPSTest.xlsx` and press "Save"
4) An alert will confirm that the file was created:
diff --git a/docz/docs/03-demos/10-excel.md b/docz/docs/03-demos/10-excel.md
index 3aef9c6..c8dc851 100644
--- a/docz/docs/03-demos/10-excel.md
+++ b/docz/docs/03-demos/10-excel.md
@@ -239,7 +239,7 @@ async function extern() {
After making the change, save the files. Close the terminal window and the
Excel window (do not save the Excel file). Re-run `npm start`.
-Enter the formula `=SHEETJS.EXTERN()` in cell D1 and hit Enter. Excel should
+Enter the formula `=SHEETJS.EXTERN()` in cell D1 and press Enter. Excel should
pull in the data and generate a dynamic array:

diff --git a/docz/docs/03-demos/19-mobile.md b/docz/docs/03-demos/19-mobile.md
index 5d6f3d4..227de2d 100644
--- a/docz/docs/03-demos/19-mobile.md
+++ b/docz/docs/03-demos/19-mobile.md
@@ -132,7 +132,7 @@ selecting the terminal and entering the key sequence `CTRL + C`
3) From the project folder, install the library:
```bash
-npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
+npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
```
4) To confirm the library was loaded, change the title to show the version. The
@@ -375,3 +375,369 @@ id,name,role

+
+## Quasar
+
+:::note
+
+This demo was tested on an Intel Mac on 2022 August 14. Quasar version `2.7.7`.
+The iOS simulator runs iOS 15.5 on an iPhone SE 3rd generation.
+
+:::
+
+This demo will focus on VueJS and Cordova with the Quasar Vite starter project.
+
+### Integration Details
+
+The complete solution uses `cordova-plugin-file` for file operations. It can
+be installed like any other Cordova plugin:
+
+```bash
+cd src-cordova
+cordova plugin add cordova-plugin-file
+cd ..
+```
+
+#### Reading data
+
+The `q-file` component presents an API reminiscent of File Input elements:
+
+```html
+
+```
+
+When binding to the `input` element, the callback receives an `Event` object:
+
+```ts
+import { read } from 'xlsx';
+
+// assuming `todos` is a standard VueJS `ref`
+async function updateFile(v) { try {
+ // `v.target.files[0]` is the desired file object
+ const files = (v.target as HTMLInputElement).files;
+ if(!files || files.length == 0) return;
+
+ // read first file
+ const wb = read(await files[0].arrayBuffer());
+
+ // get data of first worksheet as an array of objects
+ const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
+
+ // update state
+ todos.value = data.map(row => ({id: row.Index, content: row.Name}));
+
+} catch(e) { console.log(e); } }
+```
+
+#### Writing data
+
+The API is shaped like the File and Directory Entries API. For clarity, since
+the code is a "pyramid of doom", the error handlers are omitted:
+
+```ts
+import { write } from 'xlsx';
+
+// on iOS and android, `XLSX.write` with type "buffer" returns a `Uint8Array`
+const u8: Uint8Array = write(wb, {bookType: "xlsx", type: "buffer"});
+// Request filesystem access for persistent storage
+window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
+ // Request a handle to "SheetJSQuasar.xlsx", making a new file if necessary
+ fs.root.getFile("SheetJSQuasar.xlsx", {create: true}, entry => {
+ // Request a FileWriter for writing data
+ entry.createWriter(writer => {
+ // The FileWriter API needs an actual Blob
+ const data = new Blob([u8], {type: "application/vnd.ms-excel"});
+ // This callback is called if the write is successful
+ writer.onwriteend = () => {
+ // TODO: show a dialog
+ };
+ // writer.onerror will be invoked if there is an error in writing
+
+ // write the data
+ writer.write(data);
+ });
+ });
+});
+```
+
+### Demo
+
+The demo builds off of the Vite example. Familiarity with VueJS and TypeScript
+is assumed.
+
+Complete Example (click to show)
+
+0) Ensure all of the dependencies are installed. Install the CLI globally:
+
+```bash
+npm i -g @quasar/cli cordova
+```
+
+(you may need to run `sudo npm i -g` if there are permission issues)
+
+1) Create a new app:
+
+```bash
+npm init quasar
+```
+
+When prompted:
+
+- "What would you like to build?": `App with Quasar CLI`
+- "Project folder": `SheetJSQuasar`
+- "Pick Quasar version": `Quasar v2 (Vue 3 | latest and greatest)`
+- "Pick script type": `Typescript`
+- "Pick Quasar App CLI variant": `Quasar App CLI with Vite`
+- "Package name": (just press enter, it will use the default `sheetjsquasar`
+- "Project product name": `SheetJSQuasar`
+- "Project description": `SheetJS + Quasar`
+- "Author": (just press enter, it will use your git config settings)
+- "Pick a Vue component style": `Composition API`
+- "Pick your CSS preprocessor": `None`
+- "Check the features needed for your project": Deselect everything
+- "Install project dependencies": `No`
+
+2) Install dependencies:
+
+```bash
+cd SheetJSQuasar
+npm i
+npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
+```
+
+3) Set up Cordova:
+
+```bash
+quasar mode add cordova
+```
+
+When prompted, enter the app id `org.sheetjs.quasar`.
+
+It will create a new `src-cordova` folder. Continue in that folder:
+
+```bash
+cd src-cordova
+cordova platform add ios
+cordova plugin add cordova-plugin-wkwebview-engine
+cordova plugin add cordova-plugin-file
+```
+
+:::note
+
+If there is an error `Could not load API for iOS project`, it needs to be reset:
+
+```bash
+cordova platform rm ios
+cordova platform add ios
+cordova plugin add cordova-plugin-file
+```
+
+:::
+
+Return to the project directory:
+
+```bash
+cd ..
+```
+
+4) Start the dev server:
+
+```bash
+quasar dev -m ios
+```
+
+:::caution
+
+If the app is blank, delete the app and close the simulator, then restart dev
+
+:::
+
+
+
+
+5) Add the Dialog plugin to `quasar.config.js`:
+
+```js title="quasar.config.js"
+ // Quasar plugins
+ // highlight-next-line
+ plugins: ['Dialog']
+```
+
+6) In the template section of `src/pages/IndexPage.vue`, add a Save button and
+ a Load file picker component at the bottom of the page:
+
+```html title="src/pages/IndexPage.vue"
+
+
+
+
+
+
+
+
+```
+
+This uses two functions that should be added to the component script:
+
+```ts title="src/pages/IndexPage.vue"
+ const meta = ref({
+ totalCount: 1200
+ });
+// highlight-start
+ function saveFile() {
+ }
+ async function updateFile(v) {
+ }
+ return { todos, meta, saveFile, updateFile };
+// highlight-end
+ }
+});
+
+```
+
+The app should now show two buttons at the bottom:
+
+
+
+:::caution
+
+If the app is blank or not refreshing, delete the app and close the simulator,
+then restart the dev process.
+
+:::
+
+7) Wire up the `updateFile` function:
+
+```ts title="src/pages/IndexPage.vue"
+import { defineComponent, ref } from 'vue';
+// highlight-start
+import { read, write, utils } from 'xlsx';
+import { useQuasar } from 'quasar';
+// highlight-end
+
+export default defineComponent({
+// ...
+// highlight-start
+ const $q = useQuasar();
+ function dialogerr(e) { $q.dialog({title: "Error!", message: e.message || String(e)}); }
+// highlight-end
+ function saveFile() {
+ }
+ async function updateFile(v) {
+// highlight-start
+ try {
+ const files = (v.target as HTMLInputElement).files;
+ if(!files || files.length == 0) return;
+
+ const wb = read(await files[0].arrayBuffer());
+
+ const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
+ todos.value = data.map(row => ({id: row.Index, content: row.Name}));
+ } catch(e) { dialogerr(e); }
+// highlight-end
+ }
+```
+
+To test that reading works:
+
+- Download
+- In the simulator, click the Home icon to return to the home screen
+- Click on the "Files" icon
+- Click and drag `pres.numbers` from a Finder window into the simulator.
+
+
+
+- Make sure "On My iPhone" is highlighted and select "Save"
+- Click the Home icon again then select the SheetJSQuasar app
+- Click the "Load" button, then select "Choose File" and select `pres`:
+
+
+
+Once selected, the screen should refresh with new contents:
+
+
+
+8) Wire up the `saveFile` function:
+
+```js
+ function saveFile() {
+// highlight-start
+ /* generate workbook from state */
+ const ws = utils.json_to_sheet(todos.value);
+ const wb = utils.book_new();
+ utils.book_append_sheet(wb, ws, "SheetJSQuasar");
+ const u8: Uint8Array = write(wb, {bookType: "xlsx", type: "buffer"});
+
+ /* save to file */
+ window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
+ try {
+ fs.root.getFile("SheetJSQuasar.xlsx", {create: true}, entry => {
+ const msg = `File stored at ${$q.cordova.file.documentsDirectory} ${entry.fullPath}`;
+ entry.createWriter(writer => {
+ try {
+ const data = new Blob([u8], {type: "application/vnd.ms-excel"});
+ writer.onwriteend = () => {
+ try {
+ $q.dialog({title: "Success!", message: msg});
+ } catch(e) { dialogerr(e); }
+ };
+ writer.onerror = dialogerr;
+ writer.write(data);
+ } catch(e) { dialogerr(e); }
+ }, dialogerr);
+ }, dialogerr);
+ } catch(e) { dialogerr(e) }
+ }, dialogerr);
+// highlight-end
+ }
+```
+
+The page should revert to the old contents.
+
+To test that writing works:
+
+- Click "Save File". You will see a popup with a location:
+
+
+
+- Find the file and verify the contents are correct. Run in a new terminal:
+
+```bash
+find ~/Library/Developer/CoreSimulator -name SheetJSQuasar.xlsx |
+ while read x; do echo "$x"; npx xlsx-cli "$x"; done
+```
+
+Since the contents reverted, you should see
+
+```
+SheetJSQuasar
+id,content
+1,ct1
+2,ct2
+3,ct3
+4,ct4
+5,ct5
+```
+
+- Use "Load File" to select `pres.numbers` again. Wait for the app to refresh.
+
+- Click "Save File", then re-run the command:
+
+```bash
+find ~/Library/Developer/CoreSimulator -name SheetJSQuasar.xlsx |
+ while read x; do echo "$x"; npx xlsx-cli "$x"; done
+```
+
+The contents from `pres.numbers` should show up now, with a new header row:
+
+```
+SheetJSQuasar
+id,content
+42,Bill Clinton
+43,GeorgeW Bush
+44,Barack Obama
+45,Donald Trump
+46,Joseph Biden
+```
+
+
diff --git a/docz/docs/03-demos/20-content.md b/docz/docs/03-demos/20-content.md
index c37309e..64f91f8 100644
--- a/docz/docs/03-demos/20-content.md
+++ b/docz/docs/03-demos/20-content.md
@@ -115,17 +115,17 @@ npx create-nuxt-app SheetJSNuxt
When prompted, enter the following options:
-- `Project name`: hit Enter (use default SheetJSNuxt)
-- `Programming language`: hit Down Arrow (`TypeScript` selected) and hit Enter
-- `Package manager`: select `Npm` and hit Enter
-- `UI framework`: select `None` and hit Enter
-- `Nuxt.js modules`: scroll to `Content`, select with Space, then hit Enter
-- `Linting tools`: hit Enter (do not select any Linting tools)
-- `Testing framework`: select `None` and hit Enter
-- `Rendering mode`: select `Universal (SSR / SSG)` and hit Enter
-- `Deployment target`: select `Static (Static/Jamstack hosting)` and hit Enter
-- `Development tools`: hit Enter (do not select any Development tools)
-- `What is your GitHub username?`: hit Enter
+- `Project name`: press Enter (use default SheetJSNuxt)
+- `Programming language`: press Down Arrow (`TypeScript` selected) then Enter
+- `Package manager`: select `Npm` and press Enter
+- `UI framework`: select `None` and press Enter
+- `Nuxt.js modules`: scroll to `Content`, select with Space, then press Enter
+- `Linting tools`: press Enter (do not select any Linting tools)
+- `Testing framework`: select `None` and press Enter
+- `Rendering mode`: select `Universal (SSR / SSG)` and press Enter
+- `Deployment target`: select `Static (Static/Jamstack hosting)` and press Enter
+- `Development tools`: press Enter (do not select any Development tools)
+- `What is your GitHub username?`: press Enter
- `Version control system`: select `None`
The project will be configured and modules will be installed.
@@ -179,7 +179,7 @@ export default {
```
The browser should refresh to show the contents of the spreadsheet. If it does
-not, hit Refresh manually or open a new browser window.
+not, click Refresh manually or open a new browser window.

@@ -198,7 +198,7 @@ The page should automatically refresh with the new content:

-7) Stop the dev server (hit `CTRL+C` in the terminal window) and run
+7) Stop the dev server (press `CTRL+C` in the terminal window) and run
```bash
npm run generate
diff --git a/docz/docs/03-demos/index.md b/docz/docs/03-demos/index.md
index 0238b67..74abc46 100644
--- a/docz/docs/03-demos/index.md
+++ b/docz/docs/03-demos/index.md
@@ -22,7 +22,7 @@ The demo projects include small runnable examples and short explainers.
- [`Angular 2+ and Ionic`](https://github.com/SheetJS/SheetJS/tree/master/demos/angular2/)
- [`Knockout`](./legacy#knockout)
- [`React, React Native and NextJS`](https://github.com/SheetJS/SheetJS/tree/master/demos/react/)
-- [`VueJS, WeeX, and NuxtJS`](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/)
+- [`VueJS`](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/)
### Front-End UI Components
diff --git a/docz/static/mobile/quasar4.png b/docz/static/mobile/quasar4.png
new file mode 100644
index 0000000..94269b2
Binary files /dev/null and b/docz/static/mobile/quasar4.png differ
diff --git a/docz/static/mobile/quasar6.png b/docz/static/mobile/quasar6.png
new file mode 100644
index 0000000..611d54e
Binary files /dev/null and b/docz/static/mobile/quasar6.png differ
diff --git a/docz/static/mobile/quasar7a.png b/docz/static/mobile/quasar7a.png
new file mode 100644
index 0000000..d5e1bba
Binary files /dev/null and b/docz/static/mobile/quasar7a.png differ
diff --git a/docz/static/mobile/quasar7b.png b/docz/static/mobile/quasar7b.png
new file mode 100644
index 0000000..87a85bb
Binary files /dev/null and b/docz/static/mobile/quasar7b.png differ
diff --git a/docz/static/mobile/quasar7c.png b/docz/static/mobile/quasar7c.png
new file mode 100644
index 0000000..f1ed08d
Binary files /dev/null and b/docz/static/mobile/quasar7c.png differ
diff --git a/docz/static/mobile/quasar8.png b/docz/static/mobile/quasar8.png
new file mode 100644
index 0000000..728e96d
Binary files /dev/null and b/docz/static/mobile/quasar8.png differ